diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-08-26 08:15:20 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-08-26 08:15:20 +0000 |
commit | 87d772a7d708fec12f48cd8adc0dedff6e1025da (patch) | |
tree | 1fee344c64cc3f43074a01981e21126c8482a522 /src/go/plugin/go.d/modules/cassandra | |
parent | Adding upstream version 1.46.3. (diff) | |
download | netdata-87d772a7d708fec12f48cd8adc0dedff6e1025da.tar.xz netdata-87d772a7d708fec12f48cd8adc0dedff6e1025da.zip |
Adding upstream version 1.47.0.upstream/1.47.0
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/go/plugin/go.d/modules/cassandra')
l--------- | src/go/plugin/go.d/modules/cassandra/README.md | 1 | ||||
-rw-r--r-- | src/go/plugin/go.d/modules/cassandra/cassandra.go | 118 | ||||
-rw-r--r-- | src/go/plugin/go.d/modules/cassandra/cassandra_test.go | 298 | ||||
-rw-r--r-- | src/go/plugin/go.d/modules/cassandra/charts.go | 461 | ||||
-rw-r--r-- | src/go/plugin/go.d/modules/cassandra/collect.go | 403 | ||||
-rw-r--r-- | src/go/plugin/go.d/modules/cassandra/config_schema.json | 183 | ||||
-rw-r--r-- | src/go/plugin/go.d/modules/cassandra/init.go | 25 | ||||
-rw-r--r-- | src/go/plugin/go.d/modules/cassandra/integrations/cassandra.md | 313 | ||||
-rw-r--r-- | src/go/plugin/go.d/modules/cassandra/jmx_exporter.yaml | 31 | ||||
-rw-r--r-- | src/go/plugin/go.d/modules/cassandra/metadata.yaml | 410 | ||||
-rw-r--r-- | src/go/plugin/go.d/modules/cassandra/metrics.go | 103 | ||||
-rw-r--r-- | src/go/plugin/go.d/modules/cassandra/testdata/config.json | 20 | ||||
-rw-r--r-- | src/go/plugin/go.d/modules/cassandra/testdata/config.yaml | 17 | ||||
-rw-r--r-- | src/go/plugin/go.d/modules/cassandra/testdata/metrics.txt | 402 |
14 files changed, 2785 insertions, 0 deletions
diff --git a/src/go/plugin/go.d/modules/cassandra/README.md b/src/go/plugin/go.d/modules/cassandra/README.md new file mode 120000 index 000000000..99b5b9da5 --- /dev/null +++ b/src/go/plugin/go.d/modules/cassandra/README.md @@ -0,0 +1 @@ +integrations/cassandra.md
\ No newline at end of file diff --git a/src/go/plugin/go.d/modules/cassandra/cassandra.go b/src/go/plugin/go.d/modules/cassandra/cassandra.go new file mode 100644 index 000000000..5352703df --- /dev/null +++ b/src/go/plugin/go.d/modules/cassandra/cassandra.go @@ -0,0 +1,118 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +package cassandra + +import ( + _ "embed" + "errors" + "time" + + "github.com/netdata/netdata/go/plugins/plugin/go.d/agent/module" + "github.com/netdata/netdata/go/plugins/plugin/go.d/pkg/prometheus" + "github.com/netdata/netdata/go/plugins/plugin/go.d/pkg/web" +) + +//go:embed "config_schema.json" +var configSchema string + +func init() { + module.Register("cassandra", module.Creator{ + JobConfigSchema: configSchema, + Defaults: module.Defaults{ + UpdateEvery: 5, + }, + Create: func() module.Module { return New() }, + Config: func() any { return &Config{} }, + }) +} + +func New() *Cassandra { + return &Cassandra{ + Config: Config{ + HTTP: web.HTTP{ + Request: web.Request{ + URL: "http://127.0.0.1:7072/metrics", + }, + Client: web.Client{ + Timeout: web.Duration(time.Second * 5), + }, + }, + }, + charts: baseCharts.Copy(), + validateMetrics: true, + mx: newCassandraMetrics(), + } +} + +type Config struct { + UpdateEvery int `yaml:"update_every,omitempty" json:"update_every"` + web.HTTP `yaml:",inline" json:""` +} + +type Cassandra struct { + module.Base + Config `yaml:",inline" json:""` + + charts *module.Charts + + prom prometheus.Prometheus + + validateMetrics bool + + mx *cassandraMetrics +} + +func (c *Cassandra) Configuration() any { + return c.Config +} + +func (c *Cassandra) Init() error { + if err := c.validateConfig(); err != nil { + c.Errorf("error on validating config: %v", err) + return err + } + + prom, err := c.initPrometheusClient() + if err != nil { + c.Errorf("error on init prometheus client: %v", err) + return err + } + c.prom = prom + + return nil +} + +func (c *Cassandra) Check() error { + mx, err := c.collect() + if err != nil { + c.Error(err) + return err + } + if len(mx) == 0 { + return errors.New("no metrics collected") + + } + return nil +} + +func (c *Cassandra) Charts() *module.Charts { + return c.charts +} + +func (c *Cassandra) Collect() map[string]int64 { + mx, err := c.collect() + if err != nil { + c.Error(err) + } + + if len(mx) == 0 { + return nil + } + return mx +} + +func (c *Cassandra) Cleanup() { + if c.prom != nil && c.prom.HTTPClient() != nil { + c.prom.HTTPClient().CloseIdleConnections() + } +} diff --git a/src/go/plugin/go.d/modules/cassandra/cassandra_test.go b/src/go/plugin/go.d/modules/cassandra/cassandra_test.go new file mode 100644 index 000000000..0b6af9362 --- /dev/null +++ b/src/go/plugin/go.d/modules/cassandra/cassandra_test.go @@ -0,0 +1,298 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +package cassandra + +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") + + dataExpectedMetrics, _ = os.ReadFile("testdata/metrics.txt") +) + +func Test_testDataIsValid(t *testing.T) { + for name, data := range map[string][]byte{ + "dataConfigJSON": dataConfigJSON, + "dataConfigYAML": dataConfigYAML, + "dataExpectedMetrics": dataExpectedMetrics, + } { + assert.NotNil(t, data, name) + } +} + +func TestCassandra_ConfigurationSerialize(t *testing.T) { + module.TestConfigurationSerialize(t, &Cassandra{}, dataConfigJSON, dataConfigYAML) +} + +func TestNew(t *testing.T) { + assert.IsType(t, (*Cassandra)(nil), New()) +} + +func TestCassandra_Init(t *testing.T) { + tests := map[string]struct { + config Config + wantFail bool + }{ + "success if 'url' is set": { + config: Config{ + HTTP: web.HTTP{Request: web.Request{URL: "http://127.0.0.1:7072"}}}, + }, + "success on default config": { + wantFail: false, + config: New().Config, + }, + "fails if 'url' is unset": { + wantFail: true, + config: Config{HTTP: web.HTTP{Request: web.Request{URL: ""}}}, + }, + } + + for name, test := range tests { + t.Run(name, func(t *testing.T) { + c := New() + c.Config = test.config + + if test.wantFail { + assert.Error(t, c.Init()) + } else { + assert.NoError(t, c.Init()) + } + }) + } +} + +func TestCassandra_Check(t *testing.T) { + tests := map[string]struct { + prepare func() (c *Cassandra, cleanup func()) + wantFail bool + }{ + "success on valid response": { + prepare: prepareCassandra, + }, + "fails if endpoint returns invalid data": { + wantFail: true, + prepare: prepareCassandraInvalidData, + }, + "fails on connection refused": { + wantFail: true, + prepare: prepareCassandraConnectionRefused, + }, + "fails on 404 response": { + wantFail: true, + prepare: prepareCassandraResponse404, + }, + } + + for name, test := range tests { + t.Run(name, func(t *testing.T) { + c, cleanup := test.prepare() + defer cleanup() + + require.NoError(t, c.Init()) + + if test.wantFail { + assert.Error(t, c.Check()) + } else { + assert.NoError(t, c.Check()) + } + }) + } +} + +func TestCassandra_Charts(t *testing.T) { + assert.NotNil(t, New().Charts()) +} + +func TestCassandra_Collect(t *testing.T) { + tests := map[string]struct { + prepare func() (c *Cassandra, cleanup func()) + wantCollected map[string]int64 + }{ + "success on valid response": { + prepare: prepareCassandra, + wantCollected: map[string]int64{ + "client_request_failures_reads": 0, + "client_request_failures_writes": 0, + "client_request_latency_reads": 333316, + "client_request_latency_writes": 331841, + "client_request_read_latency_p50": 61, + "client_request_read_latency_p75": 88, + "client_request_read_latency_p95": 126, + "client_request_read_latency_p98": 182, + "client_request_read_latency_p99": 219, + "client_request_read_latency_p999": 454, + "client_request_timeouts_reads": 0, + "client_request_timeouts_writes": 0, + "client_request_total_latency_reads": 23688998, + "client_request_total_latency_writes": 14253267, + "client_request_unavailables_reads": 0, + "client_request_unavailables_writes": 0, + "client_request_write_latency_p50": 35, + "client_request_write_latency_p75": 61, + "client_request_write_latency_p95": 105, + "client_request_write_latency_p98": 126, + "client_request_write_latency_p99": 152, + "client_request_write_latency_p999": 315, + "compaction_bytes_compacted": 2532, + "compaction_completed_tasks": 1078, + "compaction_pending_tasks": 0, + "dropped_messages": 0, + "jvm_gc_cms_count": 1, + "jvm_gc_cms_time": 59, + "jvm_gc_parnew_count": 218, + "jvm_gc_parnew_time": 1617, + "jvm_memory_heap_used": 1134866288, + "jvm_memory_nonheap_used": 96565696, + "key_cache_hit_ratio": 87273, + "key_cache_hits": 1336427, + "key_cache_misses": 194890, + "key_cache_size": 196559936, + "key_cache_utilization": 20828, + "row_cache_hit_ratio": 0, + "row_cache_hits": 0, + "row_cache_misses": 0, + "row_cache_size": 0, + "row_cache_utilization": 0, + "storage_exceptions": 0, + "storage_load": 858272986, + "thread_pool_CacheCleanupExecutor_active_tasks": 0, + "thread_pool_CacheCleanupExecutor_blocked_tasks": 0, + "thread_pool_CacheCleanupExecutor_pending_tasks": 0, + "thread_pool_CacheCleanupExecutor_total_blocked_tasks": 0, + "thread_pool_CompactionExecutor_active_tasks": 0, + "thread_pool_CompactionExecutor_blocked_tasks": 0, + "thread_pool_CompactionExecutor_pending_tasks": 0, + "thread_pool_CompactionExecutor_total_blocked_tasks": 0, + "thread_pool_GossipStage_active_tasks": 0, + "thread_pool_GossipStage_blocked_tasks": 0, + "thread_pool_GossipStage_pending_tasks": 0, + "thread_pool_GossipStage_total_blocked_tasks": 0, + "thread_pool_HintsDispatcher_active_tasks": 0, + "thread_pool_HintsDispatcher_blocked_tasks": 0, + "thread_pool_HintsDispatcher_pending_tasks": 0, + "thread_pool_HintsDispatcher_total_blocked_tasks": 0, + "thread_pool_MemtableFlushWriter_active_tasks": 0, + "thread_pool_MemtableFlushWriter_blocked_tasks": 0, + "thread_pool_MemtableFlushWriter_pending_tasks": 0, + "thread_pool_MemtableFlushWriter_total_blocked_tasks": 0, + "thread_pool_MemtablePostFlush_active_tasks": 0, + "thread_pool_MemtablePostFlush_blocked_tasks": 0, + "thread_pool_MemtablePostFlush_pending_tasks": 0, + "thread_pool_MemtablePostFlush_total_blocked_tasks": 0, + "thread_pool_MemtableReclaimMemory_active_tasks": 0, + "thread_pool_MemtableReclaimMemory_blocked_tasks": 0, + "thread_pool_MemtableReclaimMemory_pending_tasks": 0, + "thread_pool_MemtableReclaimMemory_total_blocked_tasks": 0, + "thread_pool_MutationStage_active_tasks": 0, + "thread_pool_MutationStage_blocked_tasks": 0, + "thread_pool_MutationStage_pending_tasks": 0, + "thread_pool_MutationStage_total_blocked_tasks": 0, + "thread_pool_Native-Transport-Requests_active_tasks": 0, + "thread_pool_Native-Transport-Requests_blocked_tasks": 0, + "thread_pool_Native-Transport-Requests_pending_tasks": 0, + "thread_pool_Native-Transport-Requests_total_blocked_tasks": 0, + "thread_pool_PendingRangeCalculator_active_tasks": 0, + "thread_pool_PendingRangeCalculator_blocked_tasks": 0, + "thread_pool_PendingRangeCalculator_pending_tasks": 0, + "thread_pool_PendingRangeCalculator_total_blocked_tasks": 0, + "thread_pool_PerDiskMemtableFlushWriter_0_active_tasks": 0, + "thread_pool_PerDiskMemtableFlushWriter_0_blocked_tasks": 0, + "thread_pool_PerDiskMemtableFlushWriter_0_pending_tasks": 0, + "thread_pool_PerDiskMemtableFlushWriter_0_total_blocked_tasks": 0, + "thread_pool_ReadStage_active_tasks": 0, + "thread_pool_ReadStage_blocked_tasks": 0, + "thread_pool_ReadStage_pending_tasks": 0, + "thread_pool_ReadStage_total_blocked_tasks": 0, + "thread_pool_Sampler_active_tasks": 0, + "thread_pool_Sampler_blocked_tasks": 0, + "thread_pool_Sampler_pending_tasks": 0, + "thread_pool_Sampler_total_blocked_tasks": 0, + "thread_pool_SecondaryIndexManagement_active_tasks": 0, + "thread_pool_SecondaryIndexManagement_blocked_tasks": 0, + "thread_pool_SecondaryIndexManagement_pending_tasks": 0, + "thread_pool_SecondaryIndexManagement_total_blocked_tasks": 0, + "thread_pool_ValidationExecutor_active_tasks": 0, + "thread_pool_ValidationExecutor_blocked_tasks": 0, + "thread_pool_ValidationExecutor_pending_tasks": 0, + "thread_pool_ValidationExecutor_total_blocked_tasks": 0, + "thread_pool_ViewBuildExecutor_active_tasks": 0, + "thread_pool_ViewBuildExecutor_blocked_tasks": 0, + "thread_pool_ViewBuildExecutor_pending_tasks": 0, + "thread_pool_ViewBuildExecutor_total_blocked_tasks": 0, + }, + }, + "fails if endpoint returns invalid data": { + prepare: prepareCassandraInvalidData, + }, + "fails on connection refused": { + prepare: prepareCassandraConnectionRefused, + }, + "fails on 404 response": { + prepare: prepareCassandraResponse404, + }, + } + + for name, test := range tests { + t.Run(name, func(t *testing.T) { + c, cleanup := test.prepare() + defer cleanup() + + require.NoError(t, c.Init()) + + mx := c.Collect() + + assert.Equal(t, test.wantCollected, mx) + }) + } +} + +func prepareCassandra() (c *Cassandra, cleanup func()) { + ts := httptest.NewServer(http.HandlerFunc( + func(w http.ResponseWriter, r *http.Request) { + _, _ = w.Write(dataExpectedMetrics) + })) + + c = New() + c.URL = ts.URL + return c, ts.Close +} + +func prepareCassandraInvalidData() (c *Cassandra, cleanup func()) { + ts := httptest.NewServer(http.HandlerFunc( + func(w http.ResponseWriter, r *http.Request) { + _, _ = w.Write([]byte("hello and\n goodbye")) + })) + + c = New() + c.URL = ts.URL + return c, ts.Close +} + +func prepareCassandraConnectionRefused() (c *Cassandra, cleanup func()) { + c = New() + c.URL = "http://127.0.0.1:38001" + return c, func() {} +} + +func prepareCassandraResponse404() (c *Cassandra, cleanup func()) { + ts := httptest.NewServer(http.HandlerFunc( + func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusNotFound) + })) + + c = New() + c.URL = ts.URL + return c, ts.Close +} diff --git a/src/go/plugin/go.d/modules/cassandra/charts.go b/src/go/plugin/go.d/modules/cassandra/charts.go new file mode 100644 index 000000000..a909c7ba0 --- /dev/null +++ b/src/go/plugin/go.d/modules/cassandra/charts.go @@ -0,0 +1,461 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +package cassandra + +import ( + "fmt" + + "github.com/netdata/netdata/go/plugins/plugin/go.d/agent/module" +) + +const ( + prioClientRequestsRate = module.Priority + iota + + prioClientRequestReadLatency + prioClientRequestWriteLatency + prioClientRequestsLatency + + prioKeyCacheHitRatio + prioRowCacheHitRatio + prioKeyCacheHitRate + prioRowCacheHitRate + prioKeyCacheUtilization + prioRowCacheUtilization + prioKeyCacheSize + prioRowCacheSize + + prioStorageLiveDiskSpaceUsed + + prioCompactionCompletedTasksRate + prioCompactionPendingTasksCount + prioCompactionBytesCompactedRate + + prioThreadPoolActiveTasksCount + prioThreadPoolPendingTasksCount + prioThreadPoolBlockedTasksCount + prioThreadPoolBlockedTasksRate + + prioJVMMemoryUsed + prioJVMGCCount + prioJVMGCTime + + prioDroppedMessagesRate + prioRequestsTimeoutsRate + prioRequestsUnavailablesRate + prioRequestsFailuresRate + prioStorageExceptionsRate +) + +var baseCharts = module.Charts{ + chartClientRequestsRate.Copy(), + + chartClientRequestsLatency.Copy(), + chartClientRequestReadLatencyHistogram.Copy(), + chartClientRequestWriteLatencyHistogram.Copy(), + + chartKeyCacheHitRatio.Copy(), + chartRowCacheHitRatio.Copy(), + chartKeyCacheHitRate.Copy(), + chartRowCacheHitRate.Copy(), + chartKeyCacheUtilization.Copy(), + chartRowCacheUtilization.Copy(), + chartKeyCacheSize.Copy(), + chartRowCacheSize.Copy(), + + chartStorageLiveDiskSpaceUsed.Copy(), + + chartCompactionCompletedTasksRate.Copy(), + chartCompactionPendingTasksCount.Copy(), + chartCompactionBytesCompactedRate.Copy(), + + chartJVMMemoryUsed.Copy(), + chartJVMGCRate.Copy(), + chartJVMGCTime.Copy(), + + chartDroppedMessagesRate.Copy(), + chartClientRequestTimeoutsRate.Copy(), + chartClientRequestUnavailablesRate.Copy(), + chartClientRequestFailuresRate.Copy(), + chartStorageExceptionsRate.Copy(), +} + +var ( + chartClientRequestsRate = module.Chart{ + ID: "client_requests_rate", + Title: "Client requests rate", + Units: "requests/s", + Fam: "throughput", + Ctx: "cassandra.client_requests_rate", + Priority: prioClientRequestsRate, + Dims: module.Dims{ + {ID: "client_request_latency_reads", Name: "read", Algo: module.Incremental}, + {ID: "client_request_latency_writes", Name: "write", Algo: module.Incremental, Mul: -1}, + }, + } +) + +var ( + chartClientRequestReadLatencyHistogram = module.Chart{ + ID: "client_request_read_latency_histogram", + Title: "Client request read latency histogram", + Units: "seconds", + Fam: "latency", + Ctx: "cassandra.client_request_read_latency_histogram", + Priority: prioClientRequestReadLatency, + Dims: module.Dims{ + {ID: "client_request_read_latency_p50", Name: "p50", Div: 1e6}, + {ID: "client_request_read_latency_p75", Name: "p75", Div: 1e6}, + {ID: "client_request_read_latency_p95", Name: "p95", Div: 1e6}, + {ID: "client_request_read_latency_p98", Name: "p98", Div: 1e6}, + {ID: "client_request_read_latency_p99", Name: "p99", Div: 1e6}, + {ID: "client_request_read_latency_p999", Name: "p999", Div: 1e6}, + }, + } + chartClientRequestWriteLatencyHistogram = module.Chart{ + ID: "client_request_write_latency_histogram", + Title: "Client request write latency histogram", + Units: "seconds", + Fam: "latency", + Ctx: "cassandra.client_request_write_latency_histogram", + Priority: prioClientRequestWriteLatency, + Dims: module.Dims{ + {ID: "client_request_write_latency_p50", Name: "p50", Div: 1e6}, + {ID: "client_request_write_latency_p75", Name: "p75", Div: 1e6}, + {ID: "client_request_write_latency_p95", Name: "p95", Div: 1e6}, + {ID: "client_request_write_latency_p98", Name: "p98", Div: 1e6}, + {ID: "client_request_write_latency_p99", Name: "p99", Div: 1e6}, + {ID: "client_request_write_latency_p999", Name: "p999", Div: 1e6}, + }, + } + chartClientRequestsLatency = module.Chart{ + ID: "client_requests_latency", + Title: "Client requests total latency", + Units: "seconds", + Fam: "latency", + Ctx: "cassandra.client_requests_latency", + Priority: prioClientRequestsLatency, + Dims: module.Dims{ + {ID: "client_request_total_latency_reads", Name: "read", Algo: module.Incremental, Div: 1e6}, + {ID: "client_request_total_latency_writes", Name: "write", Algo: module.Incremental, Div: 1e6}, + }, + } +) + +var ( + chartKeyCacheHitRatio = module.Chart{ + ID: "key_cache_hit_ratio", + Title: "Key cache hit ratio", + Units: "percentage", + Fam: "cache", + Ctx: "cassandra.key_cache_hit_ratio", + Priority: prioKeyCacheHitRatio, + Dims: module.Dims{ + {ID: "key_cache_hit_ratio", Name: "hit_ratio", Div: 1000}, + }, + } + chartKeyCacheHitRate = module.Chart{ + ID: "key_cache_hit_rate", + Title: "Key cache hit rate", + Units: "events/s", + Fam: "cache", + Ctx: "cassandra.key_cache_hit_rate", + Priority: prioKeyCacheHitRate, + Type: module.Stacked, + Dims: module.Dims{ + {ID: "key_cache_hits", Name: "hits", Algo: module.Incremental}, + {ID: "key_cache_misses", Name: "misses", Algo: module.Incremental}, + }, + } + chartKeyCacheUtilization = module.Chart{ + ID: "key_cache_utilization", + Title: "Key cache utilization", + Units: "percentage", + Fam: "cache", + Ctx: "cassandra.key_cache_utilization", + Priority: prioKeyCacheUtilization, + Dims: module.Dims{ + {ID: "key_cache_utilization", Name: "used", Div: 1000}, + }, + } + chartKeyCacheSize = module.Chart{ + ID: "key_cache_size", + Title: "Key cache size", + Units: "bytes", + Fam: "cache", + Ctx: "cassandra.key_cache_size", + Priority: prioKeyCacheSize, + Dims: module.Dims{ + {ID: "key_cache_size", Name: "size"}, + }, + } + + chartRowCacheHitRatio = module.Chart{ + ID: "row_cache_hit_ratio", + Title: "Row cache hit ratio", + Units: "percentage", + Fam: "cache", + Ctx: "cassandra.row_cache_hit_ratio", + Priority: prioRowCacheHitRatio, + Dims: module.Dims{ + {ID: "row_cache_hit_ratio", Name: "hit_ratio", Div: 1000}, + }, + } + chartRowCacheHitRate = module.Chart{ + ID: "row_cache_hit_rate", + Title: "Row cache hit rate", + Units: "events/s", + Fam: "cache", + Ctx: "cassandra.row_cache_hit_rate", + Priority: prioRowCacheHitRate, + Type: module.Stacked, + Dims: module.Dims{ + {ID: "row_cache_hits", Name: "hits", Algo: module.Incremental}, + {ID: "row_cache_misses", Name: "misses", Algo: module.Incremental}, + }, + } + chartRowCacheUtilization = module.Chart{ + ID: "row_cache_utilization", + Title: "Row cache utilization", + Units: "percentage", + Fam: "cache", + Ctx: "cassandra.row_cache_utilization", + Priority: prioRowCacheUtilization, + Dims: module.Dims{ + {ID: "row_cache_utilization", Name: "used", Div: 1000}, + }, + } + chartRowCacheSize = module.Chart{ + ID: "row_cache_size", + Title: "Row cache size", + Units: "bytes", + Fam: "cache", + Ctx: "cassandra.row_cache_size", + Priority: prioRowCacheSize, + Dims: module.Dims{ + {ID: "row_cache_size", Name: "size"}, + }, + } +) + +var ( + chartStorageLiveDiskSpaceUsed = module.Chart{ + ID: "storage_live_disk_space_used", + Title: "Disk space used by live data", + Units: "bytes", + Fam: "disk usage", + Ctx: "cassandra.storage_live_disk_space_used", + Priority: prioStorageLiveDiskSpaceUsed, + Dims: module.Dims{ + {ID: "storage_load", Name: "used"}, + }, + } +) + +var ( + chartCompactionCompletedTasksRate = module.Chart{ + ID: "compaction_completed_tasks_rate", + Title: "Completed compactions rate", + Units: "tasks/s", + Fam: "compaction", + Ctx: "cassandra.compaction_completed_tasks_rate", + Priority: prioCompactionCompletedTasksRate, + Dims: module.Dims{ + {ID: "compaction_completed_tasks", Name: "completed", Algo: module.Incremental}, + }, + } + chartCompactionPendingTasksCount = module.Chart{ + ID: "compaction_pending_tasks_count", + Title: "Pending compactions", + Units: "tasks", + Fam: "compaction", + Ctx: "cassandra.compaction_pending_tasks_count", + Priority: prioCompactionPendingTasksCount, + Dims: module.Dims{ + {ID: "compaction_pending_tasks", Name: "pending"}, + }, + } + chartCompactionBytesCompactedRate = module.Chart{ + ID: "compaction_compacted_rate", + Title: "Compaction data rate", + Units: "bytes/s", + Fam: "compaction", + Ctx: "cassandra.compaction_compacted_rate", + Priority: prioCompactionBytesCompactedRate, + Dims: module.Dims{ + {ID: "compaction_bytes_compacted", Name: "compacted", Algo: module.Incremental}, + }, + } +) + +var ( + chartsTmplThreadPool = module.Charts{ + chartTmplThreadPoolActiveTasksCount.Copy(), + chartTmplThreadPoolPendingTasksCount.Copy(), + chartTmplThreadPoolBlockedTasksCount.Copy(), + chartTmplThreadPoolBlockedTasksRate.Copy(), + } + + chartTmplThreadPoolActiveTasksCount = module.Chart{ + ID: "thread_pool_%s_active_tasks_count", + Title: "Active tasks", + Units: "tasks", + Fam: "thread pools", + Ctx: "cassandra.thread_pool_active_tasks_count", + Priority: prioThreadPoolActiveTasksCount, + Dims: module.Dims{ + {ID: "thread_pool_%s_active_tasks", Name: "active"}, + }, + } + chartTmplThreadPoolPendingTasksCount = module.Chart{ + ID: "thread_pool_%s_pending_tasks_count", + Title: "Pending tasks", + Units: "tasks", + Fam: "thread pools", + Ctx: "cassandra.thread_pool_pending_tasks_count", + Priority: prioThreadPoolPendingTasksCount, + Dims: module.Dims{ + {ID: "thread_pool_%s_pending_tasks", Name: "pending"}, + }, + } + chartTmplThreadPoolBlockedTasksCount = module.Chart{ + ID: "thread_pool_%s_blocked_tasks_count", + Title: "Blocked tasks", + Units: "tasks", + Fam: "thread pools", + Ctx: "cassandra.thread_pool_blocked_tasks_count", + Priority: prioThreadPoolBlockedTasksCount, + Dims: module.Dims{ + {ID: "thread_pool_%s_blocked_tasks", Name: "blocked"}, + }, + } + chartTmplThreadPoolBlockedTasksRate = module.Chart{ + ID: "thread_pool_%s_blocked_tasks_rate", + Title: "Blocked tasks rate", + Units: "tasks/s", + Fam: "thread pools", + Ctx: "cassandra.thread_pool_blocked_tasks_rate", + Priority: prioThreadPoolBlockedTasksRate, + Dims: module.Dims{ + {ID: "thread_pool_%s_total_blocked_tasks", Name: "blocked", Algo: module.Incremental}, + }, + } +) + +var ( + chartJVMMemoryUsed = module.Chart{ + ID: "jvm_memory_used", + Title: "Memory used", + Units: "bytes", + Fam: "jvm runtime", + Ctx: "cassandra.jvm_memory_used", + Priority: prioJVMMemoryUsed, + Type: module.Stacked, + Dims: module.Dims{ + {ID: "jvm_memory_heap_used", Name: "heap"}, + {ID: "jvm_memory_nonheap_used", Name: "nonheap"}, + }, + } + chartJVMGCRate = module.Chart{ + ID: "jvm_gc_rate", + Title: "Garbage collections rate", + Units: "gc/s", + Fam: "jvm runtime", + Ctx: "cassandra.jvm_gc_rate", + Priority: prioJVMGCCount, + Dims: module.Dims{ + {ID: "jvm_gc_parnew_count", Name: "parnew", Algo: module.Incremental}, + {ID: "jvm_gc_cms_count", Name: "cms", Algo: module.Incremental}, + }, + } + chartJVMGCTime = module.Chart{ + ID: "jvm_gc_time", + Title: "Garbage collection time", + Units: "seconds", + Fam: "jvm runtime", + Ctx: "cassandra.jvm_gc_time", + Priority: prioJVMGCTime, + Dims: module.Dims{ + {ID: "jvm_gc_parnew_time", Name: "parnew", Algo: module.Incremental, Div: 1e9}, + {ID: "jvm_gc_cms_time", Name: "cms", Algo: module.Incremental, Div: 1e9}, + }, + } +) + +var ( + chartDroppedMessagesRate = module.Chart{ + ID: "dropped_messages_rate", + Title: "Dropped messages rate", + Units: "messages/s", + Fam: "errors", + Ctx: "cassandra.dropped_messages_rate", + Priority: prioDroppedMessagesRate, + Dims: module.Dims{ + {ID: "dropped_messages", Name: "dropped"}, + }, + } + chartClientRequestTimeoutsRate = module.Chart{ + ID: "client_requests_timeouts_rate", + Title: "Client requests timeouts rate", + Units: "timeouts/s", + Fam: "errors", + Ctx: "cassandra.client_requests_timeouts_rate", + Priority: prioRequestsTimeoutsRate, + Dims: module.Dims{ + {ID: "client_request_timeouts_reads", Name: "read", Algo: module.Incremental}, + {ID: "client_request_timeouts_writes", Name: "write", Algo: module.Incremental, Mul: -1}, + }, + } + chartClientRequestUnavailablesRate = module.Chart{ + ID: "client_requests_unavailables_rate", + Title: "Client requests unavailable exceptions rate", + Units: "exceptions/s", + Fam: "errors", + Ctx: "cassandra.client_requests_unavailables_rate", + Priority: prioRequestsUnavailablesRate, + Dims: module.Dims{ + {ID: "client_request_unavailables_reads", Name: "read", Algo: module.Incremental}, + {ID: "client_request_unavailables_writes", Name: "write", Algo: module.Incremental, Mul: -1}, + }, + } + chartClientRequestFailuresRate = module.Chart{ + ID: "client_requests_failures_rate", + Title: "Client requests failures rate", + Units: "failures/s", + Fam: "errors", + Ctx: "cassandra.client_requests_failures_rate", + Priority: prioRequestsFailuresRate, + Dims: module.Dims{ + {ID: "client_request_failures_reads", Name: "read", Algo: module.Incremental}, + {ID: "client_request_failures_writes", Name: "write", Algo: module.Incremental, Mul: -1}, + }, + } + chartStorageExceptionsRate = module.Chart{ + ID: "storage_exceptions_rate", + Title: "Storage exceptions rate", + Units: "exceptions/s", + Fam: "errors", + Ctx: "cassandra.storage_exceptions_rate", + Priority: prioStorageExceptionsRate, + Dims: module.Dims{ + {ID: "storage_exceptions", Name: "storage", Algo: module.Incremental}, + }, + } +) + +func (c *Cassandra) addThreadPoolCharts(pool *threadPoolMetrics) { + charts := chartsTmplThreadPool.Copy() + + for _, chart := range *charts { + chart.ID = fmt.Sprintf(chart.ID, pool.name) + chart.Labels = []module.Label{ + {Key: "thread_pool", Value: pool.name}, + } + for _, dim := range chart.Dims { + dim.ID = fmt.Sprintf(dim.ID, pool.name) + } + } + + if err := c.Charts().Add(*charts...); err != nil { + c.Warning(err) + } +} diff --git a/src/go/plugin/go.d/modules/cassandra/collect.go b/src/go/plugin/go.d/modules/cassandra/collect.go new file mode 100644 index 000000000..08cdfbe94 --- /dev/null +++ b/src/go/plugin/go.d/modules/cassandra/collect.go @@ -0,0 +1,403 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +package cassandra + +import ( + "errors" + "github.com/netdata/netdata/go/plugins/plugin/go.d/pkg/prometheus" + "strings" +) + +const ( + suffixCount = "_count" + suffixValue = "_value" +) + +func (c *Cassandra) collect() (map[string]int64, error) { + pms, err := c.prom.ScrapeSeries() + if err != nil { + return nil, err + } + + if c.validateMetrics { + if !isCassandraMetrics(pms) { + return nil, errors.New("collected metrics aren't Cassandra metrics") + } + c.validateMetrics = false + } + + mx := make(map[string]int64) + + c.resetMetrics() + c.collectMetrics(pms) + c.processMetric(mx) + + return mx, nil +} + +func (c *Cassandra) resetMetrics() { + cm := newCassandraMetrics() + for key, p := range c.mx.threadPools { + cm.threadPools[key] = &threadPoolMetrics{ + name: p.name, + hasCharts: p.hasCharts, + } + } + c.mx = cm +} + +func (c *Cassandra) processMetric(mx map[string]int64) { + c.mx.clientReqTotalLatencyReads.write(mx, "client_request_total_latency_reads") + c.mx.clientReqTotalLatencyWrites.write(mx, "client_request_total_latency_writes") + c.mx.clientReqLatencyReads.write(mx, "client_request_latency_reads") + c.mx.clientReqLatencyWrites.write(mx, "client_request_latency_writes") + c.mx.clientReqTimeoutsReads.write(mx, "client_request_timeouts_reads") + c.mx.clientReqTimeoutsWrites.write(mx, "client_request_timeouts_writes") + c.mx.clientReqUnavailablesReads.write(mx, "client_request_unavailables_reads") + c.mx.clientReqUnavailablesWrites.write(mx, "client_request_unavailables_writes") + c.mx.clientReqFailuresReads.write(mx, "client_request_failures_reads") + c.mx.clientReqFailuresWrites.write(mx, "client_request_failures_writes") + + c.mx.clientReqReadLatencyP50.write(mx, "client_request_read_latency_p50") + c.mx.clientReqReadLatencyP75.write(mx, "client_request_read_latency_p75") + c.mx.clientReqReadLatencyP95.write(mx, "client_request_read_latency_p95") + c.mx.clientReqReadLatencyP98.write(mx, "client_request_read_latency_p98") + c.mx.clientReqReadLatencyP99.write(mx, "client_request_read_latency_p99") + c.mx.clientReqReadLatencyP999.write(mx, "client_request_read_latency_p999") + c.mx.clientReqWriteLatencyP50.write(mx, "client_request_write_latency_p50") + c.mx.clientReqWriteLatencyP75.write(mx, "client_request_write_latency_p75") + c.mx.clientReqWriteLatencyP95.write(mx, "client_request_write_latency_p95") + c.mx.clientReqWriteLatencyP98.write(mx, "client_request_write_latency_p98") + c.mx.clientReqWriteLatencyP99.write(mx, "client_request_write_latency_p99") + c.mx.clientReqWriteLatencyP999.write(mx, "client_request_write_latency_p999") + + c.mx.rowCacheHits.write(mx, "row_cache_hits") + c.mx.rowCacheMisses.write(mx, "row_cache_misses") + c.mx.rowCacheSize.write(mx, "row_cache_size") + if c.mx.rowCacheHits.isSet && c.mx.rowCacheMisses.isSet { + if s := c.mx.rowCacheHits.value + c.mx.rowCacheMisses.value; s > 0 { + mx["row_cache_hit_ratio"] = int64((c.mx.rowCacheHits.value * 100 / s) * 1000) + } else { + mx["row_cache_hit_ratio"] = 0 + } + } + if c.mx.rowCacheCapacity.isSet && c.mx.rowCacheSize.isSet { + if s := c.mx.rowCacheCapacity.value; s > 0 { + mx["row_cache_utilization"] = int64((c.mx.rowCacheSize.value * 100 / s) * 1000) + } else { + mx["row_cache_utilization"] = 0 + } + } + + c.mx.keyCacheHits.write(mx, "key_cache_hits") + c.mx.keyCacheMisses.write(mx, "key_cache_misses") + c.mx.keyCacheSize.write(mx, "key_cache_size") + if c.mx.keyCacheHits.isSet && c.mx.keyCacheMisses.isSet { + if s := c.mx.keyCacheHits.value + c.mx.keyCacheMisses.value; s > 0 { + mx["key_cache_hit_ratio"] = int64((c.mx.keyCacheHits.value * 100 / s) * 1000) + } else { + mx["key_cache_hit_ratio"] = 0 + } + } + if c.mx.keyCacheCapacity.isSet && c.mx.keyCacheSize.isSet { + if s := c.mx.keyCacheCapacity.value; s > 0 { + mx["key_cache_utilization"] = int64((c.mx.keyCacheSize.value * 100 / s) * 1000) + } else { + mx["key_cache_utilization"] = 0 + } + } + + c.mx.droppedMessages.write1k(mx, "dropped_messages") + + c.mx.storageLoad.write(mx, "storage_load") + c.mx.storageExceptions.write(mx, "storage_exceptions") + + c.mx.compactionBytesCompacted.write(mx, "compaction_bytes_compacted") + c.mx.compactionPendingTasks.write(mx, "compaction_pending_tasks") + c.mx.compactionCompletedTasks.write(mx, "compaction_completed_tasks") + + c.mx.jvmMemoryHeapUsed.write(mx, "jvm_memory_heap_used") + c.mx.jvmMemoryNonHeapUsed.write(mx, "jvm_memory_nonheap_used") + c.mx.jvmGCParNewCount.write(mx, "jvm_gc_parnew_count") + c.mx.jvmGCParNewTime.write1k(mx, "jvm_gc_parnew_time") + c.mx.jvmGCCMSCount.write(mx, "jvm_gc_cms_count") + c.mx.jvmGCCMSTime.write1k(mx, "jvm_gc_cms_time") + + for _, p := range c.mx.threadPools { + if !p.hasCharts { + p.hasCharts = true + c.addThreadPoolCharts(p) + } + + px := "thread_pool_" + p.name + "_" + p.activeTasks.write(mx, px+"active_tasks") + p.pendingTasks.write(mx, px+"pending_tasks") + p.blockedTasks.write(mx, px+"blocked_tasks") + p.totalBlockedTasks.write(mx, px+"total_blocked_tasks") + } +} + +func (c *Cassandra) collectMetrics(pms prometheus.Series) { + c.collectClientRequestMetrics(pms) + c.collectDroppedMessagesMetrics(pms) + c.collectThreadPoolsMetrics(pms) + c.collectStorageMetrics(pms) + c.collectCacheMetrics(pms) + c.collectJVMMetrics(pms) + c.collectCompactionMetrics(pms) +} + +func (c *Cassandra) collectClientRequestMetrics(pms prometheus.Series) { + const metric = "org_apache_cassandra_metrics_clientrequest" + + var rw struct{ read, write *metricValue } + for _, pm := range pms.FindByName(metric + suffixCount) { + name := pm.Labels.Get("name") + scope := pm.Labels.Get("scope") + + switch name { + case "TotalLatency": + rw.read, rw.write = &c.mx.clientReqTotalLatencyReads, &c.mx.clientReqTotalLatencyWrites + case "Latency": + rw.read, rw.write = &c.mx.clientReqLatencyReads, &c.mx.clientReqLatencyWrites + case "Timeouts": + rw.read, rw.write = &c.mx.clientReqTimeoutsReads, &c.mx.clientReqTimeoutsWrites + case "Unavailables": + rw.read, rw.write = &c.mx.clientReqUnavailablesReads, &c.mx.clientReqUnavailablesWrites + case "Failures": + rw.read, rw.write = &c.mx.clientReqFailuresReads, &c.mx.clientReqFailuresWrites + default: + continue + } + + switch scope { + case "Read": + rw.read.add(pm.Value) + case "Write": + rw.write.add(pm.Value) + } + } + + rw = struct{ read, write *metricValue }{} + + for _, pm := range pms.FindByNames( + metric+"_50thpercentile", + metric+"_75thpercentile", + metric+"_95thpercentile", + metric+"_98thpercentile", + metric+"_99thpercentile", + metric+"_999thpercentile", + ) { + name := pm.Labels.Get("name") + scope := pm.Labels.Get("scope") + + if name != "Latency" { + continue + } + + switch { + case strings.HasSuffix(pm.Name(), "_50thpercentile"): + rw.read, rw.write = &c.mx.clientReqReadLatencyP50, &c.mx.clientReqWriteLatencyP50 + case strings.HasSuffix(pm.Name(), "_75thpercentile"): + rw.read, rw.write = &c.mx.clientReqReadLatencyP75, &c.mx.clientReqWriteLatencyP75 + case strings.HasSuffix(pm.Name(), "_95thpercentile"): + rw.read, rw.write = &c.mx.clientReqReadLatencyP95, &c.mx.clientReqWriteLatencyP95 + case strings.HasSuffix(pm.Name(), "_98thpercentile"): + rw.read, rw.write = &c.mx.clientReqReadLatencyP98, &c.mx.clientReqWriteLatencyP98 + case strings.HasSuffix(pm.Name(), "_99thpercentile"): + rw.read, rw.write = &c.mx.clientReqReadLatencyP99, &c.mx.clientReqWriteLatencyP99 + case strings.HasSuffix(pm.Name(), "_999thpercentile"): + rw.read, rw.write = &c.mx.clientReqReadLatencyP999, &c.mx.clientReqWriteLatencyP999 + default: + continue + } + + switch scope { + case "Read": + rw.read.add(pm.Value) + case "Write": + rw.write.add(pm.Value) + } + } +} + +func (c *Cassandra) collectCacheMetrics(pms prometheus.Series) { + const metric = "org_apache_cassandra_metrics_cache" + + var hm struct{ hits, misses *metricValue } + for _, pm := range pms.FindByName(metric + suffixCount) { + name := pm.Labels.Get("name") + scope := pm.Labels.Get("scope") + + switch scope { + case "KeyCache": + hm.hits, hm.misses = &c.mx.keyCacheHits, &c.mx.keyCacheMisses + case "RowCache": + hm.hits, hm.misses = &c.mx.rowCacheHits, &c.mx.rowCacheMisses + default: + continue + } + + switch name { + case "Hits": + hm.hits.add(pm.Value) + case "Misses": + hm.misses.add(pm.Value) + } + } + + var cs struct{ cap, size *metricValue } + for _, pm := range pms.FindByName(metric + suffixValue) { + name := pm.Labels.Get("name") + scope := pm.Labels.Get("scope") + + switch scope { + case "KeyCache": + cs.cap, cs.size = &c.mx.keyCacheCapacity, &c.mx.keyCacheSize + case "RowCache": + cs.cap, cs.size = &c.mx.rowCacheCapacity, &c.mx.rowCacheSize + default: + continue + } + + switch name { + case "Capacity": + cs.cap.add(pm.Value) + case "Size": + cs.size.add(pm.Value) + } + } +} + +func (c *Cassandra) collectThreadPoolsMetrics(pms prometheus.Series) { + const metric = "org_apache_cassandra_metrics_threadpools" + + for _, pm := range pms.FindByName(metric + suffixValue) { + name := pm.Labels.Get("name") + scope := pm.Labels.Get("scope") + pool := c.getThreadPoolMetrics(scope) + + switch name { + case "ActiveTasks": + pool.activeTasks.add(pm.Value) + case "PendingTasks": + pool.pendingTasks.add(pm.Value) + } + } + for _, pm := range pms.FindByName(metric + suffixCount) { + name := pm.Labels.Get("name") + scope := pm.Labels.Get("scope") + pool := c.getThreadPoolMetrics(scope) + + switch name { + case "CompletedTasks": + pool.totalBlockedTasks.add(pm.Value) + case "TotalBlockedTasks": + pool.totalBlockedTasks.add(pm.Value) + case "CurrentlyBlockedTasks": + pool.blockedTasks.add(pm.Value) + } + } +} + +func (c *Cassandra) collectStorageMetrics(pms prometheus.Series) { + const metric = "org_apache_cassandra_metrics_storage" + + for _, pm := range pms.FindByName(metric + suffixCount) { + name := pm.Labels.Get("name") + + switch name { + case "Load": + c.mx.storageLoad.add(pm.Value) + case "Exceptions": + c.mx.storageExceptions.add(pm.Value) + } + } +} + +func (c *Cassandra) collectDroppedMessagesMetrics(pms prometheus.Series) { + const metric = "org_apache_cassandra_metrics_droppedmessage" + + for _, pm := range pms.FindByName(metric + suffixCount) { + c.mx.droppedMessages.add(pm.Value) + } +} + +func (c *Cassandra) collectJVMMetrics(pms prometheus.Series) { + const metricMemUsed = "jvm_memory_bytes_used" + const metricGC = "jvm_gc_collection_seconds" + + for _, pm := range pms.FindByName(metricMemUsed) { + area := pm.Labels.Get("area") + + switch area { + case "heap": + c.mx.jvmMemoryHeapUsed.add(pm.Value) + case "nonheap": + c.mx.jvmMemoryNonHeapUsed.add(pm.Value) + } + } + + for _, pm := range pms.FindByName(metricGC + suffixCount) { + gc := pm.Labels.Get("gc") + + switch gc { + case "ParNew": + c.mx.jvmGCParNewCount.add(pm.Value) + case "ConcurrentMarkSweep": + c.mx.jvmGCCMSCount.add(pm.Value) + } + } + + for _, pm := range pms.FindByName(metricGC + "_sum") { + gc := pm.Labels.Get("gc") + + switch gc { + case "ParNew": + c.mx.jvmGCParNewTime.add(pm.Value) + case "ConcurrentMarkSweep": + c.mx.jvmGCCMSTime.add(pm.Value) + } + } +} + +func (c *Cassandra) collectCompactionMetrics(pms prometheus.Series) { + const metric = "org_apache_cassandra_metrics_compaction" + + for _, pm := range pms.FindByName(metric + suffixValue) { + name := pm.Labels.Get("name") + + switch name { + case "CompletedTasks": + c.mx.compactionCompletedTasks.add(pm.Value) + case "PendingTasks": + c.mx.compactionPendingTasks.add(pm.Value) + } + } + for _, pm := range pms.FindByName(metric + suffixCount) { + name := pm.Labels.Get("name") + + switch name { + case "BytesCompacted": + c.mx.compactionBytesCompacted.add(pm.Value) + } + } +} + +func (c *Cassandra) getThreadPoolMetrics(name string) *threadPoolMetrics { + pool, ok := c.mx.threadPools[name] + if !ok { + pool = &threadPoolMetrics{name: name} + c.mx.threadPools[name] = pool + } + return pool +} + +func isCassandraMetrics(pms prometheus.Series) bool { + for _, pm := range pms { + if strings.HasPrefix(pm.Name(), "org_apache_cassandra_metrics") { + return true + } + } + return false +} diff --git a/src/go/plugin/go.d/modules/cassandra/config_schema.json b/src/go/plugin/go.d/modules/cassandra/config_schema.json new file mode 100644 index 000000000..c4ca5f4f9 --- /dev/null +++ b/src/go/plugin/go.d/modules/cassandra/config_schema.json @@ -0,0 +1,183 @@ +{ + "jsonSchema": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Cassandra 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 Cassandra [JMX exporter](https://github.com/prometheus/jmx_exporter) metrics endpoint.", + "type": "string", + "default": "http://127.0.0.1:7072/metrics", + "format": "uri" + }, + "timeout": { + "title": "Timeout", + "description": "The timeout in seconds for the HTTP request.", + "type": "number", + "minimum": 0.5, + "default": 5 + }, + "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/cassandra/init.go b/src/go/plugin/go.d/modules/cassandra/init.go new file mode 100644 index 000000000..1a74fdf9b --- /dev/null +++ b/src/go/plugin/go.d/modules/cassandra/init.go @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +package cassandra + +import ( + "errors" + + "github.com/netdata/netdata/go/plugins/plugin/go.d/pkg/prometheus" + "github.com/netdata/netdata/go/plugins/plugin/go.d/pkg/web" +) + +func (c *Cassandra) validateConfig() error { + if c.URL == "" { + return errors.New("'url' is not set") + } + return nil +} + +func (c *Cassandra) initPrometheusClient() (prometheus.Prometheus, error) { + client, err := web.NewHTTPClient(c.Client) + if err != nil { + return nil, err + } + return prometheus.New(client, c.Request), nil +} diff --git a/src/go/plugin/go.d/modules/cassandra/integrations/cassandra.md b/src/go/plugin/go.d/modules/cassandra/integrations/cassandra.md new file mode 100644 index 000000000..61c4d1439 --- /dev/null +++ b/src/go/plugin/go.d/modules/cassandra/integrations/cassandra.md @@ -0,0 +1,313 @@ +<!--startmeta +custom_edit_url: "https://github.com/netdata/netdata/edit/master/src/go/plugin/go.d/modules/cassandra/README.md" +meta_yaml: "https://github.com/netdata/netdata/edit/master/src/go/plugin/go.d/modules/cassandra/metadata.yaml" +sidebar_label: "Cassandra" +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--> + +# Cassandra + + +<img src="https://netdata.cloud/img/cassandra.svg" width="150"/> + + +Plugin: go.d.plugin +Module: cassandra + +<img src="https://img.shields.io/badge/maintained%20by-Netdata-%2300ab44" /> + +## Overview + +This collector gathers metrics about client requests, cache hits, and many more, while also providing metrics per each thread pool. + + +The [JMX Exporter](https://github.com/prometheus/jmx_exporter) is used to fetch metrics from a Cassandra instance and make them available at an endpoint like `http://127.0.0.1:7072/metrics`. + + +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 collector discovers instances running on the local host that provide metrics on port 7072. + +On startup, it tries to collect metrics from: + +- http://127.0.0.1:7072/metrics + + +#### 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 Cassandra instance + +These metrics refer to the entire monitored application. + +This scope has no labels. + +Metrics: + +| Metric | Dimensions | Unit | +|:------|:----------|:----| +| cassandra.client_requests_rate | read, write | requests/s | +| cassandra.client_request_read_latency_histogram | p50, p75, p95, p98, p99, p999 | seconds | +| cassandra.client_request_write_latency_histogram | p50, p75, p95, p98, p99, p999 | seconds | +| cassandra.client_requests_latency | read, write | seconds | +| cassandra.row_cache_hit_ratio | hit_ratio | percentage | +| cassandra.row_cache_hit_rate | hits, misses | events/s | +| cassandra.row_cache_utilization | used | percentage | +| cassandra.row_cache_size | size | bytes | +| cassandra.key_cache_hit_ratio | hit_ratio | percentage | +| cassandra.key_cache_hit_rate | hits, misses | events/s | +| cassandra.key_cache_utilization | used | percentage | +| cassandra.key_cache_size | size | bytes | +| cassandra.storage_live_disk_space_used | used | bytes | +| cassandra.compaction_completed_tasks_rate | completed | tasks/s | +| cassandra.compaction_pending_tasks_count | pending | tasks | +| cassandra.compaction_compacted_rate | compacted | bytes/s | +| cassandra.jvm_memory_used | heap, nonheap | bytes | +| cassandra.jvm_gc_rate | parnew, cms | gc/s | +| cassandra.jvm_gc_time | parnew, cms | seconds | +| cassandra.dropped_messages_rate | dropped | messages/s | +| cassandra.client_requests_timeouts_rate | read, write | timeout/s | +| cassandra.client_requests_unavailables_rate | read, write | exceptions/s | +| cassandra.client_requests_failures_rate | read, write | failures/s | +| cassandra.storage_exceptions_rate | storage | exceptions/s | + +### Per thread pool + +Metrics related to Cassandra's thread pools. Each thread pool provides its own set of the following metrics. + +Labels: + +| Label | Description | +|:-----------|:----------------| +| thread_pool | thread pool name | + +Metrics: + +| Metric | Dimensions | Unit | +|:------|:----------|:----| +| cassandra.thread_pool_active_tasks_count | active | tasks | +| cassandra.thread_pool_pending_tasks_count | pending | tasks | +| cassandra.thread_pool_blocked_tasks_count | blocked | tasks | +| cassandra.thread_pool_blocked_tasks_rate | blocked | tasks/s | + + + +## Alerts + +There are no alerts configured by default for this integration. + + +## Setup + +### Prerequisites + +#### Configure Cassandra with Prometheus JMX Exporter + +To configure Cassandra with the [JMX Exporter](https://github.com/prometheus/jmx_exporter): + +> **Note**: paths can differ depends on your setup. + +- Download latest [jmx_exporter](https://repo1.maven.org/maven2/io/prometheus/jmx/jmx_prometheus_javaagent/) jar file + and install it in a directory where Cassandra can access it. +- Add + the [jmx_exporter.yaml](https://raw.githubusercontent.com/netdata/go.d.plugin/master/modules/cassandra/jmx_exporter.yaml) + file to `/etc/cassandra`. +- Add the following line to `/etc/cassandra/cassandra-env.sh` + ``` + JVM_OPTS="$JVM_OPTS $JVM_EXTRA_OPTS -javaagent:/opt/jmx_exporter/jmx_exporter.jar=7072:/etc/cassandra/jmx_exporter.yaml + ``` +- Restart cassandra service. + + + +### Configuration + +#### File + +The configuration file name for this integration is `go.d/cassandra.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/cassandra.conf +``` +#### Options + +The following options can be defined globally: update_every, autodetection_retry. + + +<details open><summary>Config options</summary> + +| Name | Description | Default | Required | +|:----|:-----------|:-------|:--------:| +| update_every | Data collection frequency. | 5 | no | +| autodetection_retry | Recheck interval in seconds. Zero means no recheck will be scheduled. | 0 | no | +| url | Server URL. | http://127.0.0.1:7072/metrics | 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 | +| 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 + +A basic example configuration. + +```yaml +jobs: + - name: local + url: http://127.0.0.1:7072/metrics + +``` +##### HTTP authentication + +Local server with basic HTTP authentication. + +<details open><summary>Config</summary> + +```yaml +jobs: + - name: local + url: http://127.0.0.1:7072/metrics + username: foo + password: bar + +``` +</details> + +##### HTTPS with self-signed certificate + +Local server with enabled HTTPS and self-signed certificate. + +<details open><summary>Config</summary> + +```yaml +jobs: + - name: local + url: https://127.0.0.1:7072/metrics + tls_skip_verify: yes + +``` +</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:7072/metrics + + - name: remote + url: http://192.0.2.1:7072/metrics + +``` +</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 `cassandra` 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 cassandra + ``` + +### Getting Logs + +If you're encountering problems with the `cassandra` 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 cassandra +``` + +#### 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 cassandra /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 cassandra +``` + + diff --git a/src/go/plugin/go.d/modules/cassandra/jmx_exporter.yaml b/src/go/plugin/go.d/modules/cassandra/jmx_exporter.yaml new file mode 100644 index 000000000..983f6f9b2 --- /dev/null +++ b/src/go/plugin/go.d/modules/cassandra/jmx_exporter.yaml @@ -0,0 +1,31 @@ +lowercaseOutputLabelNames: true +lowercaseOutputName: true +whitelistObjectNames: ["org.apache.cassandra.metrics:*"] +blacklistObjectNames: + - "org.apache.cassandra.metrics:type=ColumnFamily,*" + - "org.apache.cassandra.metrics:type=Table,*" +rules: + # Throughput and Latency + - pattern: org.apache.cassandra.metrics<type=(ClientRequest), scope=(Write|Read), name=(TotalLatency|Latency|Timeouts|Unavailables|Failures)><>(Count) + - pattern: org.apache.cassandra.metrics<type=(ClientRequest), scope=(Write|Read), name=(Latency)><>(\S*Percentile) + + # Dropped messages + - pattern: org.apache.cassandra.metrics<type=(DroppedMessage), scope=(\S*), name=(Dropped)><>(Count) + + # Cache + - pattern: org.apache.cassandra.metrics<type=Cache, scope=(KeyCache|RowCache), name=(Hits|Misses)><>(Count) + - pattern: org.apache.cassandra.metrics<type=Cache, scope=(KeyCache|RowCache), name=(Capacity|Size)><>(Value) + + # Storage + - pattern: org.apache.cassandra.metrics<type=(Storage), name=(Load|Exceptions)><>(Count) + + # Tables + # - pattern: org.apache.cassandra.metrics<type=(Table), keyspace=(\S*), scope=(\S*), name=(TotalDiskSpaceUsed)><>(Count) + + # Compaction + - pattern: org.apache.cassandra.metrics<type=(Compaction), name=(CompletedTasks|PendingTasks)><>(Value) + - pattern: org.apache.cassandra.metrics<type=(Compaction), name=(BytesCompacted)><>(Count) + + # Thread Pools + - pattern: org.apache.cassandra.metrics<type=(ThreadPools), path=(\S*), scope=(\S*), name=(ActiveTasks|PendingTasks)><>(Value) + - pattern: org.apache.cassandra.metrics<type=(ThreadPools), path=(\S*), scope=(\S*), name=(CurrentlyBlockedTasks|TotalBlockedTasks)><>(Count) diff --git a/src/go/plugin/go.d/modules/cassandra/metadata.yaml b/src/go/plugin/go.d/modules/cassandra/metadata.yaml new file mode 100644 index 000000000..ef9458c03 --- /dev/null +++ b/src/go/plugin/go.d/modules/cassandra/metadata.yaml @@ -0,0 +1,410 @@ +plugin_name: go.d.plugin +modules: + - meta: + id: collector-go.d.plugin-cassandra + module_name: cassandra + plugin_name: go.d.plugin + monitored_instance: + categories: + - data-collection.database-servers + icon_filename: cassandra.svg + name: Cassandra + link: https://cassandra.apache.org/_/index.html + alternative_monitored_instances: [] + keywords: + - nosql + - dbms + - db + - database + related_resources: + integrations: + list: [] + info_provided_to_referring_integrations: + description: "" + most_popular: false + overview: + data_collection: + metrics_description: | + This collector gathers metrics about client requests, cache hits, and many more, while also providing metrics per each thread pool. + method_description: | + The [JMX Exporter](https://github.com/prometheus/jmx_exporter) is used to fetch metrics from a Cassandra instance and make them available at an endpoint like `http://127.0.0.1:7072/metrics`. + supported_platforms: + include: [] + exclude: [] + multi_instance: true + additional_permissions: + description: "" + default_behavior: + auto_detection: + description: | + This collector discovers instances running on the local host that provide metrics on port 7072. + + On startup, it tries to collect metrics from: + + - http://127.0.0.1:7072/metrics + limits: + description: "" + performance_impact: + description: "" + setup: + prerequisites: + list: + - title: Configure Cassandra with Prometheus JMX Exporter + description: | + To configure Cassandra with the [JMX Exporter](https://github.com/prometheus/jmx_exporter): + + > **Note**: paths can differ depends on your setup. + + - Download latest [jmx_exporter](https://repo1.maven.org/maven2/io/prometheus/jmx/jmx_prometheus_javaagent/) jar file + and install it in a directory where Cassandra can access it. + - Add + the [jmx_exporter.yaml](https://raw.githubusercontent.com/netdata/go.d.plugin/master/modules/cassandra/jmx_exporter.yaml) + file to `/etc/cassandra`. + - Add the following line to `/etc/cassandra/cassandra-env.sh` + ``` + JVM_OPTS="$JVM_OPTS $JVM_EXTRA_OPTS -javaagent:/opt/jmx_exporter/jmx_exporter.jar=7072:/etc/cassandra/jmx_exporter.yaml + ``` + - Restart cassandra service. + configuration: + file: + name: go.d/cassandra.conf + options: + description: | + The following options can be defined globally: update_every, autodetection_retry. + folding: + title: Config options + enabled: true + list: + - name: update_every + description: Data collection frequency. + default_value: 5 + 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:7072/metrics + 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: 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 + folding: + enabled: false + description: A basic example configuration. + config: | + jobs: + - name: local + url: http://127.0.0.1:7072/metrics + - name: HTTP authentication + description: Local server with basic HTTP authentication. + config: | + jobs: + - name: local + url: http://127.0.0.1:7072/metrics + username: foo + password: bar + - name: HTTPS with self-signed certificate + description: Local server with enabled HTTPS and self-signed certificate. + config: | + jobs: + - name: local + url: https://127.0.0.1:7072/metrics + tls_skip_verify: yes + - 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:7072/metrics + + - name: remote + url: http://192.0.2.1:7072/metrics + 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: cassandra.client_requests_rate + availability: [] + description: Client requests rate + unit: requests/s + chart_type: line + dimensions: + - name: read + - name: write + - name: cassandra.client_request_read_latency_histogram + availability: [] + description: Client request read latency histogram + unit: seconds + chart_type: line + dimensions: + - name: p50 + - name: p75 + - name: p95 + - name: p98 + - name: p99 + - name: p999 + - name: cassandra.client_request_write_latency_histogram + availability: [] + description: Client request write latency histogram + unit: seconds + chart_type: line + dimensions: + - name: p50 + - name: p75 + - name: p95 + - name: p98 + - name: p99 + - name: p999 + - name: cassandra.client_requests_latency + availability: [] + description: Client requests total latency + unit: seconds + chart_type: line + dimensions: + - name: read + - name: write + - name: cassandra.row_cache_hit_ratio + availability: [] + description: Key cache hit ratio + unit: percentage + chart_type: line + dimensions: + - name: hit_ratio + - name: cassandra.row_cache_hit_rate + availability: [] + description: Key cache hit rate + unit: events/s + chart_type: stacked + dimensions: + - name: hits + - name: misses + - name: cassandra.row_cache_utilization + availability: [] + description: Key cache utilization + unit: percentage + chart_type: line + dimensions: + - name: used + - name: cassandra.row_cache_size + availability: [] + description: Key cache size + unit: bytes + chart_type: line + dimensions: + - name: size + - name: cassandra.key_cache_hit_ratio + availability: [] + description: Row cache hit ratio + unit: percentage + chart_type: line + dimensions: + - name: hit_ratio + - name: cassandra.key_cache_hit_rate + availability: [] + description: Row cache hit rate + unit: events/s + chart_type: stacked + dimensions: + - name: hits + - name: misses + - name: cassandra.key_cache_utilization + availability: [] + description: Row cache utilization + unit: percentage + chart_type: line + dimensions: + - name: used + - name: cassandra.key_cache_size + availability: [] + description: Row cache size + unit: bytes + chart_type: line + dimensions: + - name: size + - name: cassandra.storage_live_disk_space_used + availability: [] + description: Disk space used by live data + unit: bytes + chart_type: line + dimensions: + - name: used + - name: cassandra.compaction_completed_tasks_rate + availability: [] + description: Completed compactions rate + unit: tasks/s + chart_type: line + dimensions: + - name: completed + - name: cassandra.compaction_pending_tasks_count + availability: [] + description: Pending compactions + unit: tasks + chart_type: line + dimensions: + - name: pending + - name: cassandra.compaction_compacted_rate + availability: [] + description: Compaction data rate + unit: bytes/s + chart_type: line + dimensions: + - name: compacted + - name: cassandra.jvm_memory_used + availability: [] + description: Memory used + unit: bytes + chart_type: stacked + dimensions: + - name: heap + - name: nonheap + - name: cassandra.jvm_gc_rate + availability: [] + description: Garbage collections rate + unit: gc/s + chart_type: line + dimensions: + - name: parnew + - name: cms + - name: cassandra.jvm_gc_time + availability: [] + description: Garbage collection time + unit: seconds + chart_type: line + dimensions: + - name: parnew + - name: cms + - name: cassandra.dropped_messages_rate + availability: [] + description: Dropped messages rate + unit: messages/s + chart_type: line + dimensions: + - name: dropped + - name: cassandra.client_requests_timeouts_rate + availability: [] + description: Client requests timeouts rate + unit: timeout/s + chart_type: line + dimensions: + - name: read + - name: write + - name: cassandra.client_requests_unavailables_rate + availability: [] + description: Client requests unavailable exceptions rate + unit: exceptions/s + chart_type: line + dimensions: + - name: read + - name: write + - name: cassandra.client_requests_failures_rate + availability: [] + description: Client requests failures rate + unit: failures/s + chart_type: line + dimensions: + - name: read + - name: write + - name: cassandra.storage_exceptions_rate + availability: [] + description: Storage exceptions rate + unit: exceptions/s + chart_type: line + dimensions: + - name: storage + - name: thread pool + description: Metrics related to Cassandra's thread pools. Each thread pool provides its own set of the following metrics. + labels: + - name: thread_pool + description: thread pool name + metrics: + - name: cassandra.thread_pool_active_tasks_count + availability: [] + description: Active tasks + unit: tasks + chart_type: line + dimensions: + - name: active + - name: cassandra.thread_pool_pending_tasks_count + availability: [] + description: Pending tasks + unit: tasks + chart_type: line + dimensions: + - name: pending + - name: cassandra.thread_pool_blocked_tasks_count + availability: [] + description: Blocked tasks + unit: tasks + chart_type: line + dimensions: + - name: blocked + - name: cassandra.thread_pool_blocked_tasks_rate + availability: [] + description: Blocked tasks rate + unit: tasks/s + chart_type: line + dimensions: + - name: blocked diff --git a/src/go/plugin/go.d/modules/cassandra/metrics.go b/src/go/plugin/go.d/modules/cassandra/metrics.go new file mode 100644 index 000000000..6533c694c --- /dev/null +++ b/src/go/plugin/go.d/modules/cassandra/metrics.go @@ -0,0 +1,103 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +package cassandra + +// https://cassandra.apache.org/doc/latest/cassandra/operating/metrics.html#table-metrics +// https://www.datadoghq.com/blog/how-to-collect-cassandra-metrics/ +// https://docs.opennms.com/horizon/29/deployment/time-series-storage/newts/cassandra-jmx.html + +func newCassandraMetrics() *cassandraMetrics { + return &cassandraMetrics{ + threadPools: make(map[string]*threadPoolMetrics), + } +} + +type cassandraMetrics struct { + clientReqTotalLatencyReads metricValue + clientReqTotalLatencyWrites metricValue + clientReqLatencyReads metricValue + clientReqLatencyWrites metricValue + clientReqTimeoutsReads metricValue + clientReqTimeoutsWrites metricValue + clientReqUnavailablesReads metricValue + clientReqUnavailablesWrites metricValue + clientReqFailuresReads metricValue + clientReqFailuresWrites metricValue + + clientReqReadLatencyP50 metricValue + clientReqReadLatencyP75 metricValue + clientReqReadLatencyP95 metricValue + clientReqReadLatencyP98 metricValue + clientReqReadLatencyP99 metricValue + clientReqReadLatencyP999 metricValue + clientReqWriteLatencyP50 metricValue + clientReqWriteLatencyP75 metricValue + clientReqWriteLatencyP95 metricValue + clientReqWriteLatencyP98 metricValue + clientReqWriteLatencyP99 metricValue + clientReqWriteLatencyP999 metricValue + + rowCacheHits metricValue + rowCacheMisses metricValue + rowCacheCapacity metricValue + rowCacheSize metricValue + keyCacheHits metricValue + keyCacheMisses metricValue + keyCacheCapacity metricValue + keyCacheSize metricValue + + // https://cassandra.apache.org/doc/latest/cassandra/operating/metrics.html#dropped-metrics + droppedMessages metricValue + + // https://cassandra.apache.org/doc/latest/cassandra/operating/metrics.html#storage-metrics + storageLoad metricValue + storageExceptions metricValue + + // https://cassandra.apache.org/doc/latest/cassandra/operating/metrics.html#compaction-metrics + compactionBytesCompacted metricValue + compactionPendingTasks metricValue + compactionCompletedTasks metricValue + + // https://cassandra.apache.org/doc/latest/cassandra/operating/metrics.html#memory + jvmMemoryHeapUsed metricValue + jvmMemoryNonHeapUsed metricValue + // https://cassandra.apache.org/doc/latest/cassandra/operating/metrics.html#garbagecollector + jvmGCParNewCount metricValue + jvmGCParNewTime metricValue + jvmGCCMSCount metricValue + jvmGCCMSTime metricValue + + threadPools map[string]*threadPoolMetrics +} + +type threadPoolMetrics struct { + name string + hasCharts bool + + activeTasks metricValue + pendingTasks metricValue + blockedTasks metricValue + totalBlockedTasks metricValue +} + +type metricValue struct { + isSet bool + value float64 +} + +func (mv *metricValue) add(v float64) { + mv.isSet = true + mv.value += v +} + +func (mv *metricValue) write(mx map[string]int64, key string) { + if mv.isSet { + mx[key] = int64(mv.value) + } +} + +func (mv *metricValue) write1k(mx map[string]int64, key string) { + if mv.isSet { + mx[key] = int64(mv.value * 1000) + } +} diff --git a/src/go/plugin/go.d/modules/cassandra/testdata/config.json b/src/go/plugin/go.d/modules/cassandra/testdata/config.json new file mode 100644 index 000000000..984c3ed6e --- /dev/null +++ b/src/go/plugin/go.d/modules/cassandra/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/cassandra/testdata/config.yaml b/src/go/plugin/go.d/modules/cassandra/testdata/config.yaml new file mode 100644 index 000000000..8558b61cc --- /dev/null +++ b/src/go/plugin/go.d/modules/cassandra/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 diff --git a/src/go/plugin/go.d/modules/cassandra/testdata/metrics.txt b/src/go/plugin/go.d/modules/cassandra/testdata/metrics.txt new file mode 100644 index 000000000..663a68080 --- /dev/null +++ b/src/go/plugin/go.d/modules/cassandra/testdata/metrics.txt @@ -0,0 +1,402 @@ +# HELP jvm_threads_current Current thread count of a JVM +# TYPE jvm_threads_current gauge +jvm_threads_current 93.0 +# HELP jvm_threads_daemon Daemon thread count of a JVM +# TYPE jvm_threads_daemon gauge +jvm_threads_daemon 82.0 +# HELP jvm_threads_peak Peak thread count of a JVM +# TYPE jvm_threads_peak gauge +jvm_threads_peak 94.0 +# HELP jvm_threads_started_total Started thread count of a JVM +# TYPE jvm_threads_started_total counter +jvm_threads_started_total 1860.0 +# HELP jvm_threads_deadlocked Cycles of JVM-threads that are in deadlock waiting to acquire object monitors or ownable synchronizers +# TYPE jvm_threads_deadlocked gauge +jvm_threads_deadlocked 0.0 +# HELP jvm_threads_deadlocked_monitor Cycles of JVM-threads that are in deadlock waiting to acquire object monitors +# TYPE jvm_threads_deadlocked_monitor gauge +jvm_threads_deadlocked_monitor 0.0 +# HELP jvm_threads_state Current count of threads by state +# TYPE jvm_threads_state gauge +jvm_threads_state{state="NEW",} 0.0 +jvm_threads_state{state="TERMINATED",} 0.0 +jvm_threads_state{state="RUNNABLE",} 16.0 +jvm_threads_state{state="BLOCKED",} 0.0 +jvm_threads_state{state="WAITING",} 46.0 +jvm_threads_state{state="TIMED_WAITING",} 31.0 +jvm_threads_state{state="UNKNOWN",} 0.0 +# HELP jvm_memory_pool_allocated_bytes_total Total bytes allocated in a given JVM memory pool. Only updated after GC, not continuously. +# TYPE jvm_memory_pool_allocated_bytes_total counter +jvm_memory_pool_allocated_bytes_total{pool="Par Survivor Space",} 1.52801872E8 +jvm_memory_pool_allocated_bytes_total{pool="CMS Old Gen",} 8.55035344E8 +jvm_memory_pool_allocated_bytes_total{pool="CodeHeap 'profiled nmethods'",} 2.4841216E7 +jvm_memory_pool_allocated_bytes_total{pool="CodeHeap 'non-profiled nmethods'",} 1.3023104E7 +jvm_memory_pool_allocated_bytes_total{pool="Compressed Class Space",} 6640584.0 +jvm_memory_pool_allocated_bytes_total{pool="Metaspace",} 5.3862968E7 +jvm_memory_pool_allocated_bytes_total{pool="Par Eden Space",} 7.3147804328E10 +jvm_memory_pool_allocated_bytes_total{pool="CodeHeap 'non-nmethods'",} 1530112.0 +# HELP jvm_gc_collection_seconds Time spent in a given JVM garbage collector in seconds. +# TYPE jvm_gc_collection_seconds summary +jvm_gc_collection_seconds_count{gc="ParNew",} 218.0 +jvm_gc_collection_seconds_sum{gc="ParNew",} 1.617 +jvm_gc_collection_seconds_count{gc="ConcurrentMarkSweep",} 1.0 +jvm_gc_collection_seconds_sum{gc="ConcurrentMarkSweep",} 0.059 +# HELP jvm_classes_currently_loaded The number of classes that are currently loaded in the JVM +# TYPE jvm_classes_currently_loaded gauge +jvm_classes_currently_loaded 9663.0 +# HELP jvm_classes_loaded_total The total number of classes that have been loaded since the JVM has started execution +# TYPE jvm_classes_loaded_total counter +jvm_classes_loaded_total 9663.0 +# HELP jvm_classes_unloaded_total The total number of classes that have been unloaded since the JVM has started execution +# TYPE jvm_classes_unloaded_total counter +jvm_classes_unloaded_total 0.0 +# HELP jmx_config_reload_success_total Number of times configuration have successfully been reloaded. +# TYPE jmx_config_reload_success_total counter +jmx_config_reload_success_total 0.0 +# HELP jmx_config_reload_failure_total Number of times configuration have failed to be reloaded. +# TYPE jmx_config_reload_failure_total counter +jmx_config_reload_failure_total 0.0 +# HELP org_apache_cassandra_metrics_clientrequest_50thpercentile Attribute exposed for management org.apache.cassandra.metrics:name=Latency,type=ClientRequest,attribute=50thPercentile +# TYPE org_apache_cassandra_metrics_clientrequest_50thpercentile untyped +org_apache_cassandra_metrics_clientrequest_50thpercentile{scope="Read",name="Latency",} 61.214 +org_apache_cassandra_metrics_clientrequest_50thpercentile{scope="Write",name="Latency",} 35.425000000000004 +# HELP org_apache_cassandra_metrics_clientrequest_95thpercentile Attribute exposed for management org.apache.cassandra.metrics:name=Latency,type=ClientRequest,attribute=95thPercentile +# TYPE org_apache_cassandra_metrics_clientrequest_95thpercentile untyped +org_apache_cassandra_metrics_clientrequest_95thpercentile{scope="Read",name="Latency",} 126.934 +org_apache_cassandra_metrics_clientrequest_95thpercentile{scope="Write",name="Latency",} 105.778 +# HELP org_apache_cassandra_metrics_cache_count Attribute exposed for management org.apache.cassandra.metrics:name=Misses,type=Cache,attribute=Count +# TYPE org_apache_cassandra_metrics_cache_count untyped +org_apache_cassandra_metrics_cache_count{scope="KeyCache",name="Misses",} 194890.0 +org_apache_cassandra_metrics_cache_count{scope="KeyCache",name="Hits",} 1336427.0 +org_apache_cassandra_metrics_cache_count{scope="RowCache",name="Hits",} 0.0 +org_apache_cassandra_metrics_cache_count{scope="RowCache",name="Misses",} 0.0 +# HELP org_apache_cassandra_metrics_storage_count Attribute exposed for management org.apache.cassandra.metrics:name=Exceptions,type=Storage,attribute=Count +# TYPE org_apache_cassandra_metrics_storage_count untyped +org_apache_cassandra_metrics_storage_count{name="Exceptions",} 0.0 +org_apache_cassandra_metrics_storage_count{name="Load",} 8.58272986E8 +# HELP org_apache_cassandra_metrics_compaction_count Attribute exposed for management org.apache.cassandra.metrics:name=BytesCompacted,type=Compaction,attribute=Count +# TYPE org_apache_cassandra_metrics_compaction_count untyped +org_apache_cassandra_metrics_compaction_count{name="BytesCompacted",} 2532.0 +# HELP org_apache_cassandra_metrics_clientrequest_count Attribute exposed for management org.apache.cassandra.metrics:name=Timeouts,type=ClientRequest,attribute=Count +# TYPE org_apache_cassandra_metrics_clientrequest_count untyped +org_apache_cassandra_metrics_clientrequest_count{scope="Write",name="Timeouts",} 0.0 +org_apache_cassandra_metrics_clientrequest_count{scope="Read",name="Latency",} 333316.0 +org_apache_cassandra_metrics_clientrequest_count{scope="Read",name="Unavailables",} 0.0 +org_apache_cassandra_metrics_clientrequest_count{scope="Write",name="TotalLatency",} 1.4253267E7 +org_apache_cassandra_metrics_clientrequest_count{scope="Read",name="Timeouts",} 0.0 +org_apache_cassandra_metrics_clientrequest_count{scope="Write",name="Failures",} 0.0 +org_apache_cassandra_metrics_clientrequest_count{scope="Write",name="Latency",} 331841.0 +org_apache_cassandra_metrics_clientrequest_count{scope="Read",name="Failures",} 0.0 +org_apache_cassandra_metrics_clientrequest_count{scope="Read",name="TotalLatency",} 2.3688998E7 +org_apache_cassandra_metrics_clientrequest_count{scope="Write",name="Unavailables",} 0.0 +# HELP org_apache_cassandra_metrics_cache_value Attribute exposed for management org.apache.cassandra.metrics:name=Size,type=Cache,attribute=Value +# TYPE org_apache_cassandra_metrics_cache_value untyped +org_apache_cassandra_metrics_cache_value{scope="RowCache",name="Size",} 0.0 +org_apache_cassandra_metrics_cache_value{scope="KeyCache",name="Size",} 1.96559936E8 +org_apache_cassandra_metrics_cache_value{scope="RowCache",name="Capacity",} 0.0 +org_apache_cassandra_metrics_cache_value{scope="KeyCache",name="Capacity",} 9.437184E8 +# HELP org_apache_cassandra_metrics_clientrequest_75thpercentile Attribute exposed for management org.apache.cassandra.metrics:name=Latency,type=ClientRequest,attribute=75thPercentile +# TYPE org_apache_cassandra_metrics_clientrequest_75thpercentile untyped +org_apache_cassandra_metrics_clientrequest_75thpercentile{scope="Read",name="Latency",} 88.148 +org_apache_cassandra_metrics_clientrequest_75thpercentile{scope="Write",name="Latency",} 61.214 +# HELP org_apache_cassandra_metrics_clientrequest_999thpercentile Attribute exposed for management org.apache.cassandra.metrics:name=Latency,type=ClientRequest,attribute=999thPercentile +# TYPE org_apache_cassandra_metrics_clientrequest_999thpercentile untyped +org_apache_cassandra_metrics_clientrequest_999thpercentile{scope="Read",name="Latency",} 454.826 +org_apache_cassandra_metrics_clientrequest_999thpercentile{scope="Write",name="Latency",} 315.85200000000003 +# HELP org_apache_cassandra_metrics_clientrequest_99thpercentile Attribute exposed for management org.apache.cassandra.metrics:name=Latency,type=ClientRequest,attribute=99thPercentile +# TYPE org_apache_cassandra_metrics_clientrequest_99thpercentile untyped +org_apache_cassandra_metrics_clientrequest_99thpercentile{scope="Read",name="Latency",} 219.342 +org_apache_cassandra_metrics_clientrequest_99thpercentile{scope="Write",name="Latency",} 152.321 +# HELP org_apache_cassandra_metrics_threadpools_value Attribute exposed for management org.apache.cassandra.metrics:name=ActiveTasks,type=ThreadPools,attribute=Value +# TYPE org_apache_cassandra_metrics_threadpools_value untyped +org_apache_cassandra_metrics_threadpools_value{path="transport",scope="Native-Transport-Requests",name="ActiveTasks",} 0.0 +org_apache_cassandra_metrics_threadpools_value{path="internal",scope="HintsDispatcher",name="ActiveTasks",} 0.0 +org_apache_cassandra_metrics_threadpools_value{path="transport",scope="Native-Transport-Requests",name="PendingTasks",} 0.0 +org_apache_cassandra_metrics_threadpools_value{path="internal",scope="MemtableFlushWriter",name="PendingTasks",} 0.0 +org_apache_cassandra_metrics_threadpools_value{path="internal",scope="CompactionExecutor",name="ActiveTasks",} 0.0 +org_apache_cassandra_metrics_threadpools_value{path="internal",scope="Sampler",name="PendingTasks",} 0.0 +org_apache_cassandra_metrics_threadpools_value{path="internal",scope="MemtableReclaimMemory",name="ActiveTasks",} 0.0 +org_apache_cassandra_metrics_threadpools_value{path="internal",scope="ViewBuildExecutor",name="ActiveTasks",} 0.0 +org_apache_cassandra_metrics_threadpools_value{path="internal",scope="MemtableReclaimMemory",name="PendingTasks",} 0.0 +org_apache_cassandra_metrics_threadpools_value{path="internal",scope="PerDiskMemtableFlushWriter_0",name="ActiveTasks",} 0.0 +org_apache_cassandra_metrics_threadpools_value{path="internal",scope="MemtablePostFlush",name="ActiveTasks",} 0.0 +org_apache_cassandra_metrics_threadpools_value{path="internal",scope="SecondaryIndexManagement",name="ActiveTasks",} 0.0 +org_apache_cassandra_metrics_threadpools_value{path="internal",scope="ValidationExecutor",name="PendingTasks",} 0.0 +org_apache_cassandra_metrics_threadpools_value{path="internal",scope="Sampler",name="ActiveTasks",} 0.0 +org_apache_cassandra_metrics_threadpools_value{path="internal",scope="MemtableFlushWriter",name="ActiveTasks",} 0.0 +org_apache_cassandra_metrics_threadpools_value{path="internal",scope="ValidationExecutor",name="ActiveTasks",} 0.0 +org_apache_cassandra_metrics_threadpools_value{path="internal",scope="HintsDispatcher",name="PendingTasks",} 0.0 +org_apache_cassandra_metrics_threadpools_value{path="internal",scope="SecondaryIndexManagement",name="PendingTasks",} 0.0 +org_apache_cassandra_metrics_threadpools_value{path="request",scope="MutationStage",name="ActiveTasks",} 0.0 +org_apache_cassandra_metrics_threadpools_value{path="request",scope="ReadStage",name="PendingTasks",} 0.0 +org_apache_cassandra_metrics_threadpools_value{path="internal",scope="GossipStage",name="PendingTasks",} 0.0 +org_apache_cassandra_metrics_threadpools_value{path="internal",scope="CacheCleanupExecutor",name="ActiveTasks",} 0.0 +org_apache_cassandra_metrics_threadpools_value{path="internal",scope="CompactionExecutor",name="PendingTasks",} 0.0 +org_apache_cassandra_metrics_threadpools_value{path="request",scope="MutationStage",name="PendingTasks",} 0.0 +org_apache_cassandra_metrics_threadpools_value{path="internal",scope="PendingRangeCalculator",name="PendingTasks",} 0.0 +org_apache_cassandra_metrics_threadpools_value{path="internal",scope="CacheCleanupExecutor",name="PendingTasks",} 0.0 +org_apache_cassandra_metrics_threadpools_value{path="internal",scope="MemtablePostFlush",name="PendingTasks",} 0.0 +org_apache_cassandra_metrics_threadpools_value{path="internal",scope="ViewBuildExecutor",name="PendingTasks",} 0.0 +org_apache_cassandra_metrics_threadpools_value{path="request",scope="ReadStage",name="ActiveTasks",} 0.0 +org_apache_cassandra_metrics_threadpools_value{path="internal",scope="PerDiskMemtableFlushWriter_0",name="PendingTasks",} 0.0 +org_apache_cassandra_metrics_threadpools_value{path="internal",scope="PendingRangeCalculator",name="ActiveTasks",} 0.0 +org_apache_cassandra_metrics_threadpools_value{path="internal",scope="GossipStage",name="ActiveTasks",} 0.0 +# HELP org_apache_cassandra_metrics_droppedmessage_count Attribute exposed for management org.apache.cassandra.metrics:name=Dropped,type=DroppedMessage,attribute=Count +# TYPE org_apache_cassandra_metrics_droppedmessage_count untyped +org_apache_cassandra_metrics_droppedmessage_count{scope="FINALIZE_PROPOSE_MSG",name="Dropped",} 0.0 +org_apache_cassandra_metrics_droppedmessage_count{scope="COUNTER_MUTATION_RSP",name="Dropped",} 0.0 +org_apache_cassandra_metrics_droppedmessage_count{scope="BATCH_REMOVE",name="Dropped",} 0.0 +org_apache_cassandra_metrics_droppedmessage_count{scope="MUTATION_RSP",name="Dropped",} 0.0 +org_apache_cassandra_metrics_droppedmessage_count{scope="SCHEMA_PULL_REQ",name="Dropped",} 0.0 +org_apache_cassandra_metrics_droppedmessage_count{scope="READ_REPAIR",name="Dropped",} 0.0 +org_apache_cassandra_metrics_droppedmessage_count{scope="_TEST_2",name="Dropped",} 0.0 +org_apache_cassandra_metrics_droppedmessage_count{scope="BATCH_STORE_REQ",name="Dropped",} 0.0 +org_apache_cassandra_metrics_droppedmessage_count{scope="PAXOS_COMMIT_RSP",name="Dropped",} 0.0 +org_apache_cassandra_metrics_droppedmessage_count{scope="PAXOS_PROPOSE_RSP",name="Dropped",} 0.0 +org_apache_cassandra_metrics_droppedmessage_count{scope="RANGE_RSP",name="Dropped",} 0.0 +org_apache_cassandra_metrics_droppedmessage_count{scope="SNAPSHOT_RSP",name="Dropped",} 0.0 +org_apache_cassandra_metrics_droppedmessage_count{scope="SCHEMA_VERSION_RSP",name="Dropped",} 0.0 +org_apache_cassandra_metrics_droppedmessage_count{scope="PING_RSP",name="Dropped",} 0.0 +org_apache_cassandra_metrics_droppedmessage_count{scope="SNAPSHOT_MSG",name="Dropped",} 0.0 +org_apache_cassandra_metrics_droppedmessage_count{scope="VALIDATION_REQ",name="Dropped",} 0.0 +org_apache_cassandra_metrics_droppedmessage_count{scope="GOSSIP_DIGEST_SYN",name="Dropped",} 0.0 +org_apache_cassandra_metrics_droppedmessage_count{scope="HINT_RSP",name="Dropped",} 0.0 +org_apache_cassandra_metrics_droppedmessage_count{scope="FINALIZE_PROMISE_MSG",name="Dropped",} 0.0 +org_apache_cassandra_metrics_droppedmessage_count{scope="GOSSIP_SHUTDOWN",name="Dropped",} 0.0 +org_apache_cassandra_metrics_droppedmessage_count{scope="PAXOS_PROPOSE_REQ",name="Dropped",} 0.0 +org_apache_cassandra_metrics_droppedmessage_count{scope="RANGE_SLICE",name="Dropped",} 0.0 +org_apache_cassandra_metrics_droppedmessage_count{scope="REPAIR_RSP",name="Dropped",} 0.0 +org_apache_cassandra_metrics_droppedmessage_count{scope="COUNTER_MUTATION_REQ",name="Dropped",} 0.0 +org_apache_cassandra_metrics_droppedmessage_count{scope="MUTATION",name="Dropped",} 0.0 +org_apache_cassandra_metrics_droppedmessage_count{scope="_TRACE",name="Dropped",} 0.0 +org_apache_cassandra_metrics_droppedmessage_count{scope="PING_REQ",name="Dropped",} 0.0 +org_apache_cassandra_metrics_droppedmessage_count{scope="CLEANUP_MSG",name="Dropped",} 0.0 +org_apache_cassandra_metrics_droppedmessage_count{scope="BATCH_STORE",name="Dropped",} 0.0 +org_apache_cassandra_metrics_droppedmessage_count{scope="REQUEST_RSP",name="Dropped",} 0.0 +org_apache_cassandra_metrics_droppedmessage_count{scope="BATCH_STORE_RSP",name="Dropped",} 0.0 +org_apache_cassandra_metrics_droppedmessage_count{scope="ECHO_RSP",name="Dropped",} 0.0 +org_apache_cassandra_metrics_droppedmessage_count{scope="READ_REPAIR_REQ",name="Dropped",} 0.0 +org_apache_cassandra_metrics_droppedmessage_count{scope="READ_REPAIR_RSP",name="Dropped",} 0.0 +org_apache_cassandra_metrics_droppedmessage_count{scope="STATUS_RSP",name="Dropped",} 0.0 +org_apache_cassandra_metrics_droppedmessage_count{scope="REPLICATION_DONE_REQ",name="Dropped",} 0.0 +org_apache_cassandra_metrics_droppedmessage_count{scope="REQUEST_RESPONSE",name="Dropped",} 0.0 +org_apache_cassandra_metrics_droppedmessage_count{scope="PREPARE_CONSISTENT_REQ",name="Dropped",} 0.0 +org_apache_cassandra_metrics_droppedmessage_count{scope="_SAMPLE",name="Dropped",} 0.0 +org_apache_cassandra_metrics_droppedmessage_count{scope="SCHEMA_VERSION_REQ",name="Dropped",} 0.0 +org_apache_cassandra_metrics_droppedmessage_count{scope="FAILURE_RSP",name="Dropped",} 0.0 +org_apache_cassandra_metrics_droppedmessage_count{scope="GOSSIP_DIGEST_ACK2",name="Dropped",} 0.0 +org_apache_cassandra_metrics_droppedmessage_count{scope="SYNC_REQ",name="Dropped",} 0.0 +org_apache_cassandra_metrics_droppedmessage_count{scope="TRUNCATE_RSP",name="Dropped",} 0.0 +org_apache_cassandra_metrics_droppedmessage_count{scope="COUNTER_MUTATION",name="Dropped",} 0.0 +org_apache_cassandra_metrics_droppedmessage_count{scope="UNUSED_CUSTOM_VERB",name="Dropped",} 0.0 +org_apache_cassandra_metrics_droppedmessage_count{scope="READ_REQ",name="Dropped",} 0.0 +org_apache_cassandra_metrics_droppedmessage_count{scope="PREPARE_MSG",name="Dropped",} 0.0 +org_apache_cassandra_metrics_droppedmessage_count{scope="BATCH_REMOVE_REQ",name="Dropped",} 0.0 +org_apache_cassandra_metrics_droppedmessage_count{scope="ECHO_REQ",name="Dropped",} 0.0 +org_apache_cassandra_metrics_droppedmessage_count{scope="FAILED_SESSION_MSG",name="Dropped",} 0.0 +org_apache_cassandra_metrics_droppedmessage_count{scope="PAXOS_PREPARE_RSP",name="Dropped",} 0.0 +org_apache_cassandra_metrics_droppedmessage_count{scope="STATUS_REQ",name="Dropped",} 0.0 +org_apache_cassandra_metrics_droppedmessage_count{scope="_TEST_1",name="Dropped",} 0.0 +org_apache_cassandra_metrics_droppedmessage_count{scope="HINT",name="Dropped",} 0.0 +org_apache_cassandra_metrics_droppedmessage_count{scope="SCHEMA_PUSH_REQ",name="Dropped",} 0.0 +org_apache_cassandra_metrics_droppedmessage_count{scope="PREPARE_CONSISTENT_RSP",name="Dropped",} 0.0 +org_apache_cassandra_metrics_droppedmessage_count{scope="REPLICATION_DONE_RSP",name="Dropped",} 0.0 +org_apache_cassandra_metrics_droppedmessage_count{scope="MUTATION_REQ",name="Dropped",} 0.0 +org_apache_cassandra_metrics_droppedmessage_count{scope="SCHEMA_PULL_RSP",name="Dropped",} 0.0 +org_apache_cassandra_metrics_droppedmessage_count{scope="READ_RSP",name="Dropped",} 0.0 +org_apache_cassandra_metrics_droppedmessage_count{scope="GOSSIP_DIGEST_ACK",name="Dropped",} 0.0 +org_apache_cassandra_metrics_droppedmessage_count{scope="FINALIZE_COMMIT_MSG",name="Dropped",} 0.0 +org_apache_cassandra_metrics_droppedmessage_count{scope="RANGE_REQ",name="Dropped",} 0.0 +org_apache_cassandra_metrics_droppedmessage_count{scope="SYNC_RSP",name="Dropped",} 0.0 +org_apache_cassandra_metrics_droppedmessage_count{scope="INTERNAL_RSP",name="Dropped",} 0.0 +org_apache_cassandra_metrics_droppedmessage_count{scope="TRUNCATE_REQ",name="Dropped",} 0.0 +org_apache_cassandra_metrics_droppedmessage_count{scope="PAXOS_COMMIT_REQ",name="Dropped",} 0.0 +org_apache_cassandra_metrics_droppedmessage_count{scope="READ",name="Dropped",} 0.0 +org_apache_cassandra_metrics_droppedmessage_count{scope="BATCH_REMOVE_RSP",name="Dropped",} 0.0 +org_apache_cassandra_metrics_droppedmessage_count{scope="HINT_REQ",name="Dropped",} 0.0 +org_apache_cassandra_metrics_droppedmessage_count{scope="SNAPSHOT_REQ",name="Dropped",} 0.0 +org_apache_cassandra_metrics_droppedmessage_count{scope="PAXOS_PREPARE_REQ",name="Dropped",} 0.0 +org_apache_cassandra_metrics_droppedmessage_count{scope="VALIDATION_RSP",name="Dropped",} 0.0 +org_apache_cassandra_metrics_droppedmessage_count{scope="SCHEMA_PUSH_RSP",name="Dropped",} 0.0 +# HELP org_apache_cassandra_metrics_clientrequest_98thpercentile Attribute exposed for management org.apache.cassandra.metrics:name=Latency,type=ClientRequest,attribute=98thPercentile +# TYPE org_apache_cassandra_metrics_clientrequest_98thpercentile untyped +org_apache_cassandra_metrics_clientrequest_98thpercentile{scope="Read",name="Latency",} 182.785 +org_apache_cassandra_metrics_clientrequest_98thpercentile{scope="Write",name="Latency",} 126.934 +# HELP org_apache_cassandra_metrics_threadpools_count Attribute exposed for management org.apache.cassandra.metrics:name=TotalBlockedTasks,type=ThreadPools,attribute=Count +# TYPE org_apache_cassandra_metrics_threadpools_count untyped +org_apache_cassandra_metrics_threadpools_count{path="internal",scope="HintsDispatcher",name="TotalBlockedTasks",} 0.0 +org_apache_cassandra_metrics_threadpools_count{path="request",scope="MutationStage",name="CurrentlyBlockedTasks",} 0.0 +org_apache_cassandra_metrics_threadpools_count{path="internal",scope="Sampler",name="CurrentlyBlockedTasks",} 0.0 +org_apache_cassandra_metrics_threadpools_count{path="internal",scope="GossipStage",name="CurrentlyBlockedTasks",} 0.0 +org_apache_cassandra_metrics_threadpools_count{path="internal",scope="MemtableFlushWriter",name="TotalBlockedTasks",} 0.0 +org_apache_cassandra_metrics_threadpools_count{path="internal",scope="Sampler",name="TotalBlockedTasks",} 0.0 +org_apache_cassandra_metrics_threadpools_count{path="internal",scope="PerDiskMemtableFlushWriter_0",name="CurrentlyBlockedTasks",} 0.0 +org_apache_cassandra_metrics_threadpools_count{path="internal",scope="MemtableFlushWriter",name="CurrentlyBlockedTasks",} 0.0 +org_apache_cassandra_metrics_threadpools_count{path="internal",scope="CacheCleanupExecutor",name="CurrentlyBlockedTasks",} 0.0 +org_apache_cassandra_metrics_threadpools_count{path="internal",scope="ValidationExecutor",name="TotalBlockedTasks",} 0.0 +org_apache_cassandra_metrics_threadpools_count{path="internal",scope="MemtableReclaimMemory",name="TotalBlockedTasks",} 0.0 +org_apache_cassandra_metrics_threadpools_count{path="internal",scope="GossipStage",name="TotalBlockedTasks",} 0.0 +org_apache_cassandra_metrics_threadpools_count{path="internal",scope="MemtablePostFlush",name="CurrentlyBlockedTasks",} 0.0 +org_apache_cassandra_metrics_threadpools_count{path="internal",scope="ViewBuildExecutor",name="CurrentlyBlockedTasks",} 0.0 +org_apache_cassandra_metrics_threadpools_count{path="internal",scope="CacheCleanupExecutor",name="TotalBlockedTasks",} 0.0 +org_apache_cassandra_metrics_threadpools_count{path="internal",scope="PendingRangeCalculator",name="TotalBlockedTasks",} 0.0 +org_apache_cassandra_metrics_threadpools_count{path="internal",scope="MemtableReclaimMemory",name="CurrentlyBlockedTasks",} 0.0 +org_apache_cassandra_metrics_threadpools_count{path="internal",scope="HintsDispatcher",name="CurrentlyBlockedTasks",} 0.0 +org_apache_cassandra_metrics_threadpools_count{path="internal",scope="CompactionExecutor",name="CurrentlyBlockedTasks",} 0.0 +org_apache_cassandra_metrics_threadpools_count{path="transport",scope="Native-Transport-Requests",name="TotalBlockedTasks",} 0.0 +org_apache_cassandra_metrics_threadpools_count{path="transport",scope="Native-Transport-Requests",name="CurrentlyBlockedTasks",} 0.0 +org_apache_cassandra_metrics_threadpools_count{path="internal",scope="SecondaryIndexManagement",name="CurrentlyBlockedTasks",} 0.0 +org_apache_cassandra_metrics_threadpools_count{path="internal",scope="MemtablePostFlush",name="TotalBlockedTasks",} 0.0 +org_apache_cassandra_metrics_threadpools_count{path="request",scope="MutationStage",name="TotalBlockedTasks",} 0.0 +org_apache_cassandra_metrics_threadpools_count{path="internal",scope="ValidationExecutor",name="CurrentlyBlockedTasks",} 0.0 +org_apache_cassandra_metrics_threadpools_count{path="internal",scope="PerDiskMemtableFlushWriter_0",name="TotalBlockedTasks",} 0.0 +org_apache_cassandra_metrics_threadpools_count{path="request",scope="ReadStage",name="CurrentlyBlockedTasks",} 0.0 +org_apache_cassandra_metrics_threadpools_count{path="internal",scope="ViewBuildExecutor",name="TotalBlockedTasks",} 0.0 +org_apache_cassandra_metrics_threadpools_count{path="internal",scope="SecondaryIndexManagement",name="TotalBlockedTasks",} 0.0 +org_apache_cassandra_metrics_threadpools_count{path="internal",scope="PendingRangeCalculator",name="CurrentlyBlockedTasks",} 0.0 +org_apache_cassandra_metrics_threadpools_count{path="internal",scope="CompactionExecutor",name="TotalBlockedTasks",} 0.0 +org_apache_cassandra_metrics_threadpools_count{path="request",scope="ReadStage",name="TotalBlockedTasks",} 0.0 +# HELP org_apache_cassandra_metrics_compaction_value Attribute exposed for management org.apache.cassandra.metrics:name=CompletedTasks,type=Compaction,attribute=Value +# TYPE org_apache_cassandra_metrics_compaction_value untyped +org_apache_cassandra_metrics_compaction_value{name="CompletedTasks",} 1078.0 +org_apache_cassandra_metrics_compaction_value{name="PendingTasks",} 0.0 +# HELP jmx_scrape_duration_seconds Time this JMX scrape took, in seconds. +# TYPE jmx_scrape_duration_seconds gauge +jmx_scrape_duration_seconds 0.102931999 +# HELP jmx_scrape_error Non-zero if this scrape failed. +# TYPE jmx_scrape_error gauge +jmx_scrape_error 0.0 +# HELP jmx_scrape_cached_beans Number of beans with their matching rule cached +# TYPE jmx_scrape_cached_beans gauge +jmx_scrape_cached_beans 0.0 +# HELP process_cpu_seconds_total Total user and system CPU time spent in seconds. +# TYPE process_cpu_seconds_total counter +process_cpu_seconds_total 155.0 +# HELP process_start_time_seconds Start time of the process since unix epoch in seconds. +# TYPE process_start_time_seconds gauge +process_start_time_seconds 1.666810482687E9 +# HELP process_open_fds Number of open file descriptors. +# TYPE process_open_fds gauge +process_open_fds 213.0 +# HELP process_max_fds Maximum number of open file descriptors. +# TYPE process_max_fds gauge +process_max_fds 100000.0 +# HELP process_virtual_memory_bytes Virtual memory size in bytes. +# TYPE process_virtual_memory_bytes gauge +process_virtual_memory_bytes 5.105344512E9 +# HELP process_resident_memory_bytes Resident memory size in bytes. +# TYPE process_resident_memory_bytes gauge +process_resident_memory_bytes 3.464957952E9 +# HELP jvm_memory_objects_pending_finalization The number of objects waiting in the finalizer queue. +# TYPE jvm_memory_objects_pending_finalization gauge +jvm_memory_objects_pending_finalization 0.0 +# HELP jvm_memory_bytes_used Used bytes of a given JVM memory area. +# TYPE jvm_memory_bytes_used gauge +jvm_memory_bytes_used{area="heap",} 1.134866288E9 +jvm_memory_bytes_used{area="nonheap",} 9.6565696E7 +# HELP jvm_memory_bytes_committed Committed (bytes) of a given JVM memory area. +# TYPE jvm_memory_bytes_committed gauge +jvm_memory_bytes_committed{area="heap",} 2.0447232E9 +jvm_memory_bytes_committed{area="nonheap",} 1.01838848E8 +# HELP jvm_memory_bytes_max Max (bytes) of a given JVM memory area. +# TYPE jvm_memory_bytes_max gauge +jvm_memory_bytes_max{area="heap",} 2.0447232E9 +jvm_memory_bytes_max{area="nonheap",} -1.0 +# HELP jvm_memory_bytes_init Initial bytes of a given JVM memory area. +# TYPE jvm_memory_bytes_init gauge +jvm_memory_bytes_init{area="heap",} 2.08666624E9 +jvm_memory_bytes_init{area="nonheap",} 7667712.0 +# HELP jvm_memory_pool_bytes_used Used bytes of a given JVM memory pool. +# TYPE jvm_memory_pool_bytes_used gauge +jvm_memory_pool_bytes_used{pool="CodeHeap 'non-nmethods'",} 1443712.0 +jvm_memory_pool_bytes_used{pool="Metaspace",} 5.386508E7 +jvm_memory_pool_bytes_used{pool="CodeHeap 'profiled nmethods'",} 2.2212992E7 +jvm_memory_pool_bytes_used{pool="Compressed Class Space",} 6640584.0 +jvm_memory_pool_bytes_used{pool="Par Eden Space",} 2.6869912E8 +jvm_memory_pool_bytes_used{pool="Par Survivor Space",} 1.1131824E7 +jvm_memory_pool_bytes_used{pool="CodeHeap 'non-profiled nmethods'",} 1.2403328E7 +jvm_memory_pool_bytes_used{pool="CMS Old Gen",} 8.55035344E8 +# HELP jvm_memory_pool_bytes_committed Committed bytes of a given JVM memory pool. +# TYPE jvm_memory_pool_bytes_committed gauge +jvm_memory_pool_bytes_committed{pool="CodeHeap 'non-nmethods'",} 2555904.0 +jvm_memory_pool_bytes_committed{pool="Metaspace",} 5.574656E7 +jvm_memory_pool_bytes_committed{pool="CodeHeap 'profiled nmethods'",} 2.3724032E7 +jvm_memory_pool_bytes_committed{pool="Compressed Class Space",} 7360512.0 +jvm_memory_pool_bytes_committed{pool="Par Eden Space",} 3.3554432E8 +jvm_memory_pool_bytes_committed{pool="Par Survivor Space",} 4.194304E7 +jvm_memory_pool_bytes_committed{pool="CodeHeap 'non-profiled nmethods'",} 1.245184E7 +jvm_memory_pool_bytes_committed{pool="CMS Old Gen",} 1.66723584E9 +# HELP jvm_memory_pool_bytes_max Max bytes of a given JVM memory pool. +# TYPE jvm_memory_pool_bytes_max gauge +jvm_memory_pool_bytes_max{pool="CodeHeap 'non-nmethods'",} 5832704.0 +jvm_memory_pool_bytes_max{pool="Metaspace",} -1.0 +jvm_memory_pool_bytes_max{pool="CodeHeap 'profiled nmethods'",} 1.22912768E8 +jvm_memory_pool_bytes_max{pool="Compressed Class Space",} 1.073741824E9 +jvm_memory_pool_bytes_max{pool="Par Eden Space",} 3.3554432E8 +jvm_memory_pool_bytes_max{pool="Par Survivor Space",} 4.194304E7 +jvm_memory_pool_bytes_max{pool="CodeHeap 'non-profiled nmethods'",} 1.22912768E8 +jvm_memory_pool_bytes_max{pool="CMS Old Gen",} 1.66723584E9 +# HELP jvm_memory_pool_bytes_init Initial bytes of a given JVM memory pool. +# TYPE jvm_memory_pool_bytes_init gauge +jvm_memory_pool_bytes_init{pool="CodeHeap 'non-nmethods'",} 2555904.0 +jvm_memory_pool_bytes_init{pool="Metaspace",} 0.0 +jvm_memory_pool_bytes_init{pool="CodeHeap 'profiled nmethods'",} 2555904.0 +jvm_memory_pool_bytes_init{pool="Compressed Class Space",} 0.0 +jvm_memory_pool_bytes_init{pool="Par Eden Space",} 3.3554432E8 +jvm_memory_pool_bytes_init{pool="Par Survivor Space",} 4.194304E7 +jvm_memory_pool_bytes_init{pool="CodeHeap 'non-profiled nmethods'",} 2555904.0 +jvm_memory_pool_bytes_init{pool="CMS Old Gen",} 1.66723584E9 +# HELP jvm_memory_pool_collection_used_bytes Used bytes after last collection of a given JVM memory pool. +# TYPE jvm_memory_pool_collection_used_bytes gauge +jvm_memory_pool_collection_used_bytes{pool="Par Eden Space",} 0.0 +jvm_memory_pool_collection_used_bytes{pool="Par Survivor Space",} 1.1131824E7 +jvm_memory_pool_collection_used_bytes{pool="CMS Old Gen",} 0.0 +# HELP jvm_memory_pool_collection_committed_bytes Committed after last collection bytes of a given JVM memory pool. +# TYPE jvm_memory_pool_collection_committed_bytes gauge +jvm_memory_pool_collection_committed_bytes{pool="Par Eden Space",} 3.3554432E8 +jvm_memory_pool_collection_committed_bytes{pool="Par Survivor Space",} 4.194304E7 +jvm_memory_pool_collection_committed_bytes{pool="CMS Old Gen",} 1.66723584E9 +# HELP jvm_memory_pool_collection_max_bytes Max bytes after last collection of a given JVM memory pool. +# TYPE jvm_memory_pool_collection_max_bytes gauge +jvm_memory_pool_collection_max_bytes{pool="Par Eden Space",} 3.3554432E8 +jvm_memory_pool_collection_max_bytes{pool="Par Survivor Space",} 4.194304E7 +jvm_memory_pool_collection_max_bytes{pool="CMS Old Gen",} 1.66723584E9 +# HELP jvm_memory_pool_collection_init_bytes Initial after last collection bytes of a given JVM memory pool. +# TYPE jvm_memory_pool_collection_init_bytes gauge +jvm_memory_pool_collection_init_bytes{pool="Par Eden Space",} 3.3554432E8 +jvm_memory_pool_collection_init_bytes{pool="Par Survivor Space",} 4.194304E7 +jvm_memory_pool_collection_init_bytes{pool="CMS Old Gen",} 1.66723584E9 +# HELP jvm_info VM version info +# TYPE jvm_info gauge +jvm_info{runtime="OpenJDK Runtime Environment",vendor="Debian",version="11.0.16+8-post-Debian-1deb11u1",} 1.0 +# HELP jvm_buffer_pool_used_bytes Used bytes of a given JVM buffer pool. +# TYPE jvm_buffer_pool_used_bytes gauge +jvm_buffer_pool_used_bytes{pool="mapped",} 9.20360582E8 +jvm_buffer_pool_used_bytes{pool="direct",} 5.1679788E7 +# HELP jvm_buffer_pool_capacity_bytes Bytes capacity of a given JVM buffer pool. +# TYPE jvm_buffer_pool_capacity_bytes gauge +jvm_buffer_pool_capacity_bytes{pool="mapped",} 9.20360582E8 +jvm_buffer_pool_capacity_bytes{pool="direct",} 5.1679786E7 +# HELP jvm_buffer_pool_used_buffers Used buffers of a given JVM buffer pool. +# TYPE jvm_buffer_pool_used_buffers gauge +jvm_buffer_pool_used_buffers{pool="mapped",} 74.0 +jvm_buffer_pool_used_buffers{pool="direct",} 34.0 +# HELP jmx_exporter_build_info A metric with a constant '1' value labeled with the version of the JMX exporter. +# TYPE jmx_exporter_build_info gauge +jmx_exporter_build_info{version="0.17.2",name="jmx_prometheus_javaagent",} 1.0 +# HELP jmx_config_reload_failure_created Number of times configuration have failed to be reloaded. +# TYPE jmx_config_reload_failure_created gauge +jmx_config_reload_failure_created 1.666810482756E9 +# HELP jmx_config_reload_success_created Number of times configuration have successfully been reloaded. +# TYPE jmx_config_reload_success_created gauge +jmx_config_reload_success_created 1.666810482755E9 +# HELP jvm_memory_pool_allocated_bytes_created Total bytes allocated in a given JVM memory pool. Only updated after GC, not continuously. +# TYPE jvm_memory_pool_allocated_bytes_created gauge +jvm_memory_pool_allocated_bytes_created{pool="Par Survivor Space",} 1.666810483789E9 +jvm_memory_pool_allocated_bytes_created{pool="CMS Old Gen",} 1.666810484715E9 +jvm_memory_pool_allocated_bytes_created{pool="CodeHeap 'profiled nmethods'",} 1.666810483788E9 +jvm_memory_pool_allocated_bytes_created{pool="CodeHeap 'non-profiled nmethods'",} 1.666810483789E9 +jvm_memory_pool_allocated_bytes_created{pool="Compressed Class Space",} 1.666810483789E9 +jvm_memory_pool_allocated_bytes_created{pool="Metaspace",} 1.666810483789E9 +jvm_memory_pool_allocated_bytes_created{pool="Par Eden Space",} 1.666810483789E9 +jvm_memory_pool_allocated_bytes_created{pool="CodeHeap 'non-nmethods'",} 1.666810483789E9
\ No newline at end of file |