diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-08-26 08:15:24 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-08-26 08:15:35 +0000 |
commit | f09848204fa5283d21ea43e262ee41aa578e1808 (patch) | |
tree | c62385d7adf209fa6a798635954d887f718fb3fb /src/go/plugin/go.d/modules/couchbase | |
parent | Releasing debian version 1.46.3-2. (diff) | |
download | netdata-f09848204fa5283d21ea43e262ee41aa578e1808.tar.xz netdata-f09848204fa5283d21ea43e262ee41aa578e1808.zip |
Merging upstream version 1.47.0.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/go/plugin/go.d/modules/couchbase')
l--------- | src/go/plugin/go.d/modules/couchbase/README.md | 1 | ||||
-rw-r--r-- | src/go/plugin/go.d/modules/couchbase/charts.go | 84 | ||||
-rw-r--r-- | src/go/plugin/go.d/modules/couchbase/collect.go | 154 | ||||
-rw-r--r-- | src/go/plugin/go.d/modules/couchbase/config_schema.json | 183 | ||||
-rw-r--r-- | src/go/plugin/go.d/modules/couchbase/couchbase.go | 122 | ||||
-rw-r--r-- | src/go/plugin/go.d/modules/couchbase/couchbase_test.go | 240 | ||||
-rw-r--r-- | src/go/plugin/go.d/modules/couchbase/init.go | 39 | ||||
-rw-r--r-- | src/go/plugin/go.d/modules/couchbase/integrations/couchbase.md | 247 | ||||
-rw-r--r-- | src/go/plugin/go.d/modules/couchbase/metadata.yaml | 214 | ||||
-rw-r--r-- | src/go/plugin/go.d/modules/couchbase/metrics.go | 33 | ||||
-rw-r--r-- | src/go/plugin/go.d/modules/couchbase/testdata/6.6.0/buckets_basic_stats.json | 422 | ||||
-rw-r--r-- | src/go/plugin/go.d/modules/couchbase/testdata/config.json | 20 | ||||
-rw-r--r-- | src/go/plugin/go.d/modules/couchbase/testdata/config.yaml | 17 |
13 files changed, 1776 insertions, 0 deletions
diff --git a/src/go/plugin/go.d/modules/couchbase/README.md b/src/go/plugin/go.d/modules/couchbase/README.md new file mode 120000 index 00000000..fa8d05e1 --- /dev/null +++ b/src/go/plugin/go.d/modules/couchbase/README.md @@ -0,0 +1 @@ +integrations/couchbase.md
\ No newline at end of file diff --git a/src/go/plugin/go.d/modules/couchbase/charts.go b/src/go/plugin/go.d/modules/couchbase/charts.go new file mode 100644 index 00000000..277b814a --- /dev/null +++ b/src/go/plugin/go.d/modules/couchbase/charts.go @@ -0,0 +1,84 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +package couchbase + +import ( + "github.com/netdata/netdata/go/plugins/plugin/go.d/agent/module" +) + +type ( + Charts = module.Charts + Chart = module.Chart + Dim = module.Dim +) + +var bucketQuotaPercentUsedChart = Chart{ + ID: "bucket_quota_percent_used", + Title: "Quota Percent Used Per Bucket", + Units: "%", + Fam: "buckets basic stats", + Ctx: "couchbase.bucket_quota_percent_used", +} + +var bucketOpsPerSecChart = Chart{ + ID: "bucket_ops_per_sec", + Title: "Operations Per Second Per Bucket", + Units: "ops/s", + Fam: "buckets basic stats", + Ctx: "couchbase.bucket_ops_per_sec", + Type: module.Stacked, +} + +var bucketDiskFetchesChart = Chart{ + ID: "bucket_disk_fetches", + Title: "Disk Fetches Per Bucket", + Units: "fetches", + Fam: "buckets basic stats", + Ctx: "couchbase.bucket_disk_fetches", + Type: module.Stacked, +} + +var bucketItemCountChart = Chart{ + ID: "bucket_item_count", + Title: "Item Count Per Bucket", + Units: "items", + Fam: "buckets basic stats", + Ctx: "couchbase.bucket_item_count", + Type: module.Stacked, +} + +var bucketDiskUsedChart = Chart{ + ID: "bucket_disk_used_stats", + Title: "Disk Used Per Bucket", + Units: "bytes", + Fam: "buckets basic stats", + Ctx: "couchbase.bucket_disk_used_stats", + Type: module.Stacked, +} + +var bucketDataUsedChart = Chart{ + ID: "bucket_data_used", + Title: "Data Used Per Bucket", + Units: "bytes", + Fam: "buckets basic stats", + Ctx: "couchbase.bucket_data_used", + Type: module.Stacked, +} + +var bucketMemUsedChart = Chart{ + ID: "bucket_mem_used", + Title: "Memory Used Per Bucket", + Units: "bytes", + Fam: "buckets basic stats", + Ctx: "couchbase.bucket_mem_used", + Type: module.Stacked, +} + +var bucketVBActiveNumNonResidentChart = Chart{ + ID: "bucket_vb_active_num_non_resident_stats", + Title: "Number Of Non-Resident Items Per Bucket", + Units: "items", + Fam: "buckets basic stats", + Ctx: "couchbase.bucket_vb_active_num_non_resident", + Type: module.Stacked, +} diff --git a/src/go/plugin/go.d/modules/couchbase/collect.go b/src/go/plugin/go.d/modules/couchbase/collect.go new file mode 100644 index 00000000..6027ac91 --- /dev/null +++ b/src/go/plugin/go.d/modules/couchbase/collect.go @@ -0,0 +1,154 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +package couchbase + +import ( + "encoding/json" + "fmt" + "io" + "net/http" + "net/url" + + "github.com/netdata/netdata/go/plugins/plugin/go.d/agent/module" + "github.com/netdata/netdata/go/plugins/plugin/go.d/pkg/web" +) + +const ( + urlPathBucketsStats = "/pools/default/buckets" + + precision = 1000 +) + +func (cb *Couchbase) collect() (map[string]int64, error) { + ms, err := cb.scrapeCouchbase() + if err != nil { + return nil, fmt.Errorf("error on scraping couchbase: %v", err) + } + if ms.empty() { + return nil, nil + } + + collected := make(map[string]int64) + cb.collectBasicStats(collected, ms) + + return collected, nil +} + +func (cb *Couchbase) collectBasicStats(collected map[string]int64, ms *cbMetrics) { + for _, b := range ms.BucketsBasicStats { + + if !cb.collectedBuckets[b.Name] { + cb.collectedBuckets[b.Name] = true + cb.addBucketToCharts(b.Name) + } + + bs := b.BasicStats + collected[indexDimID(b.Name, "quota_percent_used")] = int64(bs.QuotaPercentUsed * precision) + collected[indexDimID(b.Name, "ops_per_sec")] = int64(bs.OpsPerSec * precision) + collected[indexDimID(b.Name, "disk_fetches")] = int64(bs.DiskFetches) + collected[indexDimID(b.Name, "item_count")] = int64(bs.ItemCount) + collected[indexDimID(b.Name, "disk_used")] = int64(bs.DiskUsed) + collected[indexDimID(b.Name, "data_used")] = int64(bs.DataUsed) + collected[indexDimID(b.Name, "mem_used")] = int64(bs.MemUsed) + collected[indexDimID(b.Name, "vb_active_num_non_resident")] = int64(bs.VbActiveNumNonResident) + } +} + +func (cb *Couchbase) addBucketToCharts(bucket string) { + cb.addDimToChart(bucketQuotaPercentUsedChart.ID, &module.Dim{ + ID: indexDimID(bucket, "quota_percent_used"), + Name: bucket, + Div: precision, + }) + + cb.addDimToChart(bucketOpsPerSecChart.ID, &module.Dim{ + ID: indexDimID(bucket, "ops_per_sec"), + Name: bucket, + Div: precision, + }) + + cb.addDimToChart(bucketDiskFetchesChart.ID, &module.Dim{ + ID: indexDimID(bucket, "disk_fetches"), + Name: bucket, + }) + + cb.addDimToChart(bucketItemCountChart.ID, &module.Dim{ + ID: indexDimID(bucket, "item_count"), + Name: bucket, + }) + + cb.addDimToChart(bucketDiskUsedChart.ID, &module.Dim{ + ID: indexDimID(bucket, "disk_used"), + Name: bucket, + }) + + cb.addDimToChart(bucketDataUsedChart.ID, &module.Dim{ + ID: indexDimID(bucket, "data_used"), + Name: bucket, + }) + + cb.addDimToChart(bucketMemUsedChart.ID, &module.Dim{ + ID: indexDimID(bucket, "mem_used"), + Name: bucket, + }) + + cb.addDimToChart(bucketVBActiveNumNonResidentChart.ID, &module.Dim{ + ID: indexDimID(bucket, "vb_active_num_non_resident"), + Name: bucket, + }) +} + +func (cb *Couchbase) addDimToChart(chartID string, dim *module.Dim) { + chart := cb.Charts().Get(chartID) + if chart == nil { + cb.Warningf("error on adding '%s' dimension: can not find '%s' chart", dim.ID, chartID) + return + } + if err := chart.AddDim(dim); err != nil { + cb.Warning(err) + return + } + chart.MarkNotCreated() +} + +func (cb *Couchbase) scrapeCouchbase() (*cbMetrics, error) { + req, err := web.NewHTTPRequestWithPath(cb.Request, urlPathBucketsStats) + if err != nil { + return nil, err + } + req.URL.RawQuery = url.Values{"skipMap": []string{"true"}}.Encode() + + ms := &cbMetrics{} + if err := cb.doOKDecode(req, &ms.BucketsBasicStats); err != nil { + return nil, err + } + return ms, nil +} + +func (cb *Couchbase) doOKDecode(req *http.Request, in interface{}) error { + resp, err := cb.httpClient.Do(req) + if err != nil { + return fmt.Errorf("error on HTTP request '%s': %v", req.URL, err) + } + defer closeBody(resp) + + if resp.StatusCode != http.StatusOK { + return fmt.Errorf("'%s' returned HTTP status code: %d", req.URL, resp.StatusCode) + } + + if err := json.NewDecoder(resp.Body).Decode(in); err != nil { + return fmt.Errorf("error on decoding response from '%s': %v", req.URL, err) + } + return nil +} + +func closeBody(resp *http.Response) { + if resp != nil && resp.Body != nil { + _, _ = io.Copy(io.Discard, resp.Body) + _ = resp.Body.Close() + } +} + +func indexDimID(name, metric string) string { + return fmt.Sprintf("bucket_%s_%s", name, metric) +} diff --git a/src/go/plugin/go.d/modules/couchbase/config_schema.json b/src/go/plugin/go.d/modules/couchbase/config_schema.json new file mode 100644 index 00000000..6ef455a9 --- /dev/null +++ b/src/go/plugin/go.d/modules/couchbase/config_schema.json @@ -0,0 +1,183 @@ +{ + "jsonSchema": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Couchbase collector configuration.", + "type": "object", + "properties": { + "update_every": { + "title": "Update every", + "description": "Data collection interval, measured in seconds.", + "type": "integer", + "minimum": 1, + "default": 5 + }, + "url": { + "title": "URL", + "description": "The URL of the Couchbase REST API.", + "type": "string", + "default": "http://127.0.0.1:8091", + "format": "uri" + }, + "timeout": { + "title": "Timeout", + "description": "The timeout in seconds for the HTTP request.", + "type": "number", + "minimum": 0.5, + "default": 1 + }, + "not_follow_redirects": { + "title": "Not follow redirects", + "description": "If set, the client will not follow HTTP redirects automatically.", + "type": "boolean" + }, + "username": { + "title": "Username", + "description": "The username for basic authentication.", + "type": "string", + "sensitive": true + }, + "password": { + "title": "Password", + "description": "The password for basic authentication.", + "type": "string", + "sensitive": true + }, + "proxy_url": { + "title": "Proxy URL", + "description": "The URL of the proxy server.", + "type": "string" + }, + "proxy_username": { + "title": "Proxy username", + "description": "The username for proxy authentication.", + "type": "string", + "sensitive": true + }, + "proxy_password": { + "title": "Proxy password", + "description": "The password for proxy authentication.", + "type": "string", + "sensitive": true + }, + "headers": { + "title": "Headers", + "description": "Additional HTTP headers to include in the request.", + "type": [ + "object", + "null" + ], + "additionalProperties": { + "type": "string" + } + }, + "tls_skip_verify": { + "title": "Skip TLS verification", + "description": "If set, TLS certificate verification will be skipped.", + "type": "boolean" + }, + "tls_ca": { + "title": "TLS CA", + "description": "The path to the CA certificate file for TLS verification.", + "type": "string", + "pattern": "^$|^/" + }, + "tls_cert": { + "title": "TLS certificate", + "description": "The path to the client certificate file for TLS authentication.", + "type": "string", + "pattern": "^$|^/" + }, + "tls_key": { + "title": "TLS key", + "description": "The path to the client key file for TLS authentication.", + "type": "string", + "pattern": "^$|^/" + }, + "body": { + "title": "Body", + "type": "string" + }, + "method": { + "title": "Method", + "type": "string" + } + }, + "required": [ + "url" + ], + "additionalProperties": false, + "patternProperties": { + "^name$": {} + } + }, + "uiSchema": { + "ui:flavour": "tabs", + "ui:options": { + "tabs": [ + { + "title": "Base", + "fields": [ + "update_every", + "url", + "timeout", + "not_follow_redirects" + ] + }, + { + "title": "Auth", + "fields": [ + "username", + "password" + ] + }, + { + "title": "TLS", + "fields": [ + "tls_skip_verify", + "tls_ca", + "tls_cert", + "tls_key" + ] + }, + { + "title": "Proxy", + "fields": [ + "proxy_url", + "proxy_username", + "proxy_password" + ] + }, + { + "title": "Headers", + "fields": [ + "headers" + ] + } + ] + }, + "uiOptions": { + "fullPage": true + }, + "body": { + "ui:widget": "hidden" + }, + "method": { + "ui:widget": "hidden" + }, + "timeout": { + "ui:help": "Accepts decimals for precise control (e.g., type 1.5 for 1.5 seconds)." + }, + "username": { + "ui:widget": "password" + }, + "proxy_username": { + "ui:widget": "password" + }, + "password": { + "ui:widget": "password" + }, + "proxy_password": { + "ui:widget": "password" + } + } +} diff --git a/src/go/plugin/go.d/modules/couchbase/couchbase.go b/src/go/plugin/go.d/modules/couchbase/couchbase.go new file mode 100644 index 00000000..8ef880c2 --- /dev/null +++ b/src/go/plugin/go.d/modules/couchbase/couchbase.go @@ -0,0 +1,122 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +package couchbase + +import ( + _ "embed" + "errors" + "net/http" + "time" + + "github.com/netdata/netdata/go/plugins/plugin/go.d/agent/module" + "github.com/netdata/netdata/go/plugins/plugin/go.d/pkg/web" +) + +//go:embed "config_schema.json" +var configSchema string + +func init() { + module.Register("couchbase", module.Creator{ + JobConfigSchema: configSchema, + Defaults: module.Defaults{ + UpdateEvery: 5, + }, + Create: func() module.Module { return New() }, + Config: func() any { return &Config{} }, + }) +} + +func New() *Couchbase { + return &Couchbase{ + Config: Config{ + HTTP: web.HTTP{ + Request: web.Request{ + URL: "http://127.0.0.1:8091", + }, + Client: web.Client{ + Timeout: web.Duration(time.Second), + }, + }, + }, + collectedBuckets: make(map[string]bool), + } +} + +type Config struct { + UpdateEvery int `yaml:"update_every,omitempty" json:"update_every"` + web.HTTP `yaml:",inline" json:""` +} + +type Couchbase struct { + module.Base + Config `yaml:",inline" json:""` + + httpClient *http.Client + charts *module.Charts + + collectedBuckets map[string]bool +} + +func (cb *Couchbase) Configuration() any { + return cb.Config +} + +func (cb *Couchbase) Init() error { + err := cb.validateConfig() + if err != nil { + cb.Errorf("check configuration: %v", err) + return err + } + + httpClient, err := cb.initHTTPClient() + if err != nil { + cb.Errorf("init HTTP client: %v", err) + return err + } + cb.httpClient = httpClient + + charts, err := cb.initCharts() + if err != nil { + cb.Errorf("init charts: %v", err) + return err + } + cb.charts = charts + + return nil +} + +func (cb *Couchbase) Check() error { + mx, err := cb.collect() + if err != nil { + cb.Error(err) + return err + } + if len(mx) == 0 { + return errors.New("no metrics collected") + + } + return nil +} + +func (cb *Couchbase) Charts() *Charts { + return cb.charts +} + +func (cb *Couchbase) Collect() map[string]int64 { + mx, err := cb.collect() + if err != nil { + cb.Error(err) + } + + if len(mx) == 0 { + return nil + } + return mx +} + +func (cb *Couchbase) Cleanup() { + if cb.httpClient == nil { + return + } + cb.httpClient.CloseIdleConnections() +} diff --git a/src/go/plugin/go.d/modules/couchbase/couchbase_test.go b/src/go/plugin/go.d/modules/couchbase/couchbase_test.go new file mode 100644 index 00000000..b28c8e8f --- /dev/null +++ b/src/go/plugin/go.d/modules/couchbase/couchbase_test.go @@ -0,0 +1,240 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +package couchbase + +import ( + "net/http" + "net/http/httptest" + "os" + "testing" + + "github.com/netdata/netdata/go/plugins/plugin/go.d/agent/module" + "github.com/netdata/netdata/go/plugins/plugin/go.d/pkg/web" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +var ( + dataConfigJSON, _ = os.ReadFile("testdata/config.json") + dataConfigYAML, _ = os.ReadFile("testdata/config.yaml") + + dataVer660BucketsBasicStats, _ = os.ReadFile("testdata/6.6.0/buckets_basic_stats.json") +) + +func Test_testDataIsValid(t *testing.T) { + for name, data := range map[string][]byte{ + "dataConfigJSON": dataConfigJSON, + "dataConfigYAML": dataConfigYAML, + "dataVer660BucketsBasicStats": dataVer660BucketsBasicStats, + } { + require.NotNil(t, data, name) + } +} + +func TestCouchbase_ConfigurationSerialize(t *testing.T) { + module.TestConfigurationSerialize(t, &Couchbase{}, dataConfigJSON, dataConfigYAML) +} + +func TestCouchbase_Init(t *testing.T) { + tests := map[string]struct { + config Config + wantFail bool + }{ + "success on default config": { + config: New().Config, + }, + "fails on unset 'URL'": { + wantFail: true, + config: Config{ + HTTP: web.HTTP{ + Request: web.Request{ + URL: "", + }, + }, + }, + }, + "fails on invalid URL": { + wantFail: true, + config: Config{ + HTTP: web.HTTP{ + Request: web.Request{ + URL: "127.0.0.1:9090", + }, + }, + }, + }, + } + + for name, test := range tests { + t.Run(name, func(t *testing.T) { + cb := New() + cb.Config = test.config + + if test.wantFail { + assert.Error(t, cb.Init()) + } else { + assert.NoError(t, cb.Init()) + } + }) + } +} + +func TestCouchbase_Check(t *testing.T) { + tests := map[string]struct { + prepare func(*testing.T) (cb *Couchbase, cleanup func()) + wantFail bool + }{ + "success on valid response v6.6.0": { + prepare: prepareCouchbaseV660, + }, + "fails on response with invalid data": { + wantFail: true, + prepare: prepareCouchbaseInvalidData, + }, + "fails on 404 response": { + wantFail: true, + prepare: prepareCouchbase404, + }, + "fails on connection refused": { + wantFail: true, + prepare: prepareCouchbaseConnectionRefused, + }, + } + + for name, test := range tests { + t.Run(name, func(t *testing.T) { + cb, cleanup := test.prepare(t) + defer cleanup() + + if test.wantFail { + assert.Error(t, cb.Check()) + } else { + assert.NoError(t, cb.Check()) + } + }) + } +} + +func TestCouchbase_Collect(t *testing.T) { + tests := map[string]struct { + prepare func(t *testing.T) (cb *Couchbase, cleanup func()) + wantCollected map[string]int64 + }{ + "success on valid response v6.6.0": { + prepare: prepareCouchbaseV660, + wantCollected: map[string]int64{ + "bucket_beer-sample_data_used": 13990431, + "bucket_beer-sample_disk_fetches": 1, + "bucket_beer-sample_disk_used": 27690472, + "bucket_beer-sample_item_count": 7303, + "bucket_beer-sample_mem_used": 34294872, + "bucket_beer-sample_ops_per_sec": 1100, + "bucket_beer-sample_quota_percent_used": 32706, + "bucket_beer-sample_vb_active_num_non_resident": 1, + "bucket_gamesim-sample_data_used": 5371804, + "bucket_gamesim-sample_disk_fetches": 1, + "bucket_gamesim-sample_disk_used": 13821793, + "bucket_gamesim-sample_item_count": 586, + "bucket_gamesim-sample_mem_used": 29586696, + "bucket_gamesim-sample_ops_per_sec": 1100, + "bucket_gamesim-sample_quota_percent_used": 28216, + "bucket_gamesim-sample_vb_active_num_non_resident": 1, + "bucket_travel-sample_data_used": 53865472, + "bucket_travel-sample_disk_fetches": 1, + "bucket_travel-sample_disk_used": 62244260, + "bucket_travel-sample_item_count": 31591, + "bucket_travel-sample_mem_used": 54318184, + "bucket_travel-sample_ops_per_sec": 1100, + "bucket_travel-sample_quota_percent_used": 51801, + "bucket_travel-sample_vb_active_num_non_resident": 1, + }, + }, + "fails on response with invalid data": { + prepare: prepareCouchbaseInvalidData, + }, + "fails on 404 response": { + prepare: prepareCouchbase404, + }, + "fails on connection refused": { + prepare: prepareCouchbaseConnectionRefused, + }, + } + + for name, test := range tests { + t.Run(name, func(t *testing.T) { + cb, cleanup := test.prepare(t) + defer cleanup() + + collected := cb.Collect() + + assert.Equal(t, test.wantCollected, collected) + ensureCollectedHasAllChartsDimsVarsIDs(t, cb, collected) + }) + } +} + +func prepareCouchbaseV660(t *testing.T) (cb *Couchbase, cleanup func()) { + t.Helper() + srv := httptest.NewServer(http.HandlerFunc( + func(w http.ResponseWriter, r *http.Request) { + _, _ = w.Write(dataVer660BucketsBasicStats) + })) + + cb = New() + cb.URL = srv.URL + require.NoError(t, cb.Init()) + + return cb, srv.Close +} + +func prepareCouchbaseInvalidData(t *testing.T) (*Couchbase, func()) { + t.Helper() + srv := httptest.NewServer(http.HandlerFunc( + func(w http.ResponseWriter, r *http.Request) { + _, _ = w.Write([]byte("hello and\n goodbye")) + })) + cb := New() + cb.URL = srv.URL + require.NoError(t, cb.Init()) + + return cb, srv.Close +} + +func prepareCouchbase404(t *testing.T) (*Couchbase, func()) { + t.Helper() + srv := httptest.NewServer(http.HandlerFunc( + func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusNotFound) + })) + cb := New() + cb.URL = srv.URL + require.NoError(t, cb.Init()) + + return cb, srv.Close +} + +func prepareCouchbaseConnectionRefused(t *testing.T) (*Couchbase, func()) { + t.Helper() + cb := New() + cb.URL = "http://127.0.0.1:38001" + require.NoError(t, cb.Init()) + + return cb, func() {} +} + +func ensureCollectedHasAllChartsDimsVarsIDs(t *testing.T, cb *Couchbase, collected map[string]int64) { + for _, chart := range *cb.Charts() { + if chart.Obsolete { + continue + } + for _, dim := range chart.Dims { + _, ok := collected[dim.ID] + assert.Truef(t, ok, "chart '%s' dim '%s': no dim in collected", dim.ID, chart.ID) + } + for _, v := range chart.Vars { + _, ok := collected[v.ID] + assert.Truef(t, ok, "chart '%s' dim '%s': no dim in collected", v.ID, chart.ID) + } + } +} diff --git a/src/go/plugin/go.d/modules/couchbase/init.go b/src/go/plugin/go.d/modules/couchbase/init.go new file mode 100644 index 00000000..196e6998 --- /dev/null +++ b/src/go/plugin/go.d/modules/couchbase/init.go @@ -0,0 +1,39 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +package couchbase + +import ( + "errors" + "net/http" + + "github.com/netdata/netdata/go/plugins/plugin/go.d/agent/module" + "github.com/netdata/netdata/go/plugins/plugin/go.d/pkg/web" +) + +func (cb *Couchbase) initCharts() (*Charts, error) { + var bucketCharts = module.Charts{ + bucketQuotaPercentUsedChart.Copy(), + bucketOpsPerSecChart.Copy(), + bucketDiskFetchesChart.Copy(), + bucketItemCountChart.Copy(), + bucketDiskUsedChart.Copy(), + bucketDataUsedChart.Copy(), + bucketMemUsedChart.Copy(), + bucketVBActiveNumNonResidentChart.Copy(), + } + return bucketCharts.Copy(), nil +} + +func (cb *Couchbase) initHTTPClient() (*http.Client, error) { + return web.NewHTTPClient(cb.Client) +} + +func (cb *Couchbase) validateConfig() error { + if cb.URL == "" { + return errors.New("URL not set") + } + if _, err := web.NewHTTPRequest(cb.Request); err != nil { + return err + } + return nil +} diff --git a/src/go/plugin/go.d/modules/couchbase/integrations/couchbase.md b/src/go/plugin/go.d/modules/couchbase/integrations/couchbase.md new file mode 100644 index 00000000..b53dc940 --- /dev/null +++ b/src/go/plugin/go.d/modules/couchbase/integrations/couchbase.md @@ -0,0 +1,247 @@ +<!--startmeta +custom_edit_url: "https://github.com/netdata/netdata/edit/master/src/go/plugin/go.d/modules/couchbase/README.md" +meta_yaml: "https://github.com/netdata/netdata/edit/master/src/go/plugin/go.d/modules/couchbase/metadata.yaml" +sidebar_label: "Couchbase" +learn_status: "Published" +learn_rel_path: "Collecting Metrics/Databases" +most_popular: False +message: "DO NOT EDIT THIS FILE DIRECTLY, IT IS GENERATED BY THE COLLECTOR'S metadata.yaml FILE" +endmeta--> + +# Couchbase + + +<img src="https://netdata.cloud/img/couchbase.svg" width="150"/> + + +Plugin: go.d.plugin +Module: couchbase + +<img src="https://img.shields.io/badge/maintained%20by-Netdata-%2300ab44" /> + +## Overview + +This collector monitors Couchbase servers. + + + + +This collector is supported on all platforms. + +This collector supports collecting metrics from multiple instances of this integration, including remote instances. + + +### Default Behavior + +#### Auto-Detection + +This integration doesn't support auto-detection. + +#### Limits + +The default configuration for this integration does not impose any limits on data collection. + +#### Performance Impact + +The default configuration for this integration is not expected to impose a significant performance impact on the system. + + +## Metrics + +Metrics grouped by *scope*. + +The scope defines the instance that the metric belongs to. An instance is uniquely identified by a set of labels. + + + +### Per Couchbase instance + +These metrics refer to the entire monitored application. + +This scope has no labels. + +Metrics: + +| Metric | Dimensions | Unit | +|:------|:----------|:----| +| couchbase.bucket_quota_percent_used | a dimension per bucket | percentage | +| couchbase.bucket_ops_per_sec | a dimension per bucket | ops/s | +| couchbase.bucket_disk_fetches | a dimension per bucket | fetches | +| couchbase.bucket_item_count | a dimension per bucket | items | +| couchbase.bucket_disk_used_stats | a dimension per bucket | bytes | +| couchbase.bucket_data_used | a dimension per bucket | bytes | +| couchbase.bucket_mem_used | a dimension per bucket | bytes | +| couchbase.bucket_vb_active_num_non_resident | a dimension per bucket | items | + + + +## Alerts + +There are no alerts configured by default for this integration. + + +## Setup + +### Prerequisites + +No action required. + +### Configuration + +#### File + +The configuration file name for this integration is `go.d/couchbase.conf`. + + +You can edit the configuration file using the `edit-config` script from the +Netdata [config directory](/docs/netdata-agent/configuration/README.md#the-netdata-config-directory). + +```bash +cd /etc/netdata 2>/dev/null || cd /opt/netdata/etc/netdata +sudo ./edit-config go.d/couchbase.conf +``` +#### Options + +The following options can be defined globally: update_every, autodetection_retry. + + +<details open><summary>All options</summary> + +| Name | Description | Default | Required | +|:----|:-----------|:-------|:--------:| +| update_every | Data collection frequency. | 1 | no | +| autodetection_retry | Recheck interval in seconds. Zero means no recheck will be scheduled. | 0 | no | +| url | Server URL. | http://127.0.0.1:8091 | yes | +| username | Username for basic HTTP authentication. | | no | +| password | Password for basic HTTP authentication. | | no | +| proxy_url | Proxy URL. | | no | +| proxy_username | Username for proxy basic HTTP authentication. | | no | +| proxy_password | Password for proxy basic HTTP authentication. | | no | +| timeout | HTTP request timeout. | 2 | no | +| method | HTTP request method. | GET | no | +| body | HTTP request body. | | no | +| headers | HTTP request headers. | | no | +| not_follow_redirects | Redirect handling policy. Controls whether the client follows redirects. | no | no | +| tls_skip_verify | Server certificate chain and hostname validation policy. Controls whether the client performs this check. | no | no | +| tls_ca | Certification authority that the client uses when verifying the server's certificates. | | no | +| tls_cert | Client tls certificate. | | no | +| tls_key | Client tls key. | | no | + +</details> + +#### Examples + +##### Basic + +An example configuration. + +<details open><summary>Config</summary> + +```yaml +jobs: + - name: local + url: http://127.0.0.1:8091 + +``` +</details> + +##### Basic HTTP auth + +Local server with basic HTTP authentication. + +<details open><summary>Config</summary> + +```yaml +jobs: + - name: local + url: http://127.0.0.1:8091 + username: foo + password: bar + +``` +</details> + +##### Multi-instance + +> **Note**: When you define multiple jobs, their names must be unique. + +Collecting metrics from local and remote instances. + + +<details open><summary>Config</summary> + +```yaml +jobs: + - name: local + url: http://127.0.0.1:8091 + + - name: remote + url: http://203.0.113.0:8091 + +``` +</details> + + + +## Troubleshooting + +### Debug Mode + +**Important**: Debug mode is not supported for data collection jobs created via the UI using the Dyncfg feature. + +To troubleshoot issues with the `couchbase` collector, run the `go.d.plugin` with the debug option enabled. The output +should give you clues as to why the collector isn't working. + +- Navigate to the `plugins.d` directory, usually at `/usr/libexec/netdata/plugins.d/`. If that's not the case on + your system, open `netdata.conf` and look for the `plugins` setting under `[directories]`. + + ```bash + cd /usr/libexec/netdata/plugins.d/ + ``` + +- Switch to the `netdata` user. + + ```bash + sudo -u netdata -s + ``` + +- Run the `go.d.plugin` to debug the collector: + + ```bash + ./go.d.plugin -d -m couchbase + ``` + +### Getting Logs + +If you're encountering problems with the `couchbase` collector, follow these steps to retrieve logs and identify potential issues: + +- **Run the command** specific to your system (systemd, non-systemd, or Docker container). +- **Examine the output** for any warnings or error messages that might indicate issues. These messages should provide clues about the root cause of the problem. + +#### System with systemd + +Use the following command to view logs generated since the last Netdata service restart: + +```bash +journalctl _SYSTEMD_INVOCATION_ID="$(systemctl show --value --property=InvocationID netdata)" --namespace=netdata --grep couchbase +``` + +#### System without systemd + +Locate the collector log file, typically at `/var/log/netdata/collector.log`, and use `grep` to filter for collector's name: + +```bash +grep couchbase /var/log/netdata/collector.log +``` + +**Note**: This method shows logs from all restarts. Focus on the **latest entries** for troubleshooting current issues. + +#### Docker Container + +If your Netdata runs in a Docker container named "netdata" (replace if different), use this command: + +```bash +docker logs netdata 2>&1 | grep couchbase +``` + + diff --git a/src/go/plugin/go.d/modules/couchbase/metadata.yaml b/src/go/plugin/go.d/modules/couchbase/metadata.yaml new file mode 100644 index 00000000..de21e924 --- /dev/null +++ b/src/go/plugin/go.d/modules/couchbase/metadata.yaml @@ -0,0 +1,214 @@ +plugin_name: go.d.plugin +modules: + - meta: + id: collector-go.d.plugin-couchbase + plugin_name: go.d.plugin + module_name: couchbase + monitored_instance: + name: Couchbase + link: https://www.couchbase.com/ + icon_filename: couchbase.svg + categories: + - data-collection.database-servers + keywords: + - couchbase + - databases + related_resources: + integrations: + list: [] + info_provided_to_referring_integrations: + description: "" + most_popular: false + overview: + data_collection: + metrics_description: | + This collector monitors Couchbase servers. + method_description: "" + supported_platforms: + include: [] + exclude: [] + multi_instance: true + additional_permissions: + description: "" + default_behavior: + auto_detection: + description: "" + limits: + description: "" + performance_impact: + description: "" + setup: + prerequisites: + list: [] + configuration: + file: + name: go.d/couchbase.conf + options: + description: | + The following options can be defined globally: update_every, autodetection_retry. + folding: + title: All options + enabled: true + list: + - name: update_every + description: Data collection frequency. + default_value: 1 + required: false + - name: autodetection_retry + description: Recheck interval in seconds. Zero means no recheck will be scheduled. + default_value: 0 + required: false + - name: url + description: Server URL. + default_value: http://127.0.0.1:8091 + required: true + - name: username + description: Username for basic HTTP authentication. + default_value: "" + required: false + - name: password + description: Password for basic HTTP authentication. + default_value: "" + required: false + - name: proxy_url + description: Proxy URL. + default_value: "" + required: false + - name: proxy_username + description: Username for proxy basic HTTP authentication. + default_value: "" + required: false + - name: proxy_password + description: Password for proxy basic HTTP authentication. + default_value: "" + required: false + - name: timeout + description: HTTP request timeout. + default_value: 2 + required: false + - name: method + description: HTTP request method. + default_value: GET + required: false + - name: body + description: HTTP request body. + default_value: "" + required: false + - name: headers + description: HTTP request headers. + default_value: "" + required: false + - name: not_follow_redirects + description: Redirect handling policy. Controls whether the client follows redirects. + default_value: false + required: false + - name: tls_skip_verify + description: Server certificate chain and hostname validation policy. Controls whether the client performs this check. + default_value: false + required: false + - name: tls_ca + description: Certification authority that the client uses when verifying the server's certificates. + default_value: "" + required: false + - name: tls_cert + description: Client tls certificate. + default_value: "" + required: false + - name: tls_key + description: Client tls key. + default_value: "" + required: false + examples: + folding: + title: Config + enabled: true + list: + - name: Basic + description: An example configuration. + config: | + jobs: + - name: local + url: http://127.0.0.1:8091 + - name: Basic HTTP auth + description: Local server with basic HTTP authentication. + config: | + jobs: + - name: local + url: http://127.0.0.1:8091 + username: foo + password: bar + - name: Multi-instance + description: | + > **Note**: When you define multiple jobs, their names must be unique. + + Collecting metrics from local and remote instances. + config: | + jobs: + - name: local + url: http://127.0.0.1:8091 + + - name: remote + url: http://203.0.113.0:8091 + troubleshooting: + problems: + list: [] + alerts: [] + metrics: + folding: + title: Metrics + enabled: false + description: "" + availability: [] + scopes: + - name: global + description: These metrics refer to the entire monitored application. + labels: [] + metrics: + - name: couchbase.bucket_quota_percent_used + description: Quota Percent Used Per Bucket + unit: percentage + chart_type: line + dimensions: + - name: a dimension per bucket + - name: couchbase.bucket_ops_per_sec + description: Operations Per Second Per Bucket + unit: ops/s + chart_type: stacked + dimensions: + - name: a dimension per bucket + - name: couchbase.bucket_disk_fetches + description: Disk Fetches Per Bucket + unit: fetches + chart_type: stacked + dimensions: + - name: a dimension per bucket + - name: couchbase.bucket_item_count + description: Item Count Per Bucket + unit: items + chart_type: stacked + dimensions: + - name: a dimension per bucket + - name: couchbase.bucket_disk_used_stats + description: Disk Used Per Bucket + unit: bytes + chart_type: stacked + dimensions: + - name: a dimension per bucket + - name: couchbase.bucket_data_used + description: Data Used Per Bucket + unit: bytes + chart_type: stacked + dimensions: + - name: a dimension per bucket + - name: couchbase.bucket_mem_used + description: Memory Used Per Bucket + unit: bytes + chart_type: stacked + dimensions: + - name: a dimension per bucket + - name: couchbase.bucket_vb_active_num_non_resident + description: Number Of Non-Resident Items Per Bucket + unit: items + chart_type: stacked + dimensions: + - name: a dimension per bucket diff --git a/src/go/plugin/go.d/modules/couchbase/metrics.go b/src/go/plugin/go.d/modules/couchbase/metrics.go new file mode 100644 index 00000000..c4f23304 --- /dev/null +++ b/src/go/plugin/go.d/modules/couchbase/metrics.go @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +package couchbase + +type cbMetrics struct { + // https://developer.couchbase.com/resources/best-practice-guides/monitoring-guide.pdf + BucketsBasicStats []bucketsBasicStats +} + +func (m cbMetrics) empty() bool { + switch { + case m.hasBucketsStats(): + return false + } + return true +} + +func (m cbMetrics) hasBucketsStats() bool { return len(m.BucketsBasicStats) > 0 } + +type bucketsBasicStats struct { + Name string `json:"name"` + + BasicStats struct { + DataUsed float64 `json:"dataUsed"` + DiskFetches float64 `json:"diskFetches"` + ItemCount float64 `json:"itemCount"` + DiskUsed float64 `json:"diskUsed"` + MemUsed float64 `json:"memUsed"` + OpsPerSec float64 `json:"opsPerSec"` + QuotaPercentUsed float64 `json:"quotaPercentUsed"` + VbActiveNumNonResident float64 `json:"vbActiveNumNonResident"` + } `json:"basicStats"` +} diff --git a/src/go/plugin/go.d/modules/couchbase/testdata/6.6.0/buckets_basic_stats.json b/src/go/plugin/go.d/modules/couchbase/testdata/6.6.0/buckets_basic_stats.json new file mode 100644 index 00000000..3749add7 --- /dev/null +++ b/src/go/plugin/go.d/modules/couchbase/testdata/6.6.0/buckets_basic_stats.json @@ -0,0 +1,422 @@ +[ + { + "name": "beer-sample", + "uuid": "bf10ab11911f1c065db5fd58c5fbc0b6", + "bucketType": "membase", + "authType": "sasl", + "uri": "/pools/default/buckets/beer-sample?bucket_uuid=bf10ab11911f1c065db5fd58c5fbc0b6", + "streamingUri": "/pools/default/bucketsStreaming/beer-sample?bucket_uuid=bf10ab11911f1c065db5fd58c5fbc0b6", + "localRandomKeyUri": "/pools/default/buckets/beer-sample/localRandomKey", + "controllers": { + "compactAll": "/pools/default/buckets/beer-sample/controller/compactBucket", + "compactDB": "/pools/default/buckets/beer-sample/controller/compactDatabases", + "purgeDeletes": "/pools/default/buckets/beer-sample/controller/unsafePurgeBucket", + "startRecovery": "/pools/default/buckets/beer-sample/controller/startRecovery" + }, + "nodes": [ + { + "couchApiBaseHTTPS": "https://172.17.0.2:18092/beer-sample%2Bbf10ab11911f1c065db5fd58c5fbc0b6", + "couchApiBase": "http://172.17.0.2:8092/beer-sample%2Bbf10ab11911f1c065db5fd58c5fbc0b6", + "systemStats": { + "cpu_utilization_rate": 15.21035598705502, + "cpu_stolen_rate": 0, + "swap_total": 0, + "swap_used": 0, + "mem_total": 33587437568, + "mem_free": 30532227072, + "mem_limit": 33587437568, + "cpu_cores_available": 6, + "allocstall": 0 + }, + "interestingStats": { + "cmd_get": 0, + "couch_docs_actual_disk_size": 102960477, + "couch_docs_data_size": 72439963, + "couch_spatial_data_size": 0, + "couch_spatial_disk_size": 0, + "couch_views_actual_disk_size": 796048, + "couch_views_data_size": 787744, + "curr_items": 39480, + "curr_items_tot": 39480, + "ep_bg_fetched": 0, + "get_hits": 0, + "mem_used": 118199752, + "ops": 0, + "vb_active_num_non_resident": 0, + "vb_replica_curr_items": 0 + }, + "uptime": "638", + "memoryTotal": 33587437568, + "memoryFree": 30532227072, + "mcdMemoryReserved": 25625, + "mcdMemoryAllocated": 25625, + "replication": 0, + "clusterMembership": "active", + "recoveryType": "none", + "status": "healthy", + "otpNode": "ns_1@cb.local", + "thisNode": true, + "hostname": "172.17.0.2:8091", + "nodeUUID": "da79fcb65d6ae1f8b4fdfa3ccb2e4500", + "clusterCompatibility": 393222, + "version": "6.6.0-7909-enterprise", + "os": "x86_64-unknown-linux-gnu", + "cpuCount": 6, + "ports": { + "direct": 11210, + "httpsCAPI": 18092, + "httpsMgmt": 18091, + "distTCP": 21100, + "distTLS": 21150 + }, + "services": [ + "cbas", + "eventing", + "fts", + "index", + "kv", + "n1ql" + ], + "nodeEncryption": false, + "configuredHostname": "127.0.0.1:8091", + "addressFamily": "inet", + "externalListeners": [ + { + "afamily": "inet", + "nodeEncryption": false + }, + { + "afamily": "inet6", + "nodeEncryption": false + } + ] + } + ], + "stats": { + "uri": "/pools/default/buckets/beer-sample/stats", + "directoryURI": "/pools/default/buckets/beer-sample/statsDirectory", + "nodeStatsListURI": "/pools/default/buckets/beer-sample/nodes" + }, + "nodeLocator": "vbucket", + "saslPassword": "47809efed0156c874b91bbdfeba89912", + "ddocs": { + "uri": "/pools/default/buckets/beer-sample/ddocs" + }, + "replicaIndex": true, + "autoCompactionSettings": false, + "maxTTL": 0, + "compressionMode": "passive", + "replicaNumber": 1, + "threadsNumber": 3, + "quota": { + "ram": 104857600, + "rawRAM": 104857600 + }, + "basicStats": { + "quotaPercentUsed": 32.70613861083984, + "opsPerSec": 1.1, + "diskFetches": 1, + "itemCount": 7303, + "diskUsed": 27690472, + "dataUsed": 13990431, + "memUsed": 34294872, + "vbActiveNumNonResident": 1 + }, + "evictionPolicy": "valueOnly", + "durabilityMinLevel": "none", + "conflictResolutionType": "seqno", + "bucketCapabilitiesVer": "", + "bucketCapabilities": [ + "durableWrite", + "tombstonedUserXAttrs", + "couchapi", + "dcp", + "cbhello", + "touch", + "cccp", + "xdcrCheckpointing", + "nodesExt", + "xattr" + ] + }, + { + "name": "gamesim-sample", + "uuid": "23ff61363bc4df9af4eb9c2198fc74d3", + "bucketType": "membase", + "authType": "sasl", + "uri": "/pools/default/buckets/gamesim-sample?bucket_uuid=23ff61363bc4df9af4eb9c2198fc74d3", + "streamingUri": "/pools/default/bucketsStreaming/gamesim-sample?bucket_uuid=23ff61363bc4df9af4eb9c2198fc74d3", + "localRandomKeyUri": "/pools/default/buckets/gamesim-sample/localRandomKey", + "controllers": { + "compactAll": "/pools/default/buckets/gamesim-sample/controller/compactBucket", + "compactDB": "/pools/default/buckets/gamesim-sample/controller/compactDatabases", + "purgeDeletes": "/pools/default/buckets/gamesim-sample/controller/unsafePurgeBucket", + "startRecovery": "/pools/default/buckets/gamesim-sample/controller/startRecovery" + }, + "nodes": [ + { + "couchApiBaseHTTPS": "https://172.17.0.2:18092/gamesim-sample%2B23ff61363bc4df9af4eb9c2198fc74d3", + "couchApiBase": "http://172.17.0.2:8092/gamesim-sample%2B23ff61363bc4df9af4eb9c2198fc74d3", + "systemStats": { + "cpu_utilization_rate": 15.21035598705502, + "cpu_stolen_rate": 0, + "swap_total": 0, + "swap_used": 0, + "mem_total": 33587437568, + "mem_free": 30532227072, + "mem_limit": 33587437568, + "cpu_cores_available": 6, + "allocstall": 0 + }, + "interestingStats": { + "cmd_get": 0, + "couch_docs_actual_disk_size": 102960477, + "couch_docs_data_size": 72439963, + "couch_spatial_data_size": 0, + "couch_spatial_disk_size": 0, + "couch_views_actual_disk_size": 796048, + "couch_views_data_size": 787744, + "curr_items": 39480, + "curr_items_tot": 39480, + "ep_bg_fetched": 0, + "get_hits": 0, + "mem_used": 118199752, + "ops": 0, + "vb_active_num_non_resident": 0, + "vb_replica_curr_items": 0 + }, + "uptime": "638", + "memoryTotal": 33587437568, + "memoryFree": 30532227072, + "mcdMemoryReserved": 25625, + "mcdMemoryAllocated": 25625, + "replication": 0, + "clusterMembership": "active", + "recoveryType": "none", + "status": "healthy", + "otpNode": "ns_1@cb.local", + "thisNode": true, + "hostname": "172.17.0.2:8091", + "nodeUUID": "da79fcb65d6ae1f8b4fdfa3ccb2e4500", + "clusterCompatibility": 393222, + "version": "6.6.0-7909-enterprise", + "os": "x86_64-unknown-linux-gnu", + "cpuCount": 6, + "ports": { + "direct": 11210, + "httpsCAPI": 18092, + "httpsMgmt": 18091, + "distTCP": 21100, + "distTLS": 21150 + }, + "services": [ + "cbas", + "eventing", + "fts", + "index", + "kv", + "n1ql" + ], + "nodeEncryption": false, + "configuredHostname": "127.0.0.1:8091", + "addressFamily": "inet", + "externalListeners": [ + { + "afamily": "inet", + "nodeEncryption": false + }, + { + "afamily": "inet6", + "nodeEncryption": false + } + ] + } + ], + "stats": { + "uri": "/pools/default/buckets/gamesim-sample/stats", + "directoryURI": "/pools/default/buckets/gamesim-sample/statsDirectory", + "nodeStatsListURI": "/pools/default/buckets/gamesim-sample/nodes" + }, + "nodeLocator": "vbucket", + "saslPassword": "39cf71a1da3f298bed52d19973dce967", + "ddocs": { + "uri": "/pools/default/buckets/gamesim-sample/ddocs" + }, + "replicaIndex": true, + "autoCompactionSettings": false, + "maxTTL": 0, + "compressionMode": "passive", + "replicaNumber": 1, + "threadsNumber": 3, + "quota": { + "ram": 104857600, + "rawRAM": 104857600 + }, + "basicStats": { + "quotaPercentUsed": 28.21607208251953, + "opsPerSec": 1.1, + "diskFetches": 1, + "itemCount": 586, + "diskUsed": 13821793, + "dataUsed": 5371804, + "memUsed": 29586696, + "vbActiveNumNonResident": 1 + }, + "evictionPolicy": "valueOnly", + "durabilityMinLevel": "none", + "conflictResolutionType": "seqno", + "bucketCapabilitiesVer": "", + "bucketCapabilities": [ + "durableWrite", + "tombstonedUserXAttrs", + "couchapi", + "dcp", + "cbhello", + "touch", + "cccp", + "xdcrCheckpointing", + "nodesExt", + "xattr" + ] + }, + { + "name": "travel-sample", + "uuid": "68a336f9ec0e0d2150d56298c896d0a9", + "bucketType": "membase", + "authType": "sasl", + "uri": "/pools/default/buckets/travel-sample?bucket_uuid=68a336f9ec0e0d2150d56298c896d0a9", + "streamingUri": "/pools/default/bucketsStreaming/travel-sample?bucket_uuid=68a336f9ec0e0d2150d56298c896d0a9", + "localRandomKeyUri": "/pools/default/buckets/travel-sample/localRandomKey", + "controllers": { + "compactAll": "/pools/default/buckets/travel-sample/controller/compactBucket", + "compactDB": "/pools/default/buckets/travel-sample/controller/compactDatabases", + "purgeDeletes": "/pools/default/buckets/travel-sample/controller/unsafePurgeBucket", + "startRecovery": "/pools/default/buckets/travel-sample/controller/startRecovery" + }, + "nodes": [ + { + "couchApiBaseHTTPS": "https://172.17.0.2:18092/travel-sample%2B68a336f9ec0e0d2150d56298c896d0a9", + "couchApiBase": "http://172.17.0.2:8092/travel-sample%2B68a336f9ec0e0d2150d56298c896d0a9", + "systemStats": { + "cpu_utilization_rate": 15.21035598705502, + "cpu_stolen_rate": 0, + "swap_total": 0, + "swap_used": 0, + "mem_total": 33587437568, + "mem_free": 30532227072, + "mem_limit": 33587437568, + "cpu_cores_available": 6, + "allocstall": 0 + }, + "interestingStats": { + "cmd_get": 0, + "couch_docs_actual_disk_size": 102960477, + "couch_docs_data_size": 72439963, + "couch_spatial_data_size": 0, + "couch_spatial_disk_size": 0, + "couch_views_actual_disk_size": 796048, + "couch_views_data_size": 787744, + "curr_items": 39480, + "curr_items_tot": 39480, + "ep_bg_fetched": 0, + "get_hits": 0, + "mem_used": 118199752, + "ops": 0, + "vb_active_num_non_resident": 0, + "vb_replica_curr_items": 0 + }, + "uptime": "638", + "memoryTotal": 33587437568, + "memoryFree": 30532227072, + "mcdMemoryReserved": 25625, + "mcdMemoryAllocated": 25625, + "replication": 0, + "clusterMembership": "active", + "recoveryType": "none", + "status": "healthy", + "otpNode": "ns_1@cb.local", + "thisNode": true, + "hostname": "172.17.0.2:8091", + "nodeUUID": "da79fcb65d6ae1f8b4fdfa3ccb2e4500", + "clusterCompatibility": 393222, + "version": "6.6.0-7909-enterprise", + "os": "x86_64-unknown-linux-gnu", + "cpuCount": 6, + "ports": { + "direct": 11210, + "httpsCAPI": 18092, + "httpsMgmt": 18091, + "distTCP": 21100, + "distTLS": 21150 + }, + "services": [ + "cbas", + "eventing", + "fts", + "index", + "kv", + "n1ql" + ], + "nodeEncryption": false, + "configuredHostname": "127.0.0.1:8091", + "addressFamily": "inet", + "externalListeners": [ + { + "afamily": "inet", + "nodeEncryption": false + }, + { + "afamily": "inet6", + "nodeEncryption": false + } + ] + } + ], + "stats": { + "uri": "/pools/default/buckets/travel-sample/stats", + "directoryURI": "/pools/default/buckets/travel-sample/statsDirectory", + "nodeStatsListURI": "/pools/default/buckets/travel-sample/nodes" + }, + "nodeLocator": "vbucket", + "saslPassword": "c6be6d9be723b8b1f8eac4edb84a06ed", + "ddocs": { + "uri": "/pools/default/buckets/travel-sample/ddocs" + }, + "replicaIndex": true, + "autoCompactionSettings": false, + "maxTTL": 0, + "compressionMode": "passive", + "replicaNumber": 1, + "threadsNumber": 3, + "quota": { + "ram": 104857600, + "rawRAM": 104857600 + }, + "basicStats": { + "quotaPercentUsed": 51.80185699462891, + "opsPerSec": 1.1, + "diskFetches": 1, + "itemCount": 31591, + "diskUsed": 62244260, + "dataUsed": 53865472, + "memUsed": 54318184, + "vbActiveNumNonResident": 1 + }, + "evictionPolicy": "valueOnly", + "durabilityMinLevel": "none", + "conflictResolutionType": "seqno", + "bucketCapabilitiesVer": "", + "bucketCapabilities": [ + "durableWrite", + "tombstonedUserXAttrs", + "couchapi", + "dcp", + "cbhello", + "touch", + "cccp", + "xdcrCheckpointing", + "nodesExt", + "xattr" + ] + } +] diff --git a/src/go/plugin/go.d/modules/couchbase/testdata/config.json b/src/go/plugin/go.d/modules/couchbase/testdata/config.json new file mode 100644 index 00000000..984c3ed6 --- /dev/null +++ b/src/go/plugin/go.d/modules/couchbase/testdata/config.json @@ -0,0 +1,20 @@ +{ + "update_every": 123, + "url": "ok", + "body": "ok", + "method": "ok", + "headers": { + "ok": "ok" + }, + "username": "ok", + "password": "ok", + "proxy_url": "ok", + "proxy_username": "ok", + "proxy_password": "ok", + "timeout": 123.123, + "not_follow_redirects": true, + "tls_ca": "ok", + "tls_cert": "ok", + "tls_key": "ok", + "tls_skip_verify": true +} diff --git a/src/go/plugin/go.d/modules/couchbase/testdata/config.yaml b/src/go/plugin/go.d/modules/couchbase/testdata/config.yaml new file mode 100644 index 00000000..8558b61c --- /dev/null +++ b/src/go/plugin/go.d/modules/couchbase/testdata/config.yaml @@ -0,0 +1,17 @@ +update_every: 123 +url: "ok" +body: "ok" +method: "ok" +headers: + ok: "ok" +username: "ok" +password: "ok" +proxy_url: "ok" +proxy_username: "ok" +proxy_password: "ok" +timeout: 123.123 +not_follow_redirects: yes +tls_ca: "ok" +tls_cert: "ok" +tls_key: "ok" +tls_skip_verify: yes |