feat: allow collecting node-level metrics for Couchbase buckets (#9717)
This commit is contained in:
parent
6b009f3072
commit
fcc9373eba
|
|
@ -30,6 +30,14 @@ couchbase server.
|
||||||
## Use TLS but skip chain & host verification (defaults to false)
|
## Use TLS but skip chain & host verification (defaults to false)
|
||||||
## If set to false, tls_cert and tls_key are required
|
## If set to false, tls_cert and tls_key are required
|
||||||
# insecure_skip_verify = false
|
# insecure_skip_verify = false
|
||||||
|
|
||||||
|
## Whether to collect cluster-wide bucket statistics
|
||||||
|
## It is recommended to disable this in favor of node_stats
|
||||||
|
## to get a better view of the cluster.
|
||||||
|
cluster_bucket_stats = true
|
||||||
|
|
||||||
|
## Whether to collect bucket stats for each individual node
|
||||||
|
node_bucket_stats = false
|
||||||
```
|
```
|
||||||
|
|
||||||
## Metrics
|
## Metrics
|
||||||
|
|
@ -46,12 +54,13 @@ Fields:
|
||||||
- memory_free (unit: bytes, example: 23181365248.0)
|
- memory_free (unit: bytes, example: 23181365248.0)
|
||||||
- memory_total (unit: bytes, example: 64424656896.0)
|
- memory_total (unit: bytes, example: 64424656896.0)
|
||||||
|
|
||||||
### couchbase_bucket
|
### couchbase_bucket and couchbase_node_bucket
|
||||||
|
|
||||||
Tags:
|
Tags:
|
||||||
|
|
||||||
- cluster: whatever you called it in `servers` in the configuration, e.g.: `http://couchbase-0.example.com/`)
|
- cluster: whatever you called it in `servers` in the configuration, e.g.: `http://couchbase-0.example.com/`)
|
||||||
- bucket: the name of the couchbase bucket, e.g., `blastro-df`
|
- bucket: the name of the couchbase bucket, e.g., `blastro-df`
|
||||||
|
- hostname: the hostname of the node the bucket metrics were collected from, e.g., `172.16.10.187:8091` (only present in `couchbase_node_bucket`)
|
||||||
|
|
||||||
Default bucket fields:
|
Default bucket fields:
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,9 @@ type Couchbase struct {
|
||||||
|
|
||||||
BucketStatsIncluded []string `toml:"bucket_stats_included"`
|
BucketStatsIncluded []string `toml:"bucket_stats_included"`
|
||||||
|
|
||||||
|
ClusterBucketStats bool `toml:"cluster_bucket_stats"`
|
||||||
|
NodeBucketStats bool `toml:"node_bucket_stats"`
|
||||||
|
|
||||||
bucketInclude filter.Filter
|
bucketInclude filter.Filter
|
||||||
client *http.Client
|
client *http.Client
|
||||||
|
|
||||||
|
|
@ -85,32 +88,55 @@ func (cb *Couchbase) gatherServer(acc telegraf.Accumulator, addr string) error {
|
||||||
acc.AddFields("couchbase_node", fields, tags)
|
acc.AddFields("couchbase_node", fields, tags)
|
||||||
}
|
}
|
||||||
|
|
||||||
for bucketName := range pool.BucketMap {
|
for name, bucket := range pool.BucketMap {
|
||||||
tags := map[string]string{"cluster": escapedAddr, "bucket": bucketName}
|
cluster := regexpURI.ReplaceAllString(addr, "${1}")
|
||||||
bs := pool.BucketMap[bucketName].BasicStats
|
|
||||||
fields := make(map[string]interface{})
|
|
||||||
cb.addBucketField(fields, "quota_percent_used", bs["quotaPercentUsed"])
|
|
||||||
cb.addBucketField(fields, "ops_per_sec", bs["opsPerSec"])
|
|
||||||
cb.addBucketField(fields, "disk_fetches", bs["diskFetches"])
|
|
||||||
cb.addBucketField(fields, "item_count", bs["itemCount"])
|
|
||||||
cb.addBucketField(fields, "disk_used", bs["diskUsed"])
|
|
||||||
cb.addBucketField(fields, "data_used", bs["dataUsed"])
|
|
||||||
cb.addBucketField(fields, "mem_used", bs["memUsed"])
|
|
||||||
|
|
||||||
err := cb.gatherDetailedBucketStats(addr, bucketName, fields)
|
if cb.ClusterBucketStats {
|
||||||
if err != nil {
|
fields := cb.basicBucketStats(bucket.BasicStats)
|
||||||
return err
|
tags := map[string]string{"cluster": cluster, "bucket": name}
|
||||||
|
|
||||||
|
err := cb.gatherDetailedBucketStats(addr, name, nil, fields)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
acc.AddFields("couchbase_bucket", fields, tags)
|
||||||
}
|
}
|
||||||
|
|
||||||
acc.AddFields("couchbase_bucket", fields, tags)
|
if cb.NodeBucketStats {
|
||||||
|
for _, node := range bucket.Nodes() {
|
||||||
|
fields := cb.basicBucketStats(bucket.BasicStats)
|
||||||
|
tags := map[string]string{"cluster": cluster, "bucket": name, "hostname": node.Hostname}
|
||||||
|
|
||||||
|
err := cb.gatherDetailedBucketStats(addr, name, &node.Hostname, fields)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
acc.AddFields("couchbase_node_bucket", fields, tags)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cb *Couchbase) gatherDetailedBucketStats(server, bucket string, fields map[string]interface{}) error {
|
// basicBucketStats gets the basic bucket statistics
|
||||||
|
func (cb *Couchbase) basicBucketStats(basicStats map[string]interface{}) map[string]interface{} {
|
||||||
|
fields := make(map[string]interface{})
|
||||||
|
cb.addBucketField(fields, "quota_percent_used", basicStats["quotaPercentUsed"])
|
||||||
|
cb.addBucketField(fields, "ops_per_sec", basicStats["opsPerSec"])
|
||||||
|
cb.addBucketField(fields, "disk_fetches", basicStats["diskFetches"])
|
||||||
|
cb.addBucketField(fields, "item_count", basicStats["itemCount"])
|
||||||
|
cb.addBucketField(fields, "disk_used", basicStats["diskUsed"])
|
||||||
|
cb.addBucketField(fields, "data_used", basicStats["dataUsed"])
|
||||||
|
cb.addBucketField(fields, "mem_used", basicStats["memUsed"])
|
||||||
|
return fields
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cb *Couchbase) gatherDetailedBucketStats(server, bucket string, nodeHostname *string, fields map[string]interface{}) error {
|
||||||
extendedBucketStats := &BucketStats{}
|
extendedBucketStats := &BucketStats{}
|
||||||
err := cb.queryDetailedBucketStats(server, bucket, extendedBucketStats)
|
err := cb.queryDetailedBucketStats(server, bucket, nodeHostname, extendedBucketStats)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -349,9 +375,15 @@ func (cb *Couchbase) addBucketFieldChecked(fields map[string]interface{}, fieldK
|
||||||
cb.addBucketField(fields, fieldKey, values[len(values)-1])
|
cb.addBucketField(fields, fieldKey, values[len(values)-1])
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cb *Couchbase) queryDetailedBucketStats(server, bucket string, bucketStats *BucketStats) error {
|
func (cb *Couchbase) queryDetailedBucketStats(server, bucket string, nodeHostname *string, bucketStats *BucketStats) error {
|
||||||
|
url := server + "/pools/default/buckets/" + bucket
|
||||||
|
if nodeHostname != nil {
|
||||||
|
url += "/nodes/" + *nodeHostname
|
||||||
|
}
|
||||||
|
url += "/stats?"
|
||||||
|
|
||||||
// Set up an HTTP request to get the complete set of bucket stats.
|
// Set up an HTTP request to get the complete set of bucket stats.
|
||||||
req, err := http.NewRequest("GET", server+"/pools/default/buckets/"+bucket+"/stats?", nil)
|
req, err := http.NewRequest("GET", url, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -399,6 +431,7 @@ func init() {
|
||||||
inputs.Add("couchbase", func() telegraf.Input {
|
inputs.Add("couchbase", func() telegraf.Input {
|
||||||
return &Couchbase{
|
return &Couchbase{
|
||||||
BucketStatsIncluded: []string{"quota_percent_used", "ops_per_sec", "disk_fetches", "item_count", "disk_used", "data_used", "mem_used"},
|
BucketStatsIncluded: []string{"quota_percent_used", "ops_per_sec", "disk_fetches", "item_count", "disk_used", "data_used", "mem_used"},
|
||||||
|
ClusterBucketStats: true,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue