373 lines
12 KiB
Go
373 lines
12 KiB
Go
package vsphere
|
|
|
|
import (
|
|
"context"
|
|
"sync"
|
|
"time"
|
|
|
|
"github.com/influxdata/telegraf"
|
|
"github.com/influxdata/telegraf/internal"
|
|
"github.com/influxdata/telegraf/internal/tls"
|
|
"github.com/influxdata/telegraf/plugins/inputs"
|
|
"github.com/vmware/govmomi/vim25/soap"
|
|
)
|
|
|
|
// VSphere is the top level type for the vSphere input plugin. It contains all the configuration
|
|
// and a list of connected vSphere endpoints
|
|
type VSphere struct {
|
|
Vcenters []string
|
|
Username string
|
|
Password string
|
|
DatacenterInstances bool
|
|
DatacenterMetricInclude []string
|
|
DatacenterMetricExclude []string
|
|
DatacenterInclude []string
|
|
DatacenterExclude []string
|
|
ClusterInstances bool
|
|
ClusterMetricInclude []string
|
|
ClusterMetricExclude []string
|
|
ClusterInclude []string
|
|
ClusterExclude []string
|
|
HostInstances bool
|
|
HostMetricInclude []string
|
|
HostMetricExclude []string
|
|
HostInclude []string
|
|
HostExclude []string
|
|
VMInstances bool `toml:"vm_instances"`
|
|
VMMetricInclude []string `toml:"vm_metric_include"`
|
|
VMMetricExclude []string `toml:"vm_metric_exclude"`
|
|
VMInclude []string `toml:"vm_include"`
|
|
VMExclude []string `toml:"vm_exclude"`
|
|
DatastoreInstances bool
|
|
DatastoreMetricInclude []string
|
|
DatastoreMetricExclude []string
|
|
DatastoreInclude []string
|
|
DatastoreExclude []string
|
|
Separator string
|
|
CustomAttributeInclude []string
|
|
CustomAttributeExclude []string
|
|
UseIntSamples bool
|
|
IpAddresses []string
|
|
|
|
MaxQueryObjects int
|
|
MaxQueryMetrics int
|
|
CollectConcurrency int
|
|
DiscoverConcurrency int
|
|
ForceDiscoverOnInit bool
|
|
ObjectDiscoveryInterval internal.Duration
|
|
Timeout internal.Duration
|
|
|
|
endpoints []*Endpoint
|
|
cancel context.CancelFunc
|
|
|
|
// Mix in the TLS/SSL goodness from core
|
|
tls.ClientConfig
|
|
|
|
Log telegraf.Logger
|
|
}
|
|
|
|
var sampleConfig = `
|
|
## List of vCenter URLs to be monitored. These three lines must be uncommented
|
|
## and edited for the plugin to work.
|
|
vcenters = [ "https://vcenter.local/sdk" ]
|
|
username = "user@corp.local"
|
|
password = "secret"
|
|
|
|
## VMs
|
|
## Typical VM metrics (if omitted or empty, all metrics are collected)
|
|
# vm_include = [ "/*/vm/**"] # Inventory path to VMs to collect (by default all are collected)
|
|
# vm_exclude = [] # Inventory paths to exclude
|
|
vm_metric_include = [
|
|
"cpu.demand.average",
|
|
"cpu.idle.summation",
|
|
"cpu.latency.average",
|
|
"cpu.readiness.average",
|
|
"cpu.ready.summation",
|
|
"cpu.run.summation",
|
|
"cpu.usagemhz.average",
|
|
"cpu.used.summation",
|
|
"cpu.wait.summation",
|
|
"mem.active.average",
|
|
"mem.granted.average",
|
|
"mem.latency.average",
|
|
"mem.swapin.average",
|
|
"mem.swapinRate.average",
|
|
"mem.swapout.average",
|
|
"mem.swapoutRate.average",
|
|
"mem.usage.average",
|
|
"mem.vmmemctl.average",
|
|
"net.bytesRx.average",
|
|
"net.bytesTx.average",
|
|
"net.droppedRx.summation",
|
|
"net.droppedTx.summation",
|
|
"net.usage.average",
|
|
"power.power.average",
|
|
"virtualDisk.numberReadAveraged.average",
|
|
"virtualDisk.numberWriteAveraged.average",
|
|
"virtualDisk.read.average",
|
|
"virtualDisk.readOIO.latest",
|
|
"virtualDisk.throughput.usage.average",
|
|
"virtualDisk.totalReadLatency.average",
|
|
"virtualDisk.totalWriteLatency.average",
|
|
"virtualDisk.write.average",
|
|
"virtualDisk.writeOIO.latest",
|
|
"sys.uptime.latest",
|
|
]
|
|
# vm_metric_exclude = [] ## Nothing is excluded by default
|
|
# vm_instances = true ## true by default
|
|
|
|
## Hosts
|
|
## Typical host metrics (if omitted or empty, all metrics are collected)
|
|
# host_include = [ "/*/host/**"] # Inventory path to hosts to collect (by default all are collected)
|
|
# host_exclude [] # Inventory paths to exclude
|
|
host_metric_include = [
|
|
"cpu.coreUtilization.average",
|
|
"cpu.costop.summation",
|
|
"cpu.demand.average",
|
|
"cpu.idle.summation",
|
|
"cpu.latency.average",
|
|
"cpu.readiness.average",
|
|
"cpu.ready.summation",
|
|
"cpu.swapwait.summation",
|
|
"cpu.usage.average",
|
|
"cpu.usagemhz.average",
|
|
"cpu.used.summation",
|
|
"cpu.utilization.average",
|
|
"cpu.wait.summation",
|
|
"disk.deviceReadLatency.average",
|
|
"disk.deviceWriteLatency.average",
|
|
"disk.kernelReadLatency.average",
|
|
"disk.kernelWriteLatency.average",
|
|
"disk.numberReadAveraged.average",
|
|
"disk.numberWriteAveraged.average",
|
|
"disk.read.average",
|
|
"disk.totalReadLatency.average",
|
|
"disk.totalWriteLatency.average",
|
|
"disk.write.average",
|
|
"mem.active.average",
|
|
"mem.latency.average",
|
|
"mem.state.latest",
|
|
"mem.swapin.average",
|
|
"mem.swapinRate.average",
|
|
"mem.swapout.average",
|
|
"mem.swapoutRate.average",
|
|
"mem.totalCapacity.average",
|
|
"mem.usage.average",
|
|
"mem.vmmemctl.average",
|
|
"net.bytesRx.average",
|
|
"net.bytesTx.average",
|
|
"net.droppedRx.summation",
|
|
"net.droppedTx.summation",
|
|
"net.errorsRx.summation",
|
|
"net.errorsTx.summation",
|
|
"net.usage.average",
|
|
"power.power.average",
|
|
"storageAdapter.numberReadAveraged.average",
|
|
"storageAdapter.numberWriteAveraged.average",
|
|
"storageAdapter.read.average",
|
|
"storageAdapter.write.average",
|
|
"sys.uptime.latest",
|
|
]
|
|
## Collect IP addresses? Valid values are "ipv4" and "ipv6"
|
|
# ip_addresses = ["ipv6", "ipv4" ]
|
|
|
|
# host_metric_exclude = [] ## Nothing excluded by default
|
|
# host_instances = true ## true by default
|
|
|
|
|
|
## Clusters
|
|
# cluster_include = [ "/*/host/**"] # Inventory path to clusters to collect (by default all are collected)
|
|
# cluster_exclude = [] # Inventory paths to exclude
|
|
# cluster_metric_include = [] ## if omitted or empty, all metrics are collected
|
|
# cluster_metric_exclude = [] ## Nothing excluded by default
|
|
# cluster_instances = false ## false by default
|
|
|
|
## Datastores
|
|
# datastore_include = [ "/*/datastore/**"] # Inventory path to datastores to collect (by default all are collected)
|
|
# datastore_exclude = [] # Inventory paths to exclude
|
|
# datastore_metric_include = [] ## if omitted or empty, all metrics are collected
|
|
# datastore_metric_exclude = [] ## Nothing excluded by default
|
|
# datastore_instances = false ## false by default
|
|
|
|
## Datacenters
|
|
# datacenter_include = [ "/*/host/**"] # Inventory path to clusters to collect (by default all are collected)
|
|
# datacenter_exclude = [] # Inventory paths to exclude
|
|
datacenter_metric_include = [] ## if omitted or empty, all metrics are collected
|
|
datacenter_metric_exclude = [ "*" ] ## Datacenters are not collected by default.
|
|
# datacenter_instances = false ## false by default
|
|
|
|
## Plugin Settings
|
|
## separator character to use for measurement and field names (default: "_")
|
|
# separator = "_"
|
|
|
|
## number of objects to retreive per query for realtime resources (vms and hosts)
|
|
## set to 64 for vCenter 5.5 and 6.0 (default: 256)
|
|
# max_query_objects = 256
|
|
|
|
## number of metrics to retreive per query for non-realtime resources (clusters and datastores)
|
|
## set to 64 for vCenter 5.5 and 6.0 (default: 256)
|
|
# max_query_metrics = 256
|
|
|
|
## number of go routines to use for collection and discovery of objects and metrics
|
|
# collect_concurrency = 1
|
|
# discover_concurrency = 1
|
|
|
|
## the interval before (re)discovering objects subject to metrics collection (default: 300s)
|
|
# object_discovery_interval = "300s"
|
|
|
|
## timeout applies to any of the api request made to vcenter
|
|
# timeout = "60s"
|
|
|
|
## When set to true, all samples are sent as integers. This makes the output
|
|
## data types backwards compatible with Telegraf 1.9 or lower. Normally all
|
|
## samples from vCenter, with the exception of percentages, are integer
|
|
## values, but under some conditions, some averaging takes place internally in
|
|
## the plugin. Setting this flag to "false" will send values as floats to
|
|
## preserve the full precision when averaging takes place.
|
|
# use_int_samples = true
|
|
|
|
## Custom attributes from vCenter can be very useful for queries in order to slice the
|
|
## metrics along different dimension and for forming ad-hoc relationships. They are disabled
|
|
## by default, since they can add a considerable amount of tags to the resulting metrics. To
|
|
## enable, simply set custom_attribute_exlude to [] (empty set) and use custom_attribute_include
|
|
## to select the attributes you want to include.
|
|
## By default, since they can add a considerable amount of tags to the resulting metrics. To
|
|
## enable, simply set custom_attribute_exlude to [] (empty set) and use custom_attribute_include
|
|
## to select the attributes you want to include.
|
|
# custom_attribute_include = []
|
|
# custom_attribute_exclude = ["*"]
|
|
|
|
## Optional SSL Config
|
|
# ssl_ca = "/path/to/cafile"
|
|
# ssl_cert = "/path/to/certfile"
|
|
# ssl_key = "/path/to/keyfile"
|
|
## Use SSL but skip chain & host verification
|
|
# insecure_skip_verify = false
|
|
`
|
|
|
|
// SampleConfig returns a set of default configuration to be used as a boilerplate when setting up
|
|
// Telegraf.
|
|
func (v *VSphere) SampleConfig() string {
|
|
return sampleConfig
|
|
}
|
|
|
|
// Description returns a short textual description of the plugin
|
|
func (v *VSphere) Description() string {
|
|
return "Read metrics from VMware vCenter"
|
|
}
|
|
|
|
// Start is called from telegraf core when a plugin is started and allows it to
|
|
// perform initialization tasks.
|
|
func (v *VSphere) Start(acc telegraf.Accumulator) error {
|
|
v.Log.Info("Starting plugin")
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
v.cancel = cancel
|
|
|
|
// Check for deprecated settings
|
|
if !v.ForceDiscoverOnInit {
|
|
v.Log.Warn("The 'force_discover_on_init' configuration parameter has been deprecated. Setting it to 'false' has no effect")
|
|
}
|
|
|
|
// Create endpoints, one for each vCenter we're monitoring
|
|
v.endpoints = make([]*Endpoint, len(v.Vcenters))
|
|
for i, rawURL := range v.Vcenters {
|
|
u, err := soap.ParseURL(rawURL)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
ep, err := NewEndpoint(ctx, v, u)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
v.endpoints[i] = ep
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// Stop is called from telegraf core when a plugin is stopped and allows it to
|
|
// perform shutdown tasks.
|
|
func (v *VSphere) Stop() {
|
|
v.Log.Info("Stopping plugin")
|
|
v.cancel()
|
|
|
|
// Wait for all endpoints to finish. No need to wait for
|
|
// Gather() to finish here, since it Stop() will only be called
|
|
// after the last Gather() has finished. We do, however, need to
|
|
// wait for any discovery to complete by trying to grab the
|
|
// "busy" mutex.
|
|
for _, ep := range v.endpoints {
|
|
v.Log.Debugf("Waiting for endpoint %q to finish", ep.URL.Host)
|
|
func() {
|
|
ep.busy.Lock() // Wait until discovery is finished
|
|
defer ep.busy.Unlock()
|
|
ep.Close()
|
|
}()
|
|
}
|
|
}
|
|
|
|
// Gather is the main data collection function called by the Telegraf core. It performs all
|
|
// the data collection and writes all metrics into the Accumulator passed as an argument.
|
|
func (v *VSphere) Gather(acc telegraf.Accumulator) error {
|
|
var wg sync.WaitGroup
|
|
for _, ep := range v.endpoints {
|
|
wg.Add(1)
|
|
go func(endpoint *Endpoint) {
|
|
defer wg.Done()
|
|
err := endpoint.Collect(context.Background(), acc)
|
|
if err == context.Canceled {
|
|
|
|
// No need to signal errors if we were merely canceled.
|
|
err = nil
|
|
}
|
|
if err != nil {
|
|
acc.AddError(err)
|
|
}
|
|
}(ep)
|
|
}
|
|
|
|
wg.Wait()
|
|
return nil
|
|
}
|
|
|
|
func init() {
|
|
inputs.Add("vsphere", func() telegraf.Input {
|
|
return &VSphere{
|
|
Vcenters: []string{},
|
|
|
|
DatacenterInstances: false,
|
|
DatacenterMetricInclude: nil,
|
|
DatacenterMetricExclude: nil,
|
|
DatacenterInclude: []string{"/*"},
|
|
ClusterInstances: false,
|
|
ClusterMetricInclude: nil,
|
|
ClusterMetricExclude: nil,
|
|
ClusterInclude: []string{"/*/host/**"},
|
|
HostInstances: true,
|
|
HostMetricInclude: nil,
|
|
HostMetricExclude: nil,
|
|
HostInclude: []string{"/*/host/**"},
|
|
VMInstances: true,
|
|
VMMetricInclude: nil,
|
|
VMMetricExclude: nil,
|
|
VMInclude: []string{"/*/vm/**"},
|
|
DatastoreInstances: false,
|
|
DatastoreMetricInclude: nil,
|
|
DatastoreMetricExclude: nil,
|
|
DatastoreInclude: []string{"/*/datastore/**"},
|
|
Separator: "_",
|
|
CustomAttributeInclude: []string{},
|
|
CustomAttributeExclude: []string{"*"},
|
|
UseIntSamples: true,
|
|
IpAddresses: []string{},
|
|
|
|
MaxQueryObjects: 256,
|
|
MaxQueryMetrics: 256,
|
|
CollectConcurrency: 1,
|
|
DiscoverConcurrency: 1,
|
|
ForceDiscoverOnInit: true,
|
|
ObjectDiscoveryInterval: internal.Duration{Duration: time.Second * 300},
|
|
Timeout: internal.Duration{Duration: time.Second * 60},
|
|
}
|
|
})
|
|
}
|