Port Ceph collector to Go (#18582)
Co-authored-by: ilyam8 <ilya@netdata.cloud>
Fotis Voutsas committed
Sep 27, 2024 at 14:13 UTC
32e26f24957b4346846f5e9a4857738d8d77c67a
24 files changed
+5612
-2
src/go/plugin/go.d/README.md
+1
@@ -58,6 +58,7 @@ see the appropriate collector readme.
58
| [bind](https://github.com/netdata/netdata/tree/master/src/go/plugin/go.d/modules/bind) | ISC Bind |
59
| [boinc](https://github.com/netdata/netdata/tree/master/src/go/plugin/go.d/modules/boinc) | BOINC |
60
| [cassandra](https://github.com/netdata/netdata/tree/master/src/go/plugin/go.d/modules/cassandra) | Cassandra |
61
+| [ceph](https://github.com/netdata/netdata/tree/master/src/go/plugin/go.d/modules/ceph) | Ceph |
62
| [chrony](https://github.com/netdata/netdata/tree/master/src/go/plugin/go.d/modules/chrony) | Chrony |
63
| [clickhouse](https://github.com/netdata/netdata/tree/master/src/go/plugin/go.d/modules/clickhouse) | ClickHouse |
64
| [cockroachdb](https://github.com/netdata/netdata/tree/master/src/go/plugin/go.d/modules/cockroachdb) | CockroachDB |
src/go/plugin/go.d/agent/discovery/sd/pipeline/promport.go
-2
@@ -46,7 +46,6 @@ var prometheusPortAllocations = map[int]string{
46
9125: "statsd_exporter",
47
9126: "new_relic_exporter",
48
9127: "pgbouncer_exporter",
49
- 9128: "ceph_exporter",
49
9129: "haproxy_log_exporter",
50
9130: "unifi_poller",
51
9131: "varnish_exporter",
@@ -193,7 +192,6 @@ var prometheusPortAllocations = map[int]string{
192
9280: "citrix_netscaler_exporter",
193
9281: "fastd_exporter",
194
9282: "freeswitch_exporter",
196
- 9283: "ceph_ceph-mgr_prometheus_plugin",
195
9284: "gobetween",
196
9285: "database_exporter",
197
9286: "vdo_compression_and_deduplication_exporter",
src/go/plugin/go.d/config/go.d.conf
+1
@@ -23,6 +23,7 @@ modules:
23
# beanstalk: yes
24
# bind: yes
25
# boinc: yes
26
+# ceph: yes
27
# chrony: yes
28
# clickhouse: yes
29
# cockroachdb: yes
src/go/plugin/go.d/config/go.d/ceph.conf
new
+6
@@ -0,0 +1,6 @@
1
+## All available configuration options, their descriptions and default values:
2
+## https://github.com/netdata/netdata/tree/master/src/go/plugin/go.d/modules/ceph#readme
3
+
4
+#jobs:
5
+# - name: local
6
+# url: https://127.0.0.1:8443
src/go/plugin/go.d/config/go.d/sd/net_listeners.conf
+7
@@ -26,6 +26,8 @@ classify:
26
expr: '{{ and (eq .Port "8653") (eq .Comm "bind" "named") }}'
27
- tags: "cassandra"
28
expr: '{{ and (eq .Port "7072") (glob .Cmdline "*cassandra*") }}'
29
+ - tags: "ceph"
30
+ expr: '{{ and (eq .Port "8443") (eq .Comm "ceph-mgr") }}'
31
- tags: "chrony"
32
expr: '{{ and (eq .Port "323") (eq .Comm "chronyd") }}'
33
- tags: "clickhouse"
@@ -190,6 +192,11 @@ compose:
192
module: cassandra
193
name: local
194
url: http://{{.Address}}/metrics
195
+ - selector: "ceph"
196
+ template: |
197
+ module: ceph
198
+ name: local
199
+ url: https://{{.Address}}
200
- selector: "chrony"
201
template: |
202
module: chrony
src/go/plugin/go.d/modules/ceph/api.go
new
+126
@@ -0,0 +1,126 @@
1
+// SPDX-License-Identifier: GPL-3.0-or-later
2
+
3
+package ceph
4
+
5
+import (
6
+ "net/url"
7
+)
8
+
9
+// https://docs.ceph.com/en/reef/mgr/ceph_api/
10
+
11
+const (
12
+ urlPathApiAuth = "/api/auth"
13
+ urlPathApiAuthCheck = "/api/auth/check"
14
+ urlPathApiAuthLogout = "/api/auth/logout"
15
+ urlPathApiHealthMinimal = "/api/health/minimal"
16
+ urlPathApiMonitor = "/api/monitor"
17
+ urlPathApiOsd = "/api/osd"
18
+ urlPathApiPool = "/api/pool"
19
+)
20
+
21
+var (
22
+ urlQueryApiPool = url.Values{"stats": {"true"}}.Encode()
23
+)
24
+
25
+const (
26
+ hdrAcceptVersion = "application/vnd.ceph.api.v1.0+json"
27
+ hdrContentTypeJson = "application/json"
28
+)
29
+
30
+type apiHealthMinimalResponse struct {
31
+ Health struct {
32
+ Status string `json:"status"`
33
+ } `json:"health"`
34
+ MonStatus struct {
35
+ MonMap struct {
36
+ Mons []any `json:"mons"`
37
+ } `json:"monmap"`
38
+ } `json:"mon_status"`
39
+ ScrubStatus string `json:"scrub_status"`
40
+ OsdMap struct {
41
+ Osds []struct {
42
+ In int64 `json:"in"`
43
+ Up int64 `json:"up"`
44
+ } `json:"osds"`
45
+ } `json:"osd_map"`
46
+ PgInfo struct {
47
+ ObjectStats struct {
48
+ NumObjects int64 `json:"num_objects"`
49
+ NumObjectsDegraded int64 `json:"num_objects_degraded"`
50
+ NumObjectsMisplaced int64 `json:"num_objects_misplaced"`
51
+ NumObjectsUnfound int64 `json:"num_objects_unfound"`
52
+ } `json:"object_stats"`
53
+ Statuses map[string]int64 `json:"statuses"`
54
+ PgsPerOsd float64 `json:"pgs_per_osd"`
55
+ } `json:"pg_info"`
56
+ Pools []any `json:"pools"`
57
+ MgrMap struct {
58
+ ActiveName string `json:"active_name"`
59
+ Standbys []struct {
60
+ Gid int `json:"gid"`
61
+ } `json:"standbys"`
62
+ } `json:"mgr_map"`
63
+ Df struct {
64
+ Stats struct {
65
+ TotalAvailBytes int64 `json:"total_avail_bytes"`
66
+ TotalBytes int64 `json:"total_bytes"`
67
+ TotalUsedRawBytes int64 `json:"total_used_raw_bytes"`
68
+ } `json:"stats"`
69
+ } `json:"df"`
70
+ ClientPerf struct {
71
+ ReadBytesSec float64 `json:"read_bytes_sec"`
72
+ ReadOpPerSec float64 `json:"read_op_per_sec"`
73
+ WriteBytesSec float64 `json:"write_bytes_sec"`
74
+ WriteOpPerSec float64 `json:"write_op_per_sec"`
75
+ RecoveringBytesPerSec float64 `json:"recovering_bytes_per_sec"`
76
+ } `json:"client_perf"`
77
+ Hosts int64 `json:"hosts"`
78
+ Rgw int64 `json:"rgw"`
79
+ IscsiDaemons struct {
80
+ Up int64 `json:"up"`
81
+ Down int64 `json:"down"`
82
+ } `json:"iscsi_daemons"`
83
+}
84
+
85
+type apiOsdResponse struct {
86
+ UUID string `json:"uuid"`
87
+ ID int64 `json:"id"`
88
+ Up int64 `json:"up"`
89
+ In int64 `json:"in"`
90
+ OsdStats struct {
91
+ Statfs struct {
92
+ Total int64 `json:"total"`
93
+ Available int64 `json:"available"`
94
+ } `json:"statfs"`
95
+ PerfStat struct {
96
+ CommitLatencyMs float64 `json:"commit_latency_ms"`
97
+ ApplyLatencyMs float64 `json:"apply_latency_ms"`
98
+ } `json:"perf_stat"`
99
+ } `json:"osd_stats"`
100
+ Stats struct {
101
+ OpW float64 `json:"op_w"`
102
+ OpInBytes float64 `json:"op_in_bytes"`
103
+ OpR float64 `json:"op_r"`
104
+ OpOutBytes float64 `json:"op_out_bytes"`
105
+ } `json:"stats"`
106
+ Tree struct {
107
+ DeviceClass string `json:"device_class"`
108
+ Type string `json:"type"`
109
+ Name string `json:"name"`
110
+ } `json:"tree"`
111
+}
112
+
113
+type apiPoolResponse struct {
114
+ PoolName string `json:"pool_name"`
115
+ Stats struct {
116
+ Stored struct{ Latest float64 } `json:"stored"`
117
+ Objects struct{ Latest float64 } `json:"objects"`
118
+ AvailRaw struct{ Latest float64 } `json:"avail_raw"`
119
+ BytesUsed struct{ Latest float64 } `json:"bytes_used"`
120
+ PercentUsed struct{ Latest float64 } `json:"percent_used"`
121
+ Reads struct{ Latest float64 } `json:"rd"`
122
+ ReadBytes struct{ Latest float64 } `json:"rd_bytes"`
123
+ Writes struct{ Latest float64 } `json:"wr"`
124
+ WrittenBytes struct{ Latest float64 } `json:"wr_bytes"`
125
+ } `json:"stats"`
126
+}
src/go/plugin/go.d/modules/ceph/auth.go
new
+139
@@ -0,0 +1,139 @@
1
+// SPDX-License-Identifier: GPL-3.0-or-later
2
+
3
+package ceph
4
+
5
+import (
6
+ "bytes"
7
+ "encoding/json"
8
+ "errors"
9
+ "io"
10
+ "net/http"
11
+ "net/url"
12
+
13
+ "github.com/netdata/netdata/go/plugins/plugin/go.d/pkg/web"
14
+)
15
+
16
+type (
17
+ authLoginResp struct {
18
+ Token string `json:"token"`
19
+ }
20
+ authCheckResp struct {
21
+ Username string `json:"username"`
22
+ Permissions map[string]any `json:"permissions"`
23
+ }
24
+)
25
+
26
+func (c *Ceph) authLogin() (string, error) {
27
+ // https://docs.ceph.com/en/reef/mgr/ceph_api/#post--api-auth
28
+
29
+ req, err := func() (*http.Request, error) {
30
+ var credentials = struct {
31
+ Username string `json:"username"`
32
+ Password string `json:"password"`
33
+ }{
34
+ Username: c.Username,
35
+ Password: c.Password,
36
+ }
37
+
38
+ bs, err := json.Marshal(credentials)
39
+ if err != nil {
40
+ return nil, err
41
+ }
42
+
43
+ req, err := web.NewHTTPRequestWithPath(c.RequestConfig, urlPathApiAuth)
44
+ if err != nil {
45
+ return nil, err
46
+ }
47
+
48
+ body := bytes.NewReader(bs)
49
+
50
+ req.Body = io.NopCloser(body)
51
+ req.ContentLength = int64(body.Len())
52
+ req.Method = http.MethodPost
53
+ req.Header.Set("Accept", hdrAcceptVersion)
54
+ req.Header.Set("Content-Type", hdrContentTypeJson)
55
+
56
+ return req, nil
57
+ }()
58
+ if err != nil {
59
+ return "", err
60
+ }
61
+
62
+ var tok authLoginResp
63
+
64
+ if err := c.webClient(201).RequestJSON(req, &tok); err != nil {
65
+ return "", err
66
+ }
67
+
68
+ if tok.Token == "" {
69
+ return "", errors.New("empty token")
70
+ }
71
+
72
+ return tok.Token, nil
73
+}
74
+
75
+func (c *Ceph) authCheck() (bool, error) {
76
+ // https://docs.ceph.com/en/reef/mgr/ceph_api/#post--api-auth-check
77
+ if c.token == "" {
78
+ return false, nil
79
+ }
80
+
81
+ req, err := func() (*http.Request, error) {
82
+ bs, err := json.Marshal(authLoginResp{Token: c.token})
83
+ if err != nil {
84
+ return nil, err
85
+ }
86
+
87
+ req, err := web.NewHTTPRequestWithPath(c.RequestConfig, urlPathApiAuthCheck)
88
+ if err != nil {
89
+ return nil, err
90
+ }
91
+
92
+ body := bytes.NewReader(bs)
93
+
94
+ req.Body = io.NopCloser(body)
95
+ req.ContentLength = int64(body.Len())
96
+ req.URL.RawQuery = url.Values{"token": {c.token}}.Encode() // TODO: it seems not necessary?
97
+ req.Method = http.MethodPost
98
+ req.Header.Set("Accept", hdrAcceptVersion)
99
+ req.Header.Set("Content-Type", hdrContentTypeJson)
100
+ return req, nil
101
+ }()
102
+ if err != nil {
103
+ return false, err
104
+ }
105
+
106
+ var resp authCheckResp
107
+
108
+ if err := c.webClient().RequestJSON(req, &resp); err != nil {
109
+ return false, err
110
+ }
111
+
112
+ return resp.Username != "", nil
113
+}
114
+
115
+func (c *Ceph) authLogout() error {
116
+ // https://docs.ceph.com/en/reef/mgr/ceph_api/#post--api-auth-logout
117
+
118
+ if c.token == "" {
119
+ return nil
120
+ }
121
+ defer func() { c.token = "" }()
122
+
123
+ req, err := func() (*http.Request, error) {
124
+ req, err := web.NewHTTPRequestWithPath(c.RequestConfig, urlPathApiAuthLogout)
125
+ if err != nil {
126
+ return nil, err
127
+ }
128
+
129
+ req.Method = http.MethodPost
130
+ req.Header.Set("Accept", hdrAcceptVersion)
131
+ req.Header.Set("Authorization", "Bearer "+c.token)
132
+ return req, nil
133
+ }()
134
+ if err != nil {
135
+ return err
136
+ }
137
+
138
+ return c.webClient().Request(req, nil)
139
+}
src/go/plugin/go.d/modules/ceph/ceph.go
new
+132
@@ -0,0 +1,132 @@
1
+// SPDX-License-Identifier: GPL-3.0-or-later
2
+
3
+package ceph
4
+
5
+import (
6
+ _ "embed"
7
+ "errors"
8
+ "fmt"
9
+ "net/http"
10
+ "sync"
11
+ "time"
12
+
13
+ "github.com/netdata/netdata/go/plugins/plugin/go.d/agent/module"
14
+ "github.com/netdata/netdata/go/plugins/plugin/go.d/pkg/confopt"
15
+ "github.com/netdata/netdata/go/plugins/plugin/go.d/pkg/tlscfg"
16
+ "github.com/netdata/netdata/go/plugins/plugin/go.d/pkg/web"
17
+)
18
+
19
+//go:embed "config_schema.json"
20
+var configSchema string
21
+
22
+func init() {
23
+ module.Register("ceph", module.Creator{
24
+ JobConfigSchema: configSchema,
25
+ Defaults: module.Defaults{
26
+ UpdateEvery: 10,
27
+ },
28
+ Create: func() module.Module { return New() },
29
+ Config: func() any { return &Config{} },
30
+ })
31
+}
32
+
33
+func New() *Ceph {
34
+ return &Ceph{
35
+ Config: Config{
36
+ HTTPConfig: web.HTTPConfig{
37
+ RequestConfig: web.RequestConfig{
38
+ URL: "https://127.0.0.1:8443",
39
+ },
40
+ ClientConfig: web.ClientConfig{
41
+ Timeout: confopt.Duration(time.Second * 2),
42
+ TLSConfig: tlscfg.TLSConfig{
43
+ InsecureSkipVerify: true,
44
+ },
45
+ },
46
+ },
47
+ },
48
+ charts: &module.Charts{},
49
+ seenPools: make(map[string]bool),
50
+ seenOsds: make(map[string]bool),
51
+ }
52
+}
53
+
54
+type Config struct {
55
+ UpdateEvery int `yaml:"update_every,omitempty" json:"update_every"`
56
+ web.HTTPConfig `yaml:",inline" json:""`
57
+}
58
+
59
+type Ceph struct {
60
+ module.Base
61
+ Config `yaml:",inline" json:""`
62
+
63
+ charts *module.Charts
64
+ addClusterChartsOnce sync.Once
65
+
66
+ httpClient *http.Client
67
+
68
+ token string
69
+
70
+ fsid string // a unique identifier for the cluster
71
+
72
+ seenPools map[string]bool
73
+ seenOsds map[string]bool
74
+}
75
+
76
+func (c *Ceph) Configuration() any {
77
+ return c.Config
78
+}
79
+
80
+func (c *Ceph) Init() error {
81
+ if err := c.validateConfig(); err != nil {
82
+ return fmt.Errorf("invalid config: %v", err)
83
+ }
84
+
85
+ httpClient, err := web.NewHTTPClient(c.ClientConfig)
86
+ if err != nil {
87
+ return err
88
+ }
89
+ c.httpClient = httpClient
90
+
91
+ return nil
92
+}
93
+
94
+func (c *Ceph) Check() error {
95
+ mx, err := c.collect()
96
+ if err != nil {
97
+ c.Error(err)
98
+ return err
99
+ }
100
+
101
+ if len(mx) == 0 {
102
+ return errors.New("no metrics collected")
103
+ }
104
+
105
+ return nil
106
+}
107
+
108
+func (c *Ceph) Charts() *module.Charts {
109
+ return c.charts
110
+}
111
+
112
+func (c *Ceph) Collect() map[string]int64 {
113
+ mx, err := c.collect()
114
+ if err != nil {
115
+ c.Error(err)
116
+ }
117
+
118
+ if len(mx) == 0 {
119
+ return nil
120
+ }
121
+
122
+ return mx
123
+}
124
+
125
+func (c *Ceph) Cleanup() {
126
+ if c.httpClient != nil {
127
+ if err := c.authLogout(); err != nil {
128
+ c.Warningf("failed to logout: %v", err)
129
+ }
130
+ c.httpClient.CloseIdleConnections()
131
+ }
132
+}
src/go/plugin/go.d/modules/ceph/ceph_test.go
new
+331
@@ -0,0 +1,331 @@
1
+// SPDX-License-Identifier: GPL-3.0-or-later
2
+
3
+package ceph
4
+
5
+import (
6
+ "bytes"
7
+ "encoding/json"
8
+ "io"
9
+ "net/http"
10
+ "net/http/httptest"
11
+ "os"
12
+ "sync/atomic"
13
+ "testing"
14
+
15
+ "github.com/stretchr/testify/assert"
16
+
17
+ "github.com/netdata/netdata/go/plugins/plugin/go.d/agent/module"
18
+ "github.com/netdata/netdata/go/plugins/plugin/go.d/pkg/web"
19
+
20
+ "github.com/stretchr/testify/require"
21
+)
22
+
23
+var (
24
+ dataConfigJSON, _ = os.ReadFile("testdata/config.json")
25
+ dataConfigYAML, _ = os.ReadFile("testdata/config.yaml")
26
+
27
+ dataVer16ApiHealthMinimal, _ = os.ReadFile("testdata/v16.2.15/api_health_minimal.json")
28
+ dataVer16ApiOsd, _ = os.ReadFile("testdata/v16.2.15/api_osd.json")
29
+ dataVer16ApiPoolStats, _ = os.ReadFile("testdata/v16.2.15/api_pool_stats.json")
30
+ dataVer16ApiMonitor, _ = os.ReadFile("testdata/v16.2.15/api_monitor.json")
31
+)
32
+
33
+func Test_testDataIsValid(t *testing.T) {
34
+ for name, data := range map[string][]byte{
35
+ "dataConfigJSON": dataConfigJSON,
36
+ "dataConfigYAML": dataConfigYAML,
37
+ "dataVer16ApiHealthMinimal": dataVer16ApiHealthMinimal,
38
+ "dataVer16ApiOsd": dataVer16ApiOsd,
39
+ "dataVer16ApiPoolStats": dataVer16ApiPoolStats,
40
+ "dataVer16ApiMonitor": dataVer16ApiMonitor,
41
+ } {
42
+ require.NotNil(t, data, name)
43
+ }
44
+}
45
+
46
+func TestCeph_Configuration(t *testing.T) {
47
+ module.TestConfigurationSerialize(t, &Ceph{}, dataConfigJSON, dataConfigYAML)
48
+}
49
+
50
+func TestCeph_Init(t *testing.T) {
51
+ tesceph := map[string]struct {
52
+ wantFail bool
53
+ config Config
54
+ }{
55
+ "fails with default": {
56
+ wantFail: true,
57
+ config: New().Config,
58
+ },
59
+ "fail when URL not set": {
60
+ wantFail: true,
61
+ config: Config{
62
+ HTTPConfig: web.HTTPConfig{
63
+ RequestConfig: web.RequestConfig{URL: ""},
64
+ },
65
+ },
66
+ },
67
+ }
68
+
69
+ for name, test := range tesceph {
70
+ t.Run(name, func(t *testing.T) {
71
+ ceph := New()
72
+ ceph.Config = test.config
73
+
74
+ if test.wantFail {
75
+ assert.Error(t, ceph.Init())
76
+ } else {
77
+ assert.NoError(t, ceph.Init())
78
+ }
79
+ })
80
+ }
81
+}
82
+
83
+func TestCeph_Check(t *testing.T) {
84
+ tests := map[string]struct {
85
+ wantFail bool
86
+ prepare func(t *testing.T) (ceph *Ceph, cleanup func())
87
+ }{
88
+ "success with valid API key": {
89
+ wantFail: false,
90
+ prepare: caseOk,
91
+ },
92
+ "fail on connection refused": {
93
+ wantFail: true,
94
+ prepare: caseConnectionRefused,
95
+ },
96
+ "fail on 404 response": {
97
+ wantFail: true,
98
+ prepare: case404,
99
+ },
100
+ }
101
+
102
+ for name, test := range tests {
103
+ t.Run(name, func(t *testing.T) {
104
+ ceph, cleanup := test.prepare(t)
105
+ defer cleanup()
106
+
107
+ if test.wantFail {
108
+ assert.Error(t, ceph.Check())
109
+ } else {
110
+ assert.NoError(t, ceph.Check())
111
+ }
112
+ })
113
+ }
114
+}
115
+
116
+func TestCeph_Charts(t *testing.T) {
117
+ assert.NotNil(t, New().Charts())
118
+}
119
+
120
+func TestCeph_Collect(t *testing.T) {
121
+ tests := map[string]struct {
122
+ prepare func(t *testing.T) (ceph *Ceph, cleanup func())
123
+ wantNumOfCharts int
124
+ wantMetrics map[string]int64
125
+ }{
126
+ "success with valid API key": {
127
+ prepare: caseOk,
128
+ wantNumOfCharts: len(clusterCharts) + len(osdChartsTmpl)*2 + len(poolChartsTmpl)*2,
129
+ wantMetrics: map[string]int64{
130
+ "client_perf_read_bytes_sec": 1,
131
+ "client_perf_read_op_per_sec": 1,
132
+ "client_perf_recovering_bytes_per_sec": 1,
133
+ "client_perf_write_bytes_sec": 1,
134
+ "client_perf_write_op_per_sec": 1,
135
+ "health_err": 0,
136
+ "health_ok": 0,
137
+ "health_warn": 1,
138
+ "hosts_num": 1,
139
+ "iscsi_daemons_down_num": 1,
140
+ "iscsi_daemons_num": 2,
141
+ "iscsi_daemons_up_num": 1,
142
+ "mgr_active_num": 1,
143
+ "mgr_standby_num": 1,
144
+ "monitors_num": 1,
145
+ "objects_degraded_num": 1,
146
+ "objects_healthy_num": 3,
147
+ "objects_misplaced_num": 1,
148
+ "objects_num": 6,
149
+ "objects_unfound_num": 1,
150
+ "osd_f5bbbe9d-e85b-419c-af5a-a57e2527cad3_apply_latency_ms": 1,
151
+ "osd_f5bbbe9d-e85b-419c-af5a-a57e2527cad3_commit_latency_ms": 1,
152
+ "osd_f5bbbe9d-e85b-419c-af5a-a57e2527cad3_read_bytes": 1,
153
+ "osd_f5bbbe9d-e85b-419c-af5a-a57e2527cad3_read_ops": 1,
154
+ "osd_f5bbbe9d-e85b-419c-af5a-a57e2527cad3_size_bytes": 68715282432,
155
+ "osd_f5bbbe9d-e85b-419c-af5a-a57e2527cad3_space_avail_bytes": 68410753024,
156
+ "osd_f5bbbe9d-e85b-419c-af5a-a57e2527cad3_space_used_bytes": 304529408,
157
+ "osd_f5bbbe9d-e85b-419c-af5a-a57e2527cad3_status_down": 0,
158
+ "osd_f5bbbe9d-e85b-419c-af5a-a57e2527cad3_status_in": 1,
159
+ "osd_f5bbbe9d-e85b-419c-af5a-a57e2527cad3_status_out": 0,
160
+ "osd_f5bbbe9d-e85b-419c-af5a-a57e2527cad3_status_up": 1,
161
+ "osd_f5bbbe9d-e85b-419c-af5a-a57e2527cad3_write_ops": 1,
162
+ "osd_f5bbbe9d-e85b-419c-af5a-a57e2527cad3_written_bytes": 1,
163
+ "osd_f78537db-9b18-4c62-a24f-a4344fc28de7_apply_latency_ms": 1,
164
+ "osd_f78537db-9b18-4c62-a24f-a4344fc28de7_commit_latency_ms": 1,
165
+ "osd_f78537db-9b18-4c62-a24f-a4344fc28de7_read_bytes": 1,
166
+ "osd_f78537db-9b18-4c62-a24f-a4344fc28de7_read_ops": 1,
167
+ "osd_f78537db-9b18-4c62-a24f-a4344fc28de7_size_bytes": 107369988096,
168
+ "osd_f78537db-9b18-4c62-a24f-a4344fc28de7_space_avail_bytes": 107065458688,
169
+ "osd_f78537db-9b18-4c62-a24f-a4344fc28de7_space_used_bytes": 304529408,
170
+ "osd_f78537db-9b18-4c62-a24f-a4344fc28de7_status_down": 0,
171
+ "osd_f78537db-9b18-4c62-a24f-a4344fc28de7_status_in": 1,
172
+ "osd_f78537db-9b18-4c62-a24f-a4344fc28de7_status_out": 0,
173
+ "osd_f78537db-9b18-4c62-a24f-a4344fc28de7_status_up": 1,
174
+ "osd_f78537db-9b18-4c62-a24f-a4344fc28de7_write_ops": 1,
175
+ "osd_f78537db-9b18-4c62-a24f-a4344fc28de7_written_bytes": 1,
176
+ "osds_down_num": 0,
177
+ "osds_in_num": 2,
178
+ "osds_num": 2,
179
+ "osds_out_num": 0,
180
+ "osds_up_num": 2,
181
+ "pg_status_category_clean": 1,
182
+ "pg_status_category_unknown": 0,
183
+ "pg_status_category_warning": 1,
184
+ "pg_status_category_working": 0,
185
+ "pgs_num": 2,
186
+ "pgs_per_osd": 2,
187
+ "pool_device_health_metrics_objects": 3,
188
+ "pool_device_health_metrics_read_bytes": 1,
189
+ "pool_device_health_metrics_read_ops": 1,
190
+ "pool_device_health_metrics_size": 166530172973,
191
+ "pool_device_health_metrics_space_avail_bytes": 166530172972,
192
+ "pool_device_health_metrics_space_used_bytes": 1,
193
+ "pool_device_health_metrics_space_utilization": 1000,
194
+ "pool_device_health_metrics_write_ops": 3,
195
+ "pool_device_health_metrics_written_bytes": 6144,
196
+ "pool_mySuperPool_objects": 1,
197
+ "pool_mySuperPool_read_bytes": 1,
198
+ "pool_mySuperPool_read_ops": 1,
199
+ "pool_mySuperPool_size": 166530172973,
200
+ "pool_mySuperPool_space_avail_bytes": 166530172972,
201
+ "pool_mySuperPool_space_used_bytes": 1,
202
+ "pool_mySuperPool_space_utilization": 1000,
203
+ "pool_mySuperPool_write_ops": 1,
204
+ "pool_mySuperPool_written_bytes": 1,
205
+ "pools_num": 2,
206
+ "raw_capacity_avail_bytes": 175476178944,
207
+ "raw_capacity_used_bytes": 609091584,
208
+ "raw_capacity_utilization": 345,
209
+ "rgw_num": 1,
210
+ "scrub_status_active": 0,
211
+ "scrub_status_disabled": 0,
212
+ "scrub_status_inactive": 1,
213
+ },
214
+ },
215
+ "fail on connection refused": {
216
+ prepare: caseConnectionRefused,
217
+ wantMetrics: nil,
218
+ },
219
+ "fail on 404 response": {
220
+ prepare: case404,
221
+ wantMetrics: nil,
222
+ },
223
+ }
224
+
225
+ for name, test := range tests {
226
+ t.Run(name, func(t *testing.T) {
227
+ ceph, cleanup := test.prepare(t)
228
+ defer cleanup()
229
+
230
+ _ = ceph.Check()
231
+
232
+ mx := ceph.Collect()
233
+
234
+ require.Equal(t, test.wantMetrics, mx)
235
+
236
+ if len(test.wantMetrics) > 0 {
237
+ assert.Equal(t, test.wantNumOfCharts, len(*ceph.Charts()), "want charts")
238
+
239
+ module.TestMetricsHasAllChartsDims(t, ceph.Charts(), mx)
240
+ }
241
+ })
242
+ }
243
+}
244
+
245
+func caseOk(t *testing.T) (*Ceph, func()) {
246
+ t.Helper()
247
+
248
+ loginResp, _ := json.Marshal(authLoginResp{Token: "secret_token"})
249
+ checkResp, _ := json.Marshal(authCheckResp{Username: "username"})
250
+ var loggedIn atomic.Bool
251
+
252
+ srv := httptest.NewServer(http.HandlerFunc(
253
+ func(w http.ResponseWriter, r *http.Request) {
254
+ switch r.Method {
255
+ case http.MethodPost:
256
+ switch r.URL.Path {
257
+ case urlPathApiAuth:
258
+ _, _ = w.Write(loginResp)
259
+ w.WriteHeader(http.StatusCreated)
260
+ loggedIn.Store(true)
261
+ case urlPathApiAuthCheck:
262
+ bs, _ := io.ReadAll(r.Body)
263
+ if bytes.Equal(bs, loginResp) {
264
+ _, _ = w.Write(checkResp)
265
+ } else {
266
+ w.WriteHeader(http.StatusNotFound)
267
+ }
268
+ case urlPathApiAuthLogout:
269
+ w.WriteHeader(http.StatusOK)
270
+ loggedIn.Store(false)
271
+ default:
272
+ w.WriteHeader(http.StatusNotFound)
273
+ }
274
+ case http.MethodGet:
275
+ if !loggedIn.Load() {
276
+ w.WriteHeader(http.StatusUnauthorized)
277
+ return
278
+ }
279
+ switch r.URL.Path {
280
+ case urlPathApiHealthMinimal:
281
+ _, _ = w.Write(dataVer16ApiHealthMinimal)
282
+ case urlPathApiOsd:
283
+ _, _ = w.Write(dataVer16ApiOsd)
284
+ case urlPathApiPool:
285
+ if r.URL.RawQuery != urlQueryApiPool {
286
+ w.WriteHeader(http.StatusNotFound)
287
+ } else {
288
+ _, _ = w.Write(dataVer16ApiPoolStats)
289
+ }
290
+ case urlPathApiMonitor:
291
+ _, _ = w.Write(dataVer16ApiMonitor)
292
+ default:
293
+ w.WriteHeader(http.StatusNotFound)
294
+ }
295
+ }
296
+ }))
297
+
298
+ ceph := New()
299
+ ceph.URL = srv.URL
300
+ ceph.Username = "user"
301
+ ceph.Password = "password"
302
+ require.NoError(t, ceph.Init())
303
+
304
+ return ceph, srv.Close
305
+}
306
+
307
+func caseConnectionRefused(t *testing.T) (*Ceph, func()) {
308
+ t.Helper()
309
+ ceph := New()
310
+ ceph.URL = "http://127.0.0.1:65001"
311
+ ceph.Username = "user"
312
+ ceph.Password = "password"
313
+ require.NoError(t, ceph.Init())
314
+
315
+ return ceph, func() {}
316
+}
317
+
318
+func case404(t *testing.T) (*Ceph, func()) {
319
+ t.Helper()
320
+ srv := httptest.NewServer(http.HandlerFunc(
321
+ func(w http.ResponseWriter, r *http.Request) {
322
+ w.WriteHeader(http.StatusNotFound)
323
+ }))
324
+ ceph := New()
325
+ ceph.URL = srv.URL
326
+ ceph.Username = "user"
327
+ ceph.Password = "password"
328
+ require.NoError(t, ceph.Init())
329
+
330
+ return ceph, srv.Close
331
+}
src/go/plugin/go.d/modules/ceph/charts.go
new
+576
@@ -0,0 +1,576 @@
1
+// SPDX-License-Identifier: GPL-3.0-or-later
2
+
3
+package ceph
4
+
5
+import (
6
+ "fmt"
7
+ "strings"
8
+
9
+ "github.com/netdata/netdata/go/plugins/plugin/go.d/agent/module"
10
+)
11
+
12
+const (
13
+ prioClusterStatus = module.Priority + iota
14
+ prioClusterHostsCount
15
+ prioClusterMonitorsCount
16
+ prioClusterOSDsCount
17
+ prioClusterOSDsByStatusCount
18
+ prioClusterManagersCount
19
+ prioClusterObjectGatewaysCount
20
+ prioClusterIScsiGatewaysCount
21
+ prioClusterIScsiGatewaysByStatusCount
22
+
23
+ prioClusterPhysCapacityUtilization
24
+ prioClusterPhysCapacityUsage
25
+ prioClusterObjectsCount
26
+ prioClusterObjectsByStatusPercent
27
+ prioClusterPoolsCount
28
+ prioClusterPGsCount
29
+ prioClusterPGsByStatusCount
30
+ prioClusterPGsPerOsdCount
31
+
32
+ prioClusterClientIO
33
+ prioClusterClientIOPS
34
+ prioClusterClientRecoveryThroughput
35
+ prioClusterScrubStatus
36
+
37
+ prioOsdStatus
38
+ prioOsdSpaceUsage
39
+ prioOsdIO
40
+ prioOsdIOPS
41
+ prioOsdLatency
42
+
43
+ prioPoolSpaceUtilization
44
+ prioPoolSpaceUsage
45
+ prioPoolObjectsCount
46
+ prioPoolIO
47
+ prioPoolIOPS
48
+)
49
+
50
+var clusterCharts = module.Charts{
51
+ clusterStatusChart.Copy(),
52
+ clusterHostsCountChart.Copy(),
53
+ clusterMonitorsCountChart.Copy(),
54
+ clusterOsdsCountChart.Copy(),
55
+ clusterOsdsByStatusCountChart.Copy(),
56
+ clusterManagersCountChart.Copy(),
57
+ clusterObjectGatewaysCountChart.Copy(),
58
+ clusterIScsiGatewaysCountChart.Copy(),
59
+ clusterIScsiGatewaysByStatusCountChart.Copy(),
60
+
61
+ clusterPhysCapacityUtilizationChart.Copy(),
62
+ clusterPhysCapacityUsageChart.Copy(),
63
+ clusterObjectsCountChart.Copy(),
64
+ clusterObjectsByStatusPercentChart.Copy(),
65
+ clusterPoolsCountChart.Copy(),
66
+ clusterPGsCountChart.Copy(),
67
+ clusterPGsByStatusCountChart.Copy(),
68
+ clusterPgsPerOsdCountChart.Copy(),
69
+
70
+ clusterClientIOChart.Copy(),
71
+ clusterClientIOPSChart.Copy(),
72
+ clusterRecoveryThroughputChart.Copy(),
73
+ clusterScrubStatusChart.Copy(),
74
+}
75
+
76
+var osdChartsTmpl = module.Charts{
77
+ osdStatusChartTmpl.Copy(),
78
+ osdSpaceUsageChartTmpl.Copy(),
79
+ osdIOChartTmpl.Copy(),
80
+ osdIOPSChartTmpl.Copy(),
81
+ osdLatencyChartTmpl.Copy(),
82
+}
83
+
84
+var poolChartsTmpl = module.Charts{
85
+ poolSpaceUtilizationChartTmpl.Copy(),
86
+ poolSpaceUsageChartTmpl.Copy(),
87
+ poolObjectsCountChartTmpl.Copy(),
88
+ poolIOChartTmpl.Copy(),
89
+ poolIOPSChartTmpl.Copy(),
90
+}
91
+
92
+var (
93
+ clusterStatusChart = module.Chart{
94
+ ID: "cluster_status",
95
+ Title: "Ceph Cluster Status",
96
+ Fam: "status",
97
+ Units: "status",
98
+ Ctx: "ceph.cluster_status",
99
+ Type: module.Line,
100
+ Priority: prioClusterStatus,
101
+ Dims: module.Dims{
102
+ {ID: "health_ok", Name: "ok"},
103
+ {ID: "health_err", Name: "err"},
104
+ {ID: "health_warn", Name: "warn"},
105
+ },
106
+ }
107
+ clusterHostsCountChart = module.Chart{
108
+ ID: "cluster_hosts_count",
109
+ Title: "Ceph Cluster Hosts",
110
+ Fam: "status",
111
+ Units: "hosts",
112
+ Ctx: "ceph.cluster_hosts_count",
113
+ Type: module.Line,
114
+ Priority: prioClusterHostsCount,
115
+ Dims: module.Dims{
116
+ {ID: "hosts_num", Name: "hosts"},
117
+ },
118
+ }
119
+ clusterMonitorsCountChart = module.Chart{
120
+ ID: "cluster_monitors_count",
121
+ Title: "Ceph Cluster Monitors",
122
+ Fam: "status",
123
+ Units: "monitors",
124
+ Ctx: "ceph.cluster_monitors_count",
125
+ Type: module.Line,
126
+ Priority: prioClusterMonitorsCount,
127
+ Dims: module.Dims{
128
+ {ID: "monitors_num", Name: "monitors"},
129
+ },
130
+ }
131
+ clusterOsdsCountChart = module.Chart{
132
+ ID: "cluster_osds_count",
133
+ Title: "Ceph Cluster OSDs",
134
+ Fam: "status",
135
+ Units: "osds",
136
+ Ctx: "ceph.cluster_osds_count",
137
+ Type: module.Line,
138
+ Priority: prioClusterOSDsCount,
139
+ Dims: module.Dims{
140
+ {ID: "osds_num", Name: "osds"},
141
+ },
142
+ }
143
+ clusterOsdsByStatusCountChart = module.Chart{
144
+ ID: "cluster_osds_by_status_count",
145
+ Title: "Ceph Cluster OSDs by Status",
146
+ Fam: "status",
147
+ Units: "osds",
148
+ Ctx: "ceph.cluster_osds_by_status_count",
149
+ Type: module.Line,
150
+ Priority: prioClusterOSDsByStatusCount,
151
+ Dims: module.Dims{
152
+ {ID: "osds_up_num", Name: "up"},
153
+ {ID: "osds_down_num", Name: "down"},
154
+ {ID: "osds_in_num", Name: "in"},
155
+ {ID: "osds_out_num", Name: "out"},
156
+ },
157
+ }
158
+ clusterManagersCountChart = module.Chart{
159
+ ID: "cluster_managers_count",
160
+ Title: "Ceph Cluster Managers",
161
+ Fam: "status",
162
+ Units: "managers",
163
+ Ctx: "ceph.cluster_managers_count",
164
+ Type: module.Line,
165
+ Priority: prioClusterManagersCount,
166
+ Dims: module.Dims{
167
+ {ID: "mgr_active_num", Name: "active"},
168
+ {ID: "mgr_standby_num", Name: "standby"},
169
+ },
170
+ }
171
+ clusterObjectGatewaysCountChart = module.Chart{
172
+ ID: "cluster_object_gateways_count",
173
+ Title: "Ceph Cluster Object Gateways (RGW)",
174
+ Fam: "status",
175
+ Units: "gateways",
176
+ Ctx: "ceph.cluster_object_gateways_count",
177
+ Type: module.Line,
178
+ Priority: prioClusterObjectGatewaysCount,
179
+ Dims: module.Dims{
180
+ {ID: "rgw_num", Name: "object"},
181
+ },
182
+ }
183
+ clusterIScsiGatewaysCountChart = module.Chart{
184
+ ID: "cluster_iscsi_gateways_count",
185
+ Title: "Ceph Cluster iSCSI Gateways",
186
+ Fam: "status",
187
+ Units: "gateways",
188
+ Ctx: "ceph.cluster_iscsi_gateways_count",
189
+ Type: module.Line,
190
+ Priority: prioClusterIScsiGatewaysCount,
191
+ Dims: module.Dims{
192
+ {ID: "iscsi_daemons_num", Name: "iscsi"},
193
+ },
194
+ }
195
+ clusterIScsiGatewaysByStatusCountChart = module.Chart{
196
+ ID: "cluster_iscsi_gateways_by_status_count",
197
+ Title: "Ceph Cluster iSCSI Gateways by Status",
198
+ Fam: "status",
199
+ Units: "gateways",
200
+ Ctx: "ceph.cluster_iscsi_gateways_by_status_count",
201
+ Type: module.Line,
202
+ Priority: prioClusterIScsiGatewaysByStatusCount,
203
+ Dims: module.Dims{
204
+ {ID: "iscsi_daemons_up_num", Name: "up"},
205
+ {ID: "iscsi_daemons_down_num", Name: "down"},
206
+ },
207
+ }
208
+)
209
+
210
+var (
211
+ clusterPhysCapacityUtilizationChart = module.Chart{
212
+ ID: "cluster_physical_capacity_utilization",
213
+ Title: "Ceph Cluster Physical Capacity Utilization",
214
+ Fam: "capacity",
215
+ Units: "percent",
216
+ Ctx: "ceph.cluster_physical_capacity_utilization",
217
+ Type: module.Area,
218
+ Priority: prioClusterPhysCapacityUtilization,
219
+ Dims: module.Dims{
220
+ {ID: "raw_capacity_utilization", Name: "utilization", Div: precision},
221
+ },
222
+ }
223
+ clusterPhysCapacityUsageChart = module.Chart{
224
+ ID: "cluster_physical_capacity_usage",
225
+ Title: "Ceph Cluster Physical Capacity Usage",
226
+ Fam: "capacity",
227
+ Units: "bytes",
228
+ Ctx: "ceph.cluster_physical_capacity_usage",
229
+ Type: module.Stacked,
230
+ Priority: prioClusterPhysCapacityUsage,
231
+ Dims: module.Dims{
232
+ {ID: "raw_capacity_avail_bytes", Name: "avail"},
233
+ {ID: "raw_capacity_used_bytes", Name: "used"},
234
+ },
235
+ }
236
+ clusterObjectsCountChart = module.Chart{
237
+ ID: "cluster_objects_count",
238
+ Title: "Ceph Cluster Objects",
239
+ Fam: "capacity",
240
+ Units: "objects",
241
+ Ctx: "ceph.cluster_objects_count",
242
+ Type: module.Line,
243
+ Priority: prioClusterObjectsCount,
244
+ Dims: module.Dims{
245
+ {ID: "objects_num", Name: "objects"},
246
+ },
247
+ }
248
+ clusterObjectsByStatusPercentChart = module.Chart{
249
+ ID: "cluster_objects_by_status",
250
+ Title: "Ceph Cluster Objects by Status",
251
+ Fam: "capacity",
252
+ Units: "percent",
253
+ Ctx: "ceph.cluster_objects_by_status_distribution",
254
+ Type: module.Stacked,
255
+ Priority: prioClusterObjectsByStatusPercent,
256
+ Dims: module.Dims{
257
+ {ID: "objects_healthy_num", Name: "healthy", Algo: module.PercentOfAbsolute},
258
+ {ID: "objects_misplaced_num", Name: "misplaced", Algo: module.PercentOfAbsolute},
259
+ {ID: "objects_degraded_num", Name: "degraded", Algo: module.PercentOfAbsolute},
260
+ {ID: "objects_unfound_num", Name: "unfound", Algo: module.PercentOfAbsolute},
261
+ },
262
+ }
263
+ clusterPoolsCountChart = module.Chart{
264
+ ID: "cluster_pools_count",
265
+ Title: "Ceph Cluster Pools",
266
+ Fam: "capacity",
267
+ Units: "pools",
268
+ Ctx: "ceph.cluster_pools_count",
269
+ Type: module.Line,
270
+ Priority: prioClusterPoolsCount,
271
+ Dims: module.Dims{
272
+ {ID: "pools_num", Name: "pools"},
273
+ },
274
+ }
275
+ clusterPGsCountChart = module.Chart{
276
+ ID: "cluster_pgs_count",
277
+ Title: "Ceph Cluster Placement Groups",
278
+ Fam: "capacity",
279
+ Units: "pgs",
280
+ Ctx: "ceph.cluster_pgs_count",
281
+ Type: module.Line,
282
+ Priority: prioClusterPGsCount,
283
+ Dims: module.Dims{
284
+ {ID: "pgs_num", Name: "pgs"},
285
+ },
286
+ }
287
+ clusterPGsByStatusCountChart = module.Chart{
288
+ ID: "cluster_pgs_by_status_count",
289
+ Title: "Ceph Cluster Placement Groups by Status",
290
+ Fam: "capacity",
291
+ Units: "pgs",
292
+ Ctx: "ceph.cluster_pgs_by_status_count",
293
+ Type: module.Stacked,
294
+ Priority: prioClusterPGsByStatusCount,
295
+ Dims: module.Dims{
296
+ {ID: "pg_status_category_clean", Name: "clean"},
297
+ {ID: "pg_status_category_working", Name: "working"},
298
+ {ID: "pg_status_category_warning", Name: "warning"},
299
+ {ID: "pg_status_category_unknown", Name: "unknown"},
300
+ },
301
+ }
302
+ clusterPgsPerOsdCountChart = module.Chart{
303
+ ID: "cluster_pgs_per_osd_count",
304
+ Title: "Ceph Cluster Placement Groups per OSD",
305
+ Fam: "capacity",
306
+ Units: "pgs",
307
+ Ctx: "ceph.cluster_pgs_per_osd_count",
308
+ Type: module.Line,
309
+ Priority: prioClusterPGsPerOsdCount,
310
+ Dims: module.Dims{
311
+ {ID: "pgs_per_osd", Name: "per_osd"},
312
+ },
313
+ }
314
+)
315
+
316
+var (
317
+ clusterClientIOChart = module.Chart{
318
+ ID: "cluster_client_io",
319
+ Title: "Ceph Cluster Client IO",
320
+ Fam: "performance",
321
+ Units: "bytes/s",
322
+ Ctx: "ceph.cluster_client_io",
323
+ Type: module.Area,
324
+ Priority: prioClusterClientIO,
325
+ Dims: module.Dims{
326
+ {ID: "client_perf_read_bytes_sec", Name: "read"},
327
+ {ID: "client_perf_write_bytes_sec", Name: "write", Mul: -1},
328
+ },
329
+ }
330
+ clusterClientIOPSChart = module.Chart{
331
+ ID: "cluster_client_iops",
332
+ Title: "Ceph Cluster Client IOPS",
333
+ Fam: "performance",
334
+ Units: "ops/s",
335
+ Ctx: "ceph.cluster_client_iops",
336
+ Type: module.Line,
337
+ Priority: prioClusterClientIOPS,
338
+ Dims: module.Dims{
339
+ {ID: "client_perf_read_op_per_sec", Name: "read"},
340
+ {ID: "client_perf_write_op_per_sec", Name: "write", Mul: -1},
341
+ },
342
+ }
343
+ clusterRecoveryThroughputChart = module.Chart{
344
+ ID: "cluster_recovery_throughput",
345
+ Title: "Ceph Cluster Recovery Throughput",
346
+ Fam: "performance",
347
+ Units: "bytes/s",
348
+ Ctx: "ceph.cluster_recovery_throughput",
349
+ Type: module.Line,
350
+ Priority: prioClusterClientRecoveryThroughput,
351
+ Dims: module.Dims{
352
+ {ID: "client_perf_recovering_bytes_per_sec", Name: "recovery"},
353
+ },
354
+ }
355
+ clusterScrubStatusChart = module.Chart{
356
+ ID: "cluster_scrub_status",
357
+ Title: "Ceph Cluster Scrubbing Status",
358
+ Fam: "performance",
359
+ Units: "status",
360
+ Ctx: "ceph.cluster_scrub_status",
361
+ Type: module.Line,
362
+ Priority: prioClusterScrubStatus,
363
+ Dims: module.Dims{
364
+ {ID: "scrub_status_disabled", Name: "disabled"},
365
+ {ID: "scrub_status_active", Name: "active"},
366
+ {ID: "scrub_status_inactive", Name: "inactive"},
367
+ },
368
+ }
369
+)
370
+
371
+var (
372
+ osdStatusChartTmpl = module.Chart{
373
+ ID: "osd_%s_status",
374
+ Title: "Ceph OSD Status",
375
+ Fam: "osd",
376
+ Units: "status",
377
+ Ctx: "ceph.osd_status",
378
+ Type: module.Line,
379
+ Priority: prioOsdStatus,
380
+ Dims: module.Dims{
381
+ {ID: "osd_%s_status_up", Name: "up"},
382
+ {ID: "osd_%s_status_down", Name: "down"},
383
+ {ID: "osd_%s_status_in", Name: "in"},
384
+ {ID: "osd_%s_status_out", Name: "out"},
385
+ },
386
+ }
387
+ osdSpaceUsageChartTmpl = module.Chart{
388
+ ID: "osd_%s_space_usage",
389
+ Title: "Ceph OSD Space Usage",
390
+ Fam: "osd",
391
+ Units: "bytes",
392
+ Ctx: "ceph.osd_space_usage",
393
+ Type: module.Stacked,
394
+ Priority: prioOsdSpaceUsage,
395
+ Dims: module.Dims{
396
+ {ID: "osd_%s_space_avail_bytes", Name: "avail"},
397
+ {ID: "osd_%s_space_used_bytes", Name: "used"},
398
+ },
399
+ }
400
+ osdIOChartTmpl = module.Chart{
401
+ ID: "osd_%s_io",
402
+ Title: "Ceph OSD IO",
403
+ Fam: "osd",
404
+ Units: "bytes/s",
405
+ Ctx: "ceph.osd_io",
406
+ Type: module.Area,
407
+ Priority: prioOsdIO,
408
+ Dims: module.Dims{
409
+ {ID: "osd_%s_read_bytes", Name: "read", Algo: module.Incremental},
410
+ {ID: "osd_%s_written_bytes", Name: "written", Algo: module.Incremental, Mul: -1},
411
+ },
412
+ }
413
+ osdIOPSChartTmpl = module.Chart{
414
+ ID: "osd_%s_iops",
415
+ Title: "Ceph OSD IOPS",
416
+ Fam: "osd",
417
+ Units: "ops/s",
418
+ Ctx: "ceph.osd_iops",
419
+ Type: module.Line,
420
+ Priority: prioOsdIOPS,
421
+ Dims: module.Dims{
422
+ {ID: "osd_%s_read_ops", Name: "read", Algo: module.Incremental},
423
+ {ID: "osd_%s_write_ops", Name: "write", Algo: module.Incremental},
424
+ },
425
+ }
426
+ osdLatencyChartTmpl = module.Chart{
427
+ ID: "osd_%s_latency",
428
+ Title: "Ceph OSD Latency",
429
+ Fam: "osd",
430
+ Units: "milliseconds",
431
+ Ctx: "ceph.osd_latency",
432
+ Type: module.Line,
433
+ Priority: prioOsdLatency,
434
+ Dims: module.Dims{
435
+ {ID: "osd_%s_commit_latency_ms", Name: "commit"},
436
+ {ID: "osd_%s_apply_latency_ms", Name: "apply"},
437
+ },
438
+ }
439
+)
440
+
441
+var (
442
+ poolSpaceUtilizationChartTmpl = module.Chart{
443
+ ID: "pool_%s_space_utilization",
444
+ Title: "Ceph Pool Space Utilization",
445
+ Fam: "pool",
446
+ Units: "percent",
447
+ Ctx: "ceph.pool_space_utilization",
448
+ Type: module.Area,
449
+ Priority: prioPoolSpaceUtilization,
450
+ Dims: module.Dims{
451
+ {ID: "pool_%s_space_utilization", Name: "utilization", Div: precision},
452
+ },
453
+ }
454
+ poolSpaceUsageChartTmpl = module.Chart{
455
+ ID: "pool_%s_space_usage",
456
+ Title: "Ceph Pool Space Usage",
457
+ Fam: "pool",
458
+ Units: "bytes",
459
+ Ctx: "ceph.pool_space_usage",
460
+ Type: module.Stacked,
461
+ Priority: prioPoolSpaceUsage,
462
+ Dims: module.Dims{
463
+ {ID: "pool_%s_space_avail_bytes", Name: "avail"},
464
+ {ID: "pool_%s_space_used_bytes", Name: "used"},
465
+ },
466
+ }
467
+ poolObjectsCountChartTmpl = module.Chart{
468
+ ID: "pool_%s_objects_count",
469
+ Title: "Ceph Pool Objects",
470
+ Fam: "pool",
471
+ Units: "objects",
472
+ Ctx: "ceph.pool_objects_count",
473
+ Type: module.Line,
474
+ Priority: prioPoolObjectsCount,
475
+ Dims: module.Dims{
476
+ {ID: "pool_%s_objects", Name: "objects"},
477
+ },
478
+ }
479
+ poolIOChartTmpl = module.Chart{
480
+ ID: "pool_%s_io",
481
+ Title: "Ceph Pool IO",
482
+ Fam: "pool",
483
+ Units: "bytes/s",
484
+ Ctx: "ceph.pool_io",
485
+ Type: module.Area,
486
+ Priority: prioPoolIO,
487
+ Dims: module.Dims{
488
+ {ID: "pool_%s_read_bytes", Name: "read", Algo: module.Incremental},
489
+ {ID: "pool_%s_written_bytes", Name: "written", Algo: module.Incremental, Mul: -1},
490
+ },
491
+ }
492
+ poolIOPSChartTmpl = module.Chart{
493
+ ID: "pool_%s_iops",
494
+ Title: "Ceph Pool IOPS",
495
+ Fam: "pool",
496
+ Units: "ops/s",
497
+ Ctx: "ceph.pool_iops",
498
+ Type: module.Line,
499
+ Priority: prioPoolIOPS,
500
+ Dims: module.Dims{
501
+ {ID: "pool_%s_read_ops", Name: "read", Algo: module.Incremental},
502
+ {ID: "pool_%s_write_ops", Name: "write", Algo: module.Incremental, Mul: -1},
503
+ },
504
+ }
505
+)
506
+
507
+func (c *Ceph) addClusterCharts() {
508
+ charts := clusterCharts.Copy()
509
+
510
+ for _, chart := range *charts {
511
+ chart.Labels = []module.Label{
512
+ {Key: "fsid", Value: c.fsid},
513
+ }
514
+ }
515
+
516
+ if err := c.Charts().Add(*charts...); err != nil {
517
+ c.Warning(err)
518
+ }
519
+}
520
+
521
+func (c *Ceph) addOsdCharts(osdUuid, devClass, osdName string) {
522
+ charts := osdChartsTmpl.Copy()
523
+
524
+ for _, chart := range *charts {
525
+ chart.ID = fmt.Sprintf(chart.ID, osdUuid)
526
+ chart.ID = cleanChartID(chart.ID)
527
+ chart.Labels = []module.Label{
528
+ {Key: "fsid", Value: c.fsid},
529
+ {Key: "osd_uuid", Value: osdUuid},
530
+ {Key: "osd_name", Value: osdName},
531
+ {Key: "device_class", Value: devClass},
532
+ }
533
+ for _, dim := range chart.Dims {
534
+ dim.ID = fmt.Sprintf(dim.ID, osdUuid)
535
+ }
536
+ }
537
+
538
+ if err := c.Charts().Add(*charts...); err != nil {
539
+ c.Warning(err)
540
+ }
541
+}
542
+
543
+func (c *Ceph) addPoolCharts(poolName string) {
544
+ charts := poolChartsTmpl.Copy()
545
+
546
+ for _, chart := range *charts {
547
+ chart.ID = fmt.Sprintf(chart.ID, poolName)
548
+ chart.ID = cleanChartID(chart.ID)
549
+ chart.Labels = []module.Label{
550
+ {Key: "fsid", Value: c.fsid},
551
+ {Key: "pool_name", Value: poolName},
552
+ }
553
+ for _, dim := range chart.Dims {
554
+ dim.ID = fmt.Sprintf(dim.ID, poolName)
555
+ }
556
+ }
557
+
558
+ if err := c.Charts().Add(*charts...); err != nil {
559
+ c.Warning(err)
560
+ }
561
+}
562
+
563
+func (c *Ceph) removeCharts(prefix string) {
564
+ prefix = cleanChartID(prefix)
565
+ for _, chart := range *c.Charts() {
566
+ if strings.HasPrefix(chart.ID, prefix) {
567
+ chart.MarkRemove()
568
+ chart.MarkNotCreated()
569
+ }
570
+ }
571
+}
572
+
573
+func cleanChartID(id string) string {
574
+ r := strings.NewReplacer(".", "_", " ", "_")
575
+ return strings.ToLower(r.Replace(id))
576
+}
src/go/plugin/go.d/modules/ceph/collect.go
new
+109
@@ -0,0 +1,109 @@
1
+// SPDX-License-Identifier: GPL-3.0-or-later
2
+
3
+package ceph
4
+
5
+import (
6
+ "encoding/json"
7
+ "errors"
8
+ "fmt"
9
+ "net/http"
10
+ "slices"
11
+
12
+ "github.com/netdata/netdata/go/plugins/plugin/go.d/pkg/web"
13
+)
14
+
15
+const precision = 1000
16
+
17
+func (c *Ceph) collect() (map[string]int64, error) {
18
+ mx := make(map[string]int64)
19
+
20
+ if err := c.auth(); err != nil {
21
+ return nil, err
22
+ }
23
+
24
+ if c.fsid == "" {
25
+ fsid, err := c.getFsid()
26
+ if err != nil {
27
+ return nil, fmt.Errorf("failed to get fsid: %v", err)
28
+ }
29
+ c.fsid = fsid
30
+ c.addClusterChartsOnce.Do(c.addClusterCharts)
31
+ }
32
+
33
+ if err := c.collectHealth(mx); err != nil {
34
+ return nil, fmt.Errorf("failed to collect health: %v", err)
35
+ }
36
+ if err := c.collectOsds(mx); err != nil {
37
+ return nil, fmt.Errorf("failed to collect osds: %v", err)
38
+ }
39
+ if err := c.collectPools(mx); err != nil {
40
+ return nil, fmt.Errorf("failed to collect pools: %v", err)
41
+ }
42
+
43
+ return mx, nil
44
+}
45
+
46
+func (c *Ceph) auth() error {
47
+ if c.token != "" {
48
+ ok, err := c.authCheck()
49
+ if err != nil {
50
+ return err
51
+ }
52
+ if ok {
53
+ return nil
54
+ }
55
+ c.token = ""
56
+ }
57
+
58
+ tok, err := c.authLogin()
59
+ if err != nil {
60
+ return err
61
+ }
62
+ c.token = tok
63
+
64
+ return nil
65
+}
66
+
67
+func (c *Ceph) getFsid() (string, error) {
68
+ req, err := web.NewHTTPRequestWithPath(c.RequestConfig, urlPathApiMonitor)
69
+ if err != nil {
70
+ return "", err
71
+ }
72
+
73
+ req.Header.Set("Accept", hdrAcceptVersion)
74
+ req.Header.Set("Content-Type", hdrContentTypeJson)
75
+ req.Header.Set("Authorization", "Bearer "+c.token)
76
+
77
+ var resp struct {
78
+ MonStatus struct {
79
+ MonMap struct {
80
+ FSID string `json:"fsid"`
81
+ } `json:"monmap"`
82
+ } `json:"mon_status"`
83
+ }
84
+
85
+ if err := c.webClient().RequestJSON(req, &resp); err != nil {
86
+ return "", err
87
+ }
88
+
89
+ if resp.MonStatus.MonMap.FSID == "" {
90
+ return "", errors.New("no fsid")
91
+ }
92
+
93
+ return resp.MonStatus.MonMap.FSID, nil
94
+}
95
+
96
+func (c *Ceph) webClient(statusCodes ...int) *web.Client {
97
+ return web.DoHTTP(c.httpClient).OnNokCode(func(resp *http.Response) (bool, error) {
98
+ if slices.Contains(statusCodes, resp.StatusCode) {
99
+ return true, nil
100
+ }
101
+ var msg struct {
102
+ Detail string `json:"detail"`
103
+ }
104
+ if err := json.NewDecoder(resp.Body).Decode(&msg); err == nil && msg.Detail != "" {
105
+ return false, errors.New(msg.Detail)
106
+ }
107
+ return false, nil
108
+ })
109
+}
src/go/plugin/go.d/modules/ceph/collect_health.go
new
+155
@@ -0,0 +1,155 @@
1
+// SPDX-License-Identifier: GPL-3.0-or-later
2
+
3
+package ceph
4
+
5
+import (
6
+ "strings"
7
+
8
+ "github.com/netdata/netdata/go/plugins/plugin/go.d/pkg/web"
9
+)
10
+
11
+func (c *Ceph) collectHealth(mx map[string]int64) error {
12
+ req, err := web.NewHTTPRequestWithPath(c.RequestConfig, urlPathApiHealthMinimal)
13
+ if err != nil {
14
+ return err
15
+ }
16
+
17
+ req.Header.Set("Accept", hdrAcceptVersion)
18
+ req.Header.Set("Content-Type", hdrContentTypeJson)
19
+ req.Header.Set("Authorization", "Bearer "+c.token)
20
+
21
+ var resp apiHealthMinimalResponse
22
+
23
+ if err := c.webClient().RequestJSON(req, &resp); err != nil {
24
+ return err
25
+ }
26
+
27
+ for _, v := range []string{"health_err", "health_warn", "health_ok"} {
28
+ mx[v] = 0
29
+ }
30
+ mx[strings.ToLower(resp.Health.Status)] = 1
31
+
32
+ mx["mgr_active_num"] = 0
33
+ if resp.MgrMap.ActiveName != "" {
34
+ mx["mgr_active_num"] = 1
35
+ }
36
+ mx["mgr_standby_num"] = int64(len(resp.MgrMap.Standbys))
37
+ mx["hosts_num"] = resp.Hosts
38
+ mx["rgw_num"] = resp.Rgw
39
+ mx["monitors_num"] = int64(len(resp.MonStatus.MonMap.Mons))
40
+ mx["osds_num"] = int64(len(resp.OsdMap.Osds))
41
+
42
+ for _, v := range []string{"up", "down", "in", "out"} {
43
+ mx["osds_"+v+"_num"] = 0
44
+ }
45
+ for _, v := range resp.OsdMap.Osds {
46
+ s := map[int64]string{0: "out", 1: "in"}
47
+ mx["osds_"+s[v.In]+"_num"]++
48
+
49
+ s = map[int64]string{0: "down", 1: "up"}
50
+ mx["osds_"+s[v.Up]+"_num"]++
51
+ }
52
+
53
+ mx["pools_num"] = int64(len(resp.Pools))
54
+ mx["iscsi_daemons_num"] = resp.IscsiDaemons.Up + resp.IscsiDaemons.Down
55
+ mx["iscsi_daemons_up_num"] = resp.IscsiDaemons.Up
56
+ mx["iscsi_daemons_down_num"] = resp.IscsiDaemons.Down
57
+
58
+ df := resp.Df.Stats
59
+ mx["raw_capacity_used_bytes"] = df.TotalBytes - df.TotalAvailBytes
60
+ mx["raw_capacity_avail_bytes"] = df.TotalAvailBytes
61
+ mx["raw_capacity_utilization"] = 0
62
+ if df.TotalAvailBytes > 0 {
63
+ mx["raw_capacity_utilization"] = int64(float64(df.TotalBytes-df.TotalAvailBytes) / float64(df.TotalBytes) * 100 * precision)
64
+ }
65
+
66
+ objs := resp.PgInfo.ObjectStats
67
+ mx["objects_num"] = objs.NumObjects
68
+ mx["objects_healthy_num"] = objs.NumObjects - (objs.NumObjectsMisplaced + objs.NumObjectsDegraded + objs.NumObjectsUnfound)
69
+ mx["objects_misplaced_num"] = objs.NumObjectsMisplaced
70
+ mx["objects_degraded_num"] = objs.NumObjectsDegraded
71
+ mx["objects_unfound_num"] = objs.NumObjectsUnfound
72
+ mx["pgs_per_osd"] = int64(resp.PgInfo.PgsPerOsd)
73
+
74
+ mx["pgs_num"] = 0
75
+ for _, v := range []string{"clean", "working", "warning", "unknown"} {
76
+ mx["pg_status_category_"+v] = 0
77
+ }
78
+ for k, v := range resp.PgInfo.Statuses {
79
+ mx["pg_status_category_"+pgStatusCategory(k)] += v
80
+ mx["pgs_num"] += v
81
+ }
82
+
83
+ perf := resp.ClientPerf
84
+ mx["client_perf_read_bytes_sec"] = int64(perf.ReadBytesSec)
85
+ mx["client_perf_read_op_per_sec"] = int64(perf.ReadOpPerSec)
86
+ mx["client_perf_write_bytes_sec"] = int64(perf.WriteBytesSec)
87
+ mx["client_perf_write_op_per_sec"] = int64(perf.WriteOpPerSec)
88
+ mx["client_perf_recovering_bytes_per_sec"] = int64(perf.RecoveringBytesPerSec)
89
+
90
+ for _, v := range []string{"disabled", "active", "inactive"} {
91
+ mx["scrub_status_"+v] = 0
92
+ }
93
+ mx["scrub_status_"+strings.ToLower(resp.ScrubStatus)] = 1
94
+
95
+ return nil
96
+}
97
+
98
+func pgStatusCategory(status string) string {
99
+ // 'status' is formated as 'status1+status2+...+statusN'
100
+
101
+ states := strings.Split(status, "+")
102
+
103
+ var clean, working, warning, unknown int
104
+
105
+ for _, s := range states {
106
+ switch s {
107
+ case "active", "clean":
108
+ clean++
109
+ case "activating",
110
+ "backfill_wait",
111
+ "backfilling",
112
+ "creating",
113
+ "deep",
114
+ "degraded",
115
+ "forced_backfill",
116
+ "forced_recovery",
117
+ "peering",
118
+ "peered",
119
+ "recovering",
120
+ "recovery_wait",
121
+ "repair",
122
+ "scrubbing",
123
+ "snaptrim",
124
+ "snaptrim_wait":
125
+ working++
126
+ case "backfill_toofull",
127
+ "backfill_unfound",
128
+ "down",
129
+ "incomplete",
130
+ "inconsistent",
131
+ "recovery_toofull",
132
+ "recovery_unfound",
133
+ "remapped",
134
+ "snaptrim_error",
135
+ "stale",
136
+ "undersized":
137
+ warning++
138
+ default:
139
+ unknown++
140
+ }
141
+ }
142
+
143
+ switch {
144
+ case warning > 0:
145
+ return "warning"
146
+ case unknown > 0:
147
+ return "unknown"
148
+ case working > 0:
149
+ return "working"
150
+ case clean > 0:
151
+ return "clean"
152
+ default:
153
+ return "unknown"
154
+ }
155
+}
src/go/plugin/go.d/modules/ceph/collect_osd.go
new
+66
@@ -0,0 +1,66 @@
1
+// SPDX-License-Identifier: GPL-3.0-or-later
2
+
3
+package ceph
4
+
5
+import (
6
+ "fmt"
7
+
8
+ "github.com/netdata/netdata/go/plugins/plugin/go.d/pkg/web"
9
+)
10
+
11
+func (c *Ceph) collectOsds(mx map[string]int64) error {
12
+ req, err := web.NewHTTPRequestWithPath(c.RequestConfig, urlPathApiOsd)
13
+ if err != nil {
14
+ return err
15
+ }
16
+
17
+ req.Header.Set("Accept", hdrAcceptVersion)
18
+ req.Header.Set("Content-Type", hdrContentTypeJson)
19
+ req.Header.Set("Authorization", "Bearer "+c.token)
20
+
21
+ var osds []apiOsdResponse
22
+
23
+ if err := c.webClient().RequestJSON(req, &osds); err != nil {
24
+ return err
25
+ }
26
+
27
+ seen := make(map[string]bool)
28
+
29
+ for _, osd := range osds {
30
+ px := fmt.Sprintf("osd_%s_", osd.UUID)
31
+
32
+ seen[osd.UUID] = true
33
+ if !c.seenOsds[osd.UUID] {
34
+ c.seenOsds[osd.UUID] = true
35
+ c.addOsdCharts(osd.UUID, osd.Tree.DeviceClass, osd.Tree.Name)
36
+ }
37
+
38
+ mx[px+"status_up"], mx[px+"status_down"] = 1, 0
39
+ if osd.Up == 0 {
40
+ mx[px+"status_up"], mx[px+"status_down"] = 0, 1
41
+ }
42
+ mx[px+"status_in"], mx[px+"status_out"] = 1, 0
43
+ if osd.In == 0 {
44
+ mx[px+"status_in"], mx[px+"status_out"] = 0, 1
45
+ }
46
+
47
+ mx[px+"size_bytes"] = osd.OsdStats.Statfs.Total
48
+ mx[px+"space_used_bytes"] = osd.OsdStats.Statfs.Total - osd.OsdStats.Statfs.Available
49
+ mx[px+"space_avail_bytes"] = osd.OsdStats.Statfs.Available
50
+ mx[px+"read_ops"] = int64(osd.Stats.OpR)
51
+ mx[px+"read_bytes"] = int64(osd.Stats.OpOutBytes)
52
+ mx[px+"write_ops"] = int64(osd.Stats.OpW)
53
+ mx[px+"written_bytes"] = int64(osd.Stats.OpInBytes)
54
+ mx[px+"commit_latency_ms"] = int64(osd.OsdStats.PerfStat.CommitLatencyMs)
55
+ mx[px+"apply_latency_ms"] = int64(osd.OsdStats.PerfStat.ApplyLatencyMs)
56
+ }
57
+
58
+ for uuid := range c.seenOsds {
59
+ if !seen[uuid] {
60
+ delete(c.seenOsds, uuid)
61
+ c.removeCharts(fmt.Sprintf("osd_%s_", uuid))
62
+ }
63
+ }
64
+
65
+ return nil
66
+}
src/go/plugin/go.d/modules/ceph/collect_pools.go
new
+58
@@ -0,0 +1,58 @@
1
+// SPDX-License-Identifier: GPL-3.0-or-later
2
+
3
+package ceph
4
+
5
+import (
6
+ "fmt"
7
+
8
+ "github.com/netdata/netdata/go/plugins/plugin/go.d/pkg/web"
9
+)
10
+
11
+func (c *Ceph) collectPools(mx map[string]int64) error {
12
+ req, err := web.NewHTTPRequestWithPath(c.RequestConfig, urlPathApiPool)
13
+ if err != nil {
14
+ return err
15
+ }
16
+
17
+ req.URL.RawQuery = urlQueryApiPool
18
+ req.Header.Set("Accept", hdrAcceptVersion)
19
+ req.Header.Set("Content-Type", hdrContentTypeJson)
20
+ req.Header.Set("Authorization", "Bearer "+c.token)
21
+
22
+ var pools []apiPoolResponse
23
+
24
+ if err := c.webClient().RequestJSON(req, &pools); err != nil {
25
+ return err
26
+ }
27
+
28
+ seen := make(map[string]bool)
29
+
30
+ for _, pool := range pools {
31
+ px := fmt.Sprintf("pool_%s_", pool.PoolName)
32
+
33
+ seen[pool.PoolName] = true
34
+ if !c.seenPools[pool.PoolName] {
35
+ c.seenPools[pool.PoolName] = true
36
+ c.addPoolCharts(pool.PoolName)
37
+ }
38
+
39
+ mx[px+"objects"] = int64(pool.Stats.Objects.Latest)
40
+ mx[px+"size"] = int64(pool.Stats.AvailRaw.Latest)
41
+ mx[px+"space_used_bytes"] = int64(pool.Stats.BytesUsed.Latest)
42
+ mx[px+"space_avail_bytes"] = int64(pool.Stats.AvailRaw.Latest - pool.Stats.BytesUsed.Latest)
43
+ mx[px+"space_utilization"] = int64(pool.Stats.PercentUsed.Latest * precision)
44
+ mx[px+"read_ops"] = int64(pool.Stats.Reads.Latest)
45
+ mx[px+"read_bytes"] = int64(pool.Stats.ReadBytes.Latest)
46
+ mx[px+"write_ops"] = int64(pool.Stats.Writes.Latest)
47
+ mx[px+"written_bytes"] = int64(pool.Stats.WrittenBytes.Latest)
48
+ }
49
+
50
+ for name := range c.seenPools {
51
+ if !seen[name] {
52
+ delete(c.seenPools, name)
53
+ c.removeCharts(fmt.Sprintf("pool_%s_", name))
54
+ }
55
+ }
56
+
57
+ return nil
58
+}
src/go/plugin/go.d/modules/ceph/config_schema.json
new
+186
@@ -0,0 +1,186 @@
1
+{
2
+ "jsonSchema": {
3
+ "$schema": "http://json-schema.org/draft-07/schema#",
4
+ "title": "Ceph collector configuration.",
5
+ "type": "object",
6
+ "properties": {
7
+ "update_every": {
8
+ "title": "Update every",
9
+ "description": "Data collection interval, measured in seconds.",
10
+ "type": "integer",
11
+ "minimum": 1,
12
+ "default": 10
13
+ },
14
+ "url": {
15
+ "title": "URL",
16
+ "description": "The URL of the [Ceph Manager API](https://docs.ceph.com/en/reef/mgr/ceph_api/).",
17
+ "type": "string",
18
+ "default": "https://127.0.0.1:8443",
19
+ "format": "uri"
20
+ },
21
+ "timeout": {
22
+ "title": "Timeout",
23
+ "description": "The timeout in seconds for the HTTP request.",
24
+ "type": "number",
25
+ "minimum": 0.5,
26
+ "default": 2
27
+ },
28
+ "not_follow_redirects": {
29
+ "title": "Not follow redirects",
30
+ "description": "If set, the client will not follow HTTP redirects automatically.",
31
+ "type": "boolean"
32
+ },
33
+ "username": {
34
+ "title": "Username",
35
+ "description": "The username for basic authentication.",
36
+ "type": "string",
37
+ "sensitive": true
38
+ },
39
+ "password": {
40
+ "title": "Password",
41
+ "description": "The password for basic authentication.",
42
+ "type": "string",
43
+ "sensitive": true
44
+ },
45
+ "proxy_url": {
46
+ "title": "Proxy URL",
47
+ "description": "The URL of the proxy server.",
48
+ "type": "string"
49
+ },
50
+ "proxy_username": {
51
+ "title": "Proxy username",
52
+ "description": "The username for proxy authentication.",
53
+ "type": "string",
54
+ "sensitive": true
55
+ },
56
+ "proxy_password": {
57
+ "title": "Proxy password",
58
+ "description": "The password for proxy authentication.",
59
+ "type": "string",
60
+ "sensitive": true
61
+ },
62
+ "headers": {
63
+ "title": "Headers",
64
+ "description": "Additional HTTP headers to include in the request.",
65
+ "type": [
66
+ "object",
67
+ "null"
68
+ ],
69
+ "additionalProperties": {
70
+ "type": "string"
71
+ }
72
+ },
73
+ "tls_skip_verify": {
74
+ "title": "Skip TLS verification",
75
+ "description": "If set, TLS certificate verification will be skipped.",
76
+ "type": "boolean",
77
+ "default": true
78
+ },
79
+ "tls_ca": {
80
+ "title": "TLS CA",
81
+ "description": "The path to the CA certificate file for TLS verification.",
82
+ "type": "string",
83
+ "pattern": "^$|^/"
84
+ },
85
+ "tls_cert": {
86
+ "title": "TLS certificate",
87
+ "description": "The path to the client certificate file for TLS authentication.",
88
+ "type": "string",
89
+ "pattern": "^$|^/"
90
+ },
91
+ "tls_key": {
92
+ "title": "TLS key",
93
+ "description": "The path to the client key file for TLS authentication.",
94
+ "type": "string",
95
+ "pattern": "^$|^/"
96
+ },
97
+ "body": {
98
+ "title": "Body",
99
+ "type": "string"
100
+ },
101
+ "method": {
102
+ "title": "Method",
103
+ "type": "string"
104
+ }
105
+ },
106
+ "required": [
107
+ "url",
108
+ "username",
109
+ "password"
110
+ ],
111
+ "additionalProperties": false,
112
+ "patternProperties": {
113
+ "^name$": {}
114
+ }
115
+ },
116
+ "uiSchema": {
117
+ "uiOptions": {
118
+ "fullPage": true
119
+ },
120
+ "body": {
121
+ "ui:widget": "hidden"
122
+ },
123
+ "method": {
124
+ "ui:widget": "hidden"
125
+ },
126
+ "timeout": {
127
+ "ui:help": "Accepts decimals for precise control (e.g., type 1.5 for 1.5 seconds)."
128
+ },
129
+ "username": {
130
+ "ui:widget": "password"
131
+ },
132
+ "proxy_username": {
133
+ "ui:widget": "password"
134
+ },
135
+ "password": {
136
+ "ui:widget": "password"
137
+ },
138
+ "proxy_password": {
139
+ "ui:widget": "password"
140
+ },
141
+ "ui:flavour": "tabs",
142
+ "ui:options": {
143
+ "tabs": [
144
+ {
145
+ "title": "Base",
146
+ "fields": [
147
+ "update_every",
148
+ "url",
149
+ "timeout",
150
+ "not_follow_redirects"
151
+ ]
152
+ },
153
+ {
154
+ "title": "Auth",
155
+ "fields": [
156
+ "username",
157
+ "password"
158
+ ]
159
+ },
160
+ {
161
+ "title": "TLS",
162
+ "fields": [
163
+ "tls_skip_verify",
164
+ "tls_ca",
165
+ "tls_cert",
166
+ "tls_key"
167
+ ]
168
+ },
169
+ {
170
+ "title": "Proxy",
171
+ "fields": [
172
+ "proxy_url",
173
+ "proxy_username",
174
+ "proxy_password"
175
+ ]
176
+ },
177
+ {
178
+ "title": "Headers",
179
+ "fields": [
180
+ "headers"
181
+ ]
182
+ }
183
+ ]
184
+ }
185
+ }
186
+}
src/go/plugin/go.d/modules/ceph/init.go
new
+17
@@ -0,0 +1,17 @@
1
+// SPDX-License-Identifier: GPL-3.0-or-later
2
+
3
+package ceph
4
+
5
+import (
6
+ "fmt"
7
+)
8
+
9
+func (c *Ceph) validateConfig() error {
10
+ if c.URL == "" {
11
+ return fmt.Errorf("URL is required but not set")
12
+ }
13
+ if c.Username == "" || c.Password == "" {
14
+ return fmt.Errorf("username and password are required but not set")
15
+ }
16
+ return nil
17
+}
src/go/plugin/go.d/modules/ceph/metadata.yaml
new
+391
@@ -0,0 +1,391 @@
1
+plugin_name: go.d.plugin
2
+modules:
3
+ - meta:
4
+ plugin_name: go.d.plugin
5
+ module_name: ceph
6
+ monitored_instance:
7
+ name: Ceph
8
+ link: "https://ceph.io/"
9
+ categories:
10
+ - data-collection.storage-mount-points-and-filesystems
11
+ icon_filename: "ceph.svg"
12
+ related_resources:
13
+ integrations:
14
+ list: []
15
+ info_provided_to_referring_integrations:
16
+ description: ""
17
+ keywords:
18
+ - ceph
19
+ - storage
20
+ most_popular: false
21
+ overview:
22
+ data_collection:
23
+ metrics_description: |
24
+ This collector monitors the overall health status and performance of your Ceph clusters.
25
+ It gathers key metrics for the entire cluster, individual Pools, and OSDs
26
+ method_description: |
27
+ It collects metrics by periodically issuing HTTP GET requests to the Ceph Manager [RESP API](https://docs.ceph.com/en/reef/mgr/ceph_api/#):
28
+
29
+ - [/api/monitor](https://docs.ceph.com/en/reef/mgr/ceph_api/#get--api-monitor) (only once to get the Ceph cluster id (fsid))
30
+ - [/api/health/minimal](https://docs.ceph.com/en/reef/mgr/ceph_api/#get--api-health-minimal)
31
+ - [/api/osd](https://docs.ceph.com/en/reef/mgr/ceph_api/#get--api-osd)
32
+ - [/api/pool?stats=true](https://docs.ceph.com/en/reef/mgr/ceph_api/#get--api-pool)
33
+ supported_platforms:
34
+ include: [Linux]
35
+ exclude: []
36
+ multi_instance: true
37
+ additional_permissions:
38
+ description: ""
39
+ default_behavior:
40
+ auto_detection:
41
+ description: |
42
+ The collector can automatically detect Ceph Manager instances running on:
43
+
44
+ - localhost that are listening on port 8443
45
+ - within Docker containers
46
+
47
+ > **Note that the Ceph RESP API requires a username and password**.
48
+ > While Netdata can automatically detect Ceph Manager instances and create data collection jobs, these jobs will fail unless you provide the necessary credentials.
49
+ limits:
50
+ description: ""
51
+ performance_impact:
52
+ description: ""
53
+ setup:
54
+ prerequisites:
55
+ list: []
56
+ configuration:
57
+ file:
58
+ name: go.d/ceph.conf
59
+ options:
60
+ description: |
61
+ The following options can be defined globally: update_every.
62
+ folding:
63
+ title: Config options
64
+ enabled: true
65
+ list:
66
+ - name: update_every
67
+ description: Data collection frequency.
68
+ default_value: 1
69
+ required: false
70
+ - name: autodetection_retry
71
+ description: Recheck interval in seconds. Zero means no recheck will be scheduled.
72
+ default_value: 0
73
+ required: false
74
+ - name: url
75
+ description: The URL of the [Ceph Manager API](https://docs.ceph.com/en/reef/mgr/ceph_api/).
76
+ default_value: https://127.0.0.1:8443
77
+ required: true
78
+ - name: timeout
79
+ description: HTTP request timeout.
80
+ default_value: 2
81
+ required: false
82
+ - name: username
83
+ description: Username for basic HTTP authentication.
84
+ default_value: ""
85
+ required: true
86
+ - name: password
87
+ description: Password for basic HTTP authentication.
88
+ default_value: ""
89
+ required: true
90
+ - name: proxy_url
91
+ description: Proxy URL.
92
+ default_value: ""
93
+ required: false
94
+ - name: proxy_username
95
+ description: Username for proxy basic HTTP authentication.
96
+ default_value: ""
97
+ required: false
98
+ - name: proxy_password
99
+ description: Password for proxy basic HTTP authentication.
100
+ default_value: ""
101
+ required: false
102
+ - name: method
103
+ description: HTTP request method.
104
+ default_value: "GET"
105
+ required: false
106
+ - name: body
107
+ description: HTTP request body.
108
+ default_value: ""
109
+ required: false
110
+ - name: headers
111
+ description: HTTP request headers.
112
+ default_value: ""
113
+ required: false
114
+ - name: not_follow_redirects
115
+ description: Redirect handling policy. Controls whether the client follows redirects.
116
+ default_value: no
117
+ required: false
118
+ - name: tls_skip_verify
119
+ description: Server certificate chain and hostname validation policy. Controls whether the client performs this check.
120
+ default_value: yes
121
+ required: false
122
+ - name: tls_ca
123
+ description: Certification authority that the client uses when verifying the server's certificates.
124
+ default_value: ""
125
+ required: false
126
+ - name: tls_cert
127
+ description: Client TLS certificate.
128
+ default_value: ""
129
+ required: false
130
+ - name: tls_key
131
+ description: Client TLS key.
132
+ default_value: ""
133
+ required: false
134
+ examples:
135
+ folding:
136
+ title: ""
137
+ enabled: false
138
+ list:
139
+ - name: Basic
140
+ description: A basic example configuration.
141
+ folding:
142
+ enabled: false
143
+ config: |
144
+ jobs:
145
+ - name: local
146
+ url: https://127.0.0.1:8443
147
+ username: user
148
+ password: pass
149
+ - name: Multi-instance
150
+ description: |
151
+ > **Note**: When you define multiple jobs, their names must be unique.
152
+
153
+ Collecting metrics from local and remote instances.
154
+ config: |
155
+ jobs:
156
+ - name: local
157
+ url: https://127.0.0.1:8443
158
+ username: user
159
+ password: pass
160
+
161
+ - name: remote
162
+ url: https://192.0.2.1:8443
163
+ username: user
164
+ password: pass
165
+ troubleshooting:
166
+ problems:
167
+ list: []
168
+ alerts:
169
+ - name: ceph_cluster_space_usage
170
+ link: https://github.com/netdata/netdata/blob/master/src/health/health.d/ceph.conf
171
+ metric: ceph.general_usage
172
+ info: cluster disk space utilization
173
+ metrics:
174
+ folding:
175
+ title: Metrics
176
+ enabled: false
177
+ description: ""
178
+ availability: []
179
+ scopes:
180
+ - name: cluster
181
+ description: "These metrics refer to the entire Ceph cluster."
182
+ labels:
183
+ - name: fsid
184
+ description: A unique identifier of the cluster.
185
+ metrics:
186
+ - name: ceph.cluster_status
187
+ description: Ceph Cluster Status
188
+ unit: status
189
+ chart_type: line
190
+ dimensions:
191
+ - name: ok
192
+ - name: err
193
+ - name: warn
194
+ - name: ceph.cluster_hosts_count
195
+ description: Ceph Cluster Hosts
196
+ unit: hosts
197
+ chart_type: line
198
+ dimensions:
199
+ - name: hosts
200
+ - name: ceph.cluster_monitors_count
201
+ description: Ceph Cluster Monitors
202
+ unit: monitors
203
+ chart_type: line
204
+ dimensions:
205
+ - name: monitors
206
+ - name: ceph.cluster_osds_count
207
+ description: Ceph Cluster OSDs
208
+ unit: osds
209
+ chart_type: line
210
+ dimensions:
211
+ - name: osds
212
+ - name: ceph.cluster_osds_by_status_count
213
+ description: Ceph Cluster OSDs by Status
214
+ unit: status
215
+ chart_type: line
216
+ dimensions:
217
+ - name: up
218
+ - name: down
219
+ - name: in
220
+ - name: out
221
+ - name: ceph.cluster_managers_count
222
+ description: Ceph Cluster Managers
223
+ unit: managers
224
+ chart_type: line
225
+ dimensions:
226
+ - name: active
227
+ - name: standby
228
+ - name: ceph.cluster_object_gateways_count
229
+ description: Ceph Cluster Object Gateways (RGW)
230
+ unit: gateways
231
+ chart_type: line
232
+ dimensions:
233
+ - name: object
234
+ - name: ceph.cluster_iscsi_gateways_count
235
+ description: Ceph Cluster iSCSI Gateways
236
+ unit: gateways
237
+ chart_type: line
238
+ dimensions:
239
+ - name: iscsi
240
+ - name: ceph.cluster_iscsi_gateways_by_status_count
241
+ description: Ceph Cluster iSCSI Gateways by Status
242
+ unit: gateways
243
+ chart_type: line
244
+ dimensions:
245
+ - name: up
246
+ - name: down
247
+ - name: ceph.cluster_physical_capacity_utilization
248
+ description: Ceph Cluster Physical Capacity Utilization
249
+ unit: percent
250
+ chart_type: area
251
+ dimensions:
252
+ - name: utilization
253
+ - name: ceph.cluster_physical_capacity_usage
254
+ description: Ceph Cluster Physical Capacity Usage
255
+ unit: bytes
256
+ chart_type: stacked
257
+ dimensions:
258
+ - name: avail
259
+ - name: used
260
+ - name: ceph.cluster_objects_count
261
+ description: Ceph Cluster Objects
262
+ unit: objects
263
+ chart_type: line
264
+ dimensions:
265
+ - name: objects
266
+ - name: ceph.cluster_objects_by_status_distribution
267
+ description: Ceph Cluster Objects by Status
268
+ unit: percent
269
+ chart_type: stacked
270
+ dimensions:
271
+ - name: healthy
272
+ - name: misplaced
273
+ - name: degraded
274
+ - name: unfound
275
+ - name: ceph.cluster_pools_count
276
+ description: Ceph Cluster Pools
277
+ unit: pools
278
+ chart_type: line
279
+ dimensions:
280
+ - name: pools
281
+ - name: ceph.cluster_pgs_count
282
+ description: Ceph Cluster Placement Groups
283
+ unit: pgs
284
+ chart_type: line
285
+ dimensions:
286
+ - name: pgs
287
+ - name: ceph.cluster_pgs_by_status_count
288
+ description: Ceph Cluster Placement Groups by Status
289
+ unit: pgs
290
+ chart_type: stacked
291
+ dimensions:
292
+ - name: clean
293
+ - name: working
294
+ - name: warning
295
+ - name: unknown
296
+ - name: ceph.cluster_pgs_per_osd_count
297
+ description: Ceph Cluster Placement Groups per OSD
298
+ unit: pgs
299
+ chart_type: line
300
+ dimensions:
301
+ - name: per_osd
302
+ - name: osd
303
+ description: These metrics refer to the Object Storage Daemon (OSD).
304
+ labels:
305
+ - name: fsid
306
+ description: A unique identifier of the cluster.
307
+ - name: osd_uuid
308
+ description: OSD UUID.
309
+ - name: osd_name
310
+ description: OSD name.
311
+ - name: device_class
312
+ description: OSD device class.
313
+ metrics:
314
+ - name: ceph.osd_status
315
+ description: Ceph OSD Status
316
+ unit: status
317
+ chart_type: line
318
+ dimensions:
319
+ - name: up
320
+ - name: down
321
+ - name: in
322
+ - name: out
323
+ - name: ceph.osd_space_usage
324
+ description: Ceph OSD Space Usage
325
+ unit: bytes
326
+ chart_type: stacked
327
+ dimensions:
328
+ - name: avail
329
+ - name: used
330
+ - name: ceph.osd_io
331
+ description: Ceph OSD IO
332
+ unit: bytes/s
333
+ chart_type: area
334
+ dimensions:
335
+ - name: read
336
+ - name: written
337
+ - name: ceph.osd_iops
338
+ description: Ceph OSD IOPS
339
+ unit: ops/s
340
+ chart_type: area
341
+ dimensions:
342
+ - name: read
343
+ - name: write
344
+ - name: ceph.osd_latency
345
+ description: Ceph OSD Latency
346
+ unit: milliseconds
347
+ chart_type: line
348
+ dimensions:
349
+ - name: commit
350
+ - name: apply
351
+ - name: pool
352
+ description: These metrics refer to the Pool.
353
+ labels:
354
+ - name: fsid
355
+ description: A unique identifier of the cluster.
356
+ - name: pool_name
357
+ description: Pool name.
358
+ metrics:
359
+ - name: ceph.pool_space_utilization
360
+ description: Ceph Pool Space Utilization
361
+ unit: percent
362
+ chart_type: area
363
+ dimensions:
364
+ - name: utilization
365
+ - name: ceph.pool_space_usage
366
+ description: Ceph Pool Space Usage
367
+ unit: bytes
368
+ chart_type: stacked
369
+ dimensions:
370
+ - name: avail
371
+ - name: used
372
+ - name: ceph.pool_objects_count
373
+ description: Ceph Pool Objects
374
+ unit: objects
375
+ chart_type: line
376
+ dimensions:
377
+ - name: object
378
+ - name: ceph.pool_io
379
+ description: Ceph Pool IO
380
+ unit: bytes/s
381
+ chart_type: area
382
+ dimensions:
383
+ - name: read
384
+ - name: written
385
+ - name: ceph.pool_iops
386
+ description: Ceph Pool IOPS
387
+ unit: ops/s
388
+ chart_type: area
389
+ dimensions:
390
+ - name: read
391
+ - name: write
src/go/plugin/go.d/modules/ceph/testdata/config.json
new
+20
@@ -0,0 +1,20 @@
1
+{
2
+ "update_every": 123,
3
+ "url": "ok",
4
+ "body": "ok",
5
+ "method": "ok",
6
+ "headers": {
7
+ "ok": "ok"
8
+ },
9
+ "username": "ok",
10
+ "password": "ok",
11
+ "proxy_url": "ok",
12
+ "proxy_username": "ok",
13
+ "proxy_password": "ok",
14
+ "timeout": 123.123,
15
+ "not_follow_redirects": true,
16
+ "tls_ca": "ok",
17
+ "tls_cert": "ok",
18
+ "tls_key": "ok",
19
+ "tls_skip_verify": true
20
+}
src/go/plugin/go.d/modules/ceph/testdata/config.yaml
new
+17
@@ -0,0 +1,17 @@
1
+update_every: 123
2
+url: "ok"
3
+body: "ok"
4
+method: "ok"
5
+headers:
6
+ ok: "ok"
7
+username: "ok"
8
+password: "ok"
9
+proxy_url: "ok"
10
+proxy_username: "ok"
11
+proxy_password: "ok"
12
+timeout: 123.123
13
+not_follow_redirects: yes
14
+tls_ca: "ok"
15
+tls_cert: "ok"
16
+tls_key: "ok"
17
+tls_skip_verify: yes
src/go/plugin/go.d/modules/ceph/testdata/v16.2.15/api_health_minimal.json
new
+105
@@ -0,0 +1,105 @@
1
+{
2
+ "health": {
3
+ "status": "HEALTH_WARN",
4
+ "checks": [
5
+ {
6
+ "severity": "HEALTH_WARN",
7
+ "summary": {
8
+ "message": "Reduced data availability: 1 pg inactive, 1 pg incomplete",
9
+ "count": 2
10
+ },
11
+ "detail": [
12
+ {
13
+ "message": "pg 1.0 is creating+incomplete, acting [1,2147483647,2147483647,2147483647] (reducing pool mySuperPool min_size from 3 may help; search ceph.com/docs for 'incomplete')"
14
+ }
15
+ ],
16
+ "muted": false,
17
+ "type": "PG_AVAILABILITY"
18
+ }
19
+ ],
20
+ "mutes": []
21
+ },
22
+ "mon_status": {
23
+ "monmap": {
24
+ "mons": [
25
+ {}
26
+ ]
27
+ },
28
+ "quorum": [
29
+ 0
30
+ ]
31
+ },
32
+ "fs_map": {
33
+ "filesystems": [],
34
+ "standbys": []
35
+ },
36
+ "osd_map": {
37
+ "osds": [
38
+ {
39
+ "in": 1,
40
+ "up": 1,
41
+ "state": [
42
+ "exists",
43
+ "up"
44
+ ]
45
+ },
46
+ {
47
+ "in": 1,
48
+ "up": 1,
49
+ "state": [
50
+ "exists",
51
+ "up"
52
+ ]
53
+ }
54
+ ]
55
+ },
56
+ "scrub_status": "Inactive",
57
+ "pg_info": {
58
+ "object_stats": {
59
+ "num_objects": 6,
60
+ "num_object_copies": 6,
61
+ "num_objects_degraded": 1,
62
+ "num_objects_misplaced": 1,
63
+ "num_objects_unfound": 1
64
+ },
65
+ "statuses": {
66
+ "active+clean": 1,
67
+ "creating+incomplete": 1
68
+ },
69
+ "pgs_per_osd": 2
70
+ },
71
+ "mgr_map": {
72
+ "active_name": "pve-deb-work.snrdap",
73
+ "standbys": [
74
+ {
75
+ "gid": 24118,
76
+ "name": "pve-deb-work.rjothn",
77
+ "mgr_features": 4540138314316775400
78
+ }
79
+ ]
80
+ },
81
+ "pools": [
82
+ {},
83
+ {}
84
+ ],
85
+ "df": {
86
+ "stats": {
87
+ "total_avail_bytes": 175476178944,
88
+ "total_bytes": 176085270528,
89
+ "total_used_raw_bytes": 609091584
90
+ }
91
+ },
92
+ "client_perf": {
93
+ "read_bytes_sec": 1,
94
+ "read_op_per_sec": 1,
95
+ "recovering_bytes_per_sec": 1,
96
+ "write_bytes_sec": 1,
97
+ "write_op_per_sec": 1
98
+ },
99
+ "hosts": 1,
100
+ "rgw": 1,
101
+ "iscsi_daemons": {
102
+ "up": 1,
103
+ "down": 1
104
+ }
105
+}
src/go/plugin/go.d/modules/ceph/testdata/v16.2.15/api_monitor.json
new
+315
@@ -0,0 +1,315 @@
1
+{
2
+ "mon_status": {
3
+ "name": "pve-deb-work",
4
+ "rank": 0,
5
+ "state": "leader",
6
+ "election_epoch": 7,
7
+ "quorum": [
8
+ 0
9
+ ],
10
+ "quorum_age": 315075,
11
+ "features": {
12
+ "required_con": "2449958747317026820",
13
+ "required_mon": [
14
+ "kraken",
15
+ "luminous",
16
+ "mimic",
17
+ "osdmap-prune",
18
+ "nautilus",
19
+ "octopus",
20
+ "pacific",
21
+ "elector-pinging"
22
+ ],
23
+ "quorum_con": "4540138314316775423",
24
+ "quorum_mon": [
25
+ "kraken",
26
+ "luminous",
27
+ "mimic",
28
+ "osdmap-prune",
29
+ "nautilus",
30
+ "octopus",
31
+ "pacific",
32
+ "elector-pinging"
33
+ ]
34
+ },
35
+ "outside_quorum": [],
36
+ "extra_probe_peers": [],
37
+ "sync_provider": [],
38
+ "monmap": {
39
+ "epoch": 1,
40
+ "fsid": "28c31cb4-79ce-11ef-9a4d-e6007f1f06b0",
41
+ "modified": "2024-09-23T17:06:26.264498Z",
42
+ "created": "2024-09-23T17:06:26.264498Z",
43
+ "min_mon_release": 16,
44
+ "min_mon_release_name": "pacific",
45
+ "election_strategy": 1,
46
+ "disallowed_leaders: ": "",
47
+ "stretch_mode": false,
48
+ "tiebreaker_mon": "",
49
+ "removed_ranks: ": "",
50
+ "features": {
51
+ "persistent": [
52
+ "kraken",
53
+ "luminous",
54
+ "mimic",
55
+ "osdmap-prune",
56
+ "nautilus",
57
+ "octopus",
58
+ "pacific",
59
+ "elector-pinging"
60
+ ],
61
+ "optional": []
62
+ },
63
+ "mons": [
64
+ {
65
+ "rank": 0,
66
+ "name": "pve-deb-work",
67
+ "public_addrs": {
68
+ "addrvec": [
69
+ {
70
+ "type": "v2",
71
+ "addr": "127.0.0.1:3300",
72
+ "nonce": 0
73
+ },
74
+ {
75
+ "type": "v1",
76
+ "addr": "127.0.0.1:6789",
77
+ "nonce": 0
78
+ }
79
+ ]
80
+ },
81
+ "addr": "127.0.0.1:6789/0",
82
+ "public_addr": "127.0.0.1:6789/0",
83
+ "priority": 0,
84
+ "weight": 0,
85
+ "crush_location": "{}",
86
+ "stats": {
87
+ "num_sessions": [
88
+ [
89
+ 1727428059.43674,
90
+ 9
91
+ ],
92
+ [
93
+ 1727428064.436794,
94
+ 9
95
+ ],
96
+ [
97
+ 1727428069.4371185,
98
+ 9
99
+ ],
100
+ [
101
+ 1727428074.437272,
102
+ 9
103
+ ],
104
+ [
105
+ 1727428079.437457,
106
+ 9
107
+ ],
108
+ [
109
+ 1727428084.4377377,
110
+ 9
111
+ ],
112
+ [
113
+ 1727428089.4380398,
114
+ 9
115
+ ],
116
+ [
117
+ 1727428094.4382815,
118
+ 9
119
+ ],
120
+ [
121
+ 1727428099.4385583,
122
+ 9
123
+ ],
124
+ [
125
+ 1727428104.4388537,
126
+ 9
127
+ ],
128
+ [
129
+ 1727428109.439028,
130
+ 9
131
+ ],
132
+ [
133
+ 1727428114.439225,
134
+ 9
135
+ ],
136
+ [
137
+ 1727428119.4395273,
138
+ 9
139
+ ],
140
+ [
141
+ 1727428124.4398105,
142
+ 9
143
+ ],
144
+ [
145
+ 1727428129.4401586,
146
+ 9
147
+ ],
148
+ [
149
+ 1727428134.4403143,
150
+ 9
151
+ ],
152
+ [
153
+ 1727428139.4406898,
154
+ 9
155
+ ],
156
+ [
157
+ 1727428144.4407866,
158
+ 9
159
+ ],
160
+ [
161
+ 1727428149.4410205,
162
+ 9
163
+ ],
164
+ [
165
+ 1727428154.4414103,
166
+ 9
167
+ ]
168
+ ]
169
+ }
170
+ }
171
+ ]
172
+ },
173
+ "feature_map": {
174
+ "mon": [
175
+ {
176
+ "features": "0x3f01cfbdfffdffff",
177
+ "release": "luminous",
178
+ "num": 1
179
+ }
180
+ ],
181
+ "osd": [
182
+ {
183
+ "features": "0x3f01cfbdfffdffff",
184
+ "release": "luminous",
185
+ "num": 2
186
+ }
187
+ ],
188
+ "client": [
189
+ {
190
+ "features": "0x3f01cfbdfffdffff",
191
+ "release": "luminous",
192
+ "num": 4
193
+ }
194
+ ],
195
+ "mgr": [
196
+ {
197
+ "features": "0x3f01cfbdfffdffff",
198
+ "release": "luminous",
199
+ "num": 2
200
+ }
201
+ ]
202
+ },
203
+ "stretch_mode": false
204
+ },
205
+ "in_quorum": [
206
+ {
207
+ "rank": 0,
208
+ "name": "pve-deb-work",
209
+ "public_addrs": {
210
+ "addrvec": [
211
+ {
212
+ "type": "v2",
213
+ "addr": "127.0.0.1:3300",
214
+ "nonce": 0
215
+ },
216
+ {
217
+ "type": "v1",
218
+ "addr": "127.0.0.1:6789",
219
+ "nonce": 0
220
+ }
221
+ ]
222
+ },
223
+ "addr": "127.0.0.1:6789/0",
224
+ "public_addr": "127.0.0.1:6789/0",
225
+ "priority": 0,
226
+ "weight": 0,
227
+ "crush_location": "{}",
228
+ "stats": {
229
+ "num_sessions": [
230
+ [
231
+ 1727428059.43674,
232
+ 9
233
+ ],
234
+ [
235
+ 1727428064.436794,
236
+ 9
237
+ ],
238
+ [
239
+ 1727428069.4371185,
240
+ 9
241
+ ],
242
+ [
243
+ 1727428074.437272,
244
+ 9
245
+ ],
246
+ [
247
+ 1727428079.437457,
248
+ 9
249
+ ],
250
+ [
251
+ 1727428084.4377377,
252
+ 9
253
+ ],
254
+ [
255
+ 1727428089.4380398,
256
+ 9
257
+ ],
258
+ [
259
+ 1727428094.4382815,
260
+ 9
261
+ ],
262
+ [
263
+ 1727428099.4385583,
264
+ 9
265
+ ],
266
+ [
267
+ 1727428104.4388537,
268
+ 9
269
+ ],
270
+ [
271
+ 1727428109.439028,
272
+ 9
273
+ ],
274
+ [
275
+ 1727428114.439225,
276
+ 9
277
+ ],
278
+ [
279
+ 1727428119.4395273,
280
+ 9
281
+ ],
282
+ [
283
+ 1727428124.4398105,
284
+ 9
285
+ ],
286
+ [
287
+ 1727428129.4401586,
288
+ 9
289
+ ],
290
+ [
291
+ 1727428134.4403143,
292
+ 9
293
+ ],
294
+ [
295
+ 1727428139.4406898,
296
+ 9
297
+ ],
298
+ [
299
+ 1727428144.4407866,
300
+ 9
301
+ ],
302
+ [
303
+ 1727428149.4410205,
304
+ 9
305
+ ],
306
+ [
307
+ 1727428154.4414103,
308
+ 9
309
+ ]
310
+ ]
311
+ }
312
+ }
313
+ ],
314
+ "out_quorum": []
315
+}
src/go/plugin/go.d/modules/ceph/testdata/v16.2.15/api_osd.json
new
+930
@@ -0,0 +1,930 @@
1
+[
2
+ {
3
+ "osd": 0,
4
+ "up": 1,
5
+ "in": 1,
6
+ "weight": 1.0,
7
+ "primary_affinity": 1.0,
8
+ "last_clean_begin": 0,
9
+ "last_clean_end": 0,
10
+ "up_from": 16,
11
+ "up_thru": 23,
12
+ "down_at": 0,
13
+ "lost_at": 0,
14
+ "public_addrs": {
15
+ "addrvec": [
16
+ {
17
+ "type": "v2",
18
+ "nonce": 390161213,
19
+ "addr": "127.0.0.1:6802"
20
+ },
21
+ {
22
+ "type": "v1",
23
+ "nonce": 390161213,
24
+ "addr": "127.0.0.1:6803"
25
+ }
26
+ ]
27
+ },
28
+ "cluster_addrs": {
29
+ "addrvec": [
30
+ {
31
+ "type": "v2",
32
+ "nonce": 390161213,
33
+ "addr": "127.0.0.1:6804"
34
+ },
35
+ {
36
+ "type": "v1",
37
+ "nonce": 390161213,
38
+ "addr": "127.0.0.1:6805"
39
+ }
40
+ ]
41
+ },
42
+ "heartbeat_back_addrs": {
43
+ "addrvec": [
44
+ {
45
+ "type": "v2",
46
+ "nonce": 390161213,
47
+ "addr": "127.0.0.1:6808"
48
+ },
49
+ {
50
+ "type": "v1",
51
+ "nonce": 390161213,
52
+ "addr": "127.0.0.1:6809"
53
+ }
54
+ ]
55
+ },
56
+ "heartbeat_front_addrs": {
57
+ "addrvec": [
58
+ {
59
+ "type": "v2",
60
+ "nonce": 390161213,
61
+ "addr": "127.0.0.1:6806"
62
+ },
63
+ {
64
+ "type": "v1",
65
+ "nonce": 390161213,
66
+ "addr": "127.0.0.1:6807"
67
+ }
68
+ ]
69
+ },
70
+ "state": [
71
+ "exists",
72
+ "up"
73
+ ],
74
+ "uuid": "f78537db-9b18-4c62-a24f-a4344fc28de7",
75
+ "public_addr": "127.0.0.1:6803/390161213",
76
+ "cluster_addr": "127.0.0.1:6805/390161213",
77
+ "heartbeat_back_addr": "127.0.0.1:6809/390161213",
78
+ "heartbeat_front_addr": "127.0.0.1:6807/390161213",
79
+ "id": 0,
80
+ "osd_stats": {
81
+ "osd": 0,
82
+ "up_from": 16,
83
+ "seq": 68719494425,
84
+ "num_pgs": 2,
85
+ "num_osds": 1,
86
+ "num_per_pool_osds": 1,
87
+ "num_per_pool_omap_osds": 1,
88
+ "kb": 104853504,
89
+ "kb_used": 297392,
90
+ "kb_used_data": 296,
91
+ "kb_used_omap": 0,
92
+ "kb_used_meta": 297088,
93
+ "kb_avail": 104556112,
94
+ "statfs": {
95
+ "total": 107369988096,
96
+ "available": 107065458688,
97
+ "internally_reserved": 0,
98
+ "allocated": 303104,
99
+ "data_stored": 115778,
100
+ "data_compressed": 0,
101
+ "data_compressed_allocated": 0,
102
+ "data_compressed_original": 0,
103
+ "omap_allocated": 0,
104
+ "internal_metadata": 304218112
105
+ },
106
+ "hb_peers": [
107
+ 1
108
+ ],
109
+ "snap_trim_queue_len": 0,
110
+ "num_snap_trimming": 0,
111
+ "num_shards_repaired": 0,
112
+ "op_queue_age_hist": {
113
+ "histogram": [],
114
+ "upper_bound": 1
115
+ },
116
+ "perf_stat": {
117
+ "commit_latency_ms": 1.0,
118
+ "apply_latency_ms": 1.0,
119
+ "commit_latency_ns": 0,
120
+ "apply_latency_ns": 0
121
+ },
122
+ "alerts": []
123
+ },
124
+ "tree": {
125
+ "id": 0,
126
+ "device_class": "hdd",
127
+ "type": "osd",
128
+ "type_id": 0,
129
+ "crush_weight": 0.097686767578125,
130
+ "depth": 2,
131
+ "pool_weights": {},
132
+ "exists": 1,
133
+ "status": "up",
134
+ "reweight": 1.0,
135
+ "primary_affinity": 1.0,
136
+ "name": "osd.0"
137
+ },
138
+ "host": {
139
+ "id": -3,
140
+ "name": "pve-deb-work",
141
+ "type": "host",
142
+ "type_id": 1,
143
+ "pool_weights": {},
144
+ "children": [
145
+ 1,
146
+ 0
147
+ ]
148
+ },
149
+ "stats": {
150
+ "op_w": 1.0,
151
+ "op_in_bytes": 1.0,
152
+ "op_r": 1.0,
153
+ "op_out_bytes": 1.0,
154
+ "numpg": 2,
155
+ "stat_bytes": 107369988096,
156
+ "stat_bytes_used": 304529408
157
+ },
158
+ "stats_history": {
159
+ "op_w": [
160
+ [
161
+ 1727260221.6928742,
162
+ 0.0
163
+ ],
164
+ [
165
+ 1727260226.693285,
166
+ 0.0
167
+ ],
168
+ [
169
+ 1727260231.693595,
170
+ 0.0
171
+ ],
172
+ [
173
+ 1727260236.6938233,
174
+ 0.0
175
+ ],
176
+ [
177
+ 1727260241.6942236,
178
+ 0.0
179
+ ],
180
+ [
181
+ 1727260246.6945205,
182
+ 0.0
183
+ ],
184
+ [
185
+ 1727260251.694739,
186
+ 0.0
187
+ ],
188
+ [
189
+ 1727260256.6951063,
190
+ 0.0
191
+ ],
192
+ [
193
+ 1727260261.6954763,
194
+ 0.0
195
+ ],
196
+ [
197
+ 1727260266.695751,
198
+ 0.0
199
+ ],
200
+ [
201
+ 1727260271.6960592,
202
+ 0.0
203
+ ],
204
+ [
205
+ 1727260276.6963248,
206
+ 0.0
207
+ ],
208
+ [
209
+ 1727260281.6966574,
210
+ 0.0
211
+ ],
212
+ [
213
+ 1727260286.696938,
214
+ 0.0
215
+ ],
216
+ [
217
+ 1727260291.6973395,
218
+ 0.0
219
+ ],
220
+ [
221
+ 1727260296.697657,
222
+ 0.0
223
+ ],
224
+ [
225
+ 1727260301.6980677,
226
+ 0.0
227
+ ],
228
+ [
229
+ 1727260306.698276,
230
+ 0.0
231
+ ],
232
+ [
233
+ 1727260311.6986544,
234
+ 0.0
235
+ ]
236
+ ],
237
+ "op_in_bytes": [
238
+ [
239
+ 1727260221.6928742,
240
+ 0.0
241
+ ],
242
+ [
243
+ 1727260226.693285,
244
+ 0.0
245
+ ],
246
+ [
247
+ 1727260231.693595,
248
+ 0.0
249
+ ],
250
+ [
251
+ 1727260236.6938233,
252
+ 0.0
253
+ ],
254
+ [
255
+ 1727260241.6942236,
256
+ 0.0
257
+ ],
258
+ [
259
+ 1727260246.6945205,
260
+ 0.0
261
+ ],
262
+ [
263
+ 1727260251.694739,
264
+ 0.0
265
+ ],
266
+ [
267
+ 1727260256.6951063,
268
+ 0.0
269
+ ],
270
+ [
271
+ 1727260261.6954763,
272
+ 0.0
273
+ ],
274
+ [
275
+ 1727260266.695751,
276
+ 0.0
277
+ ],
278
+ [
279
+ 1727260271.6960592,
280
+ 0.0
281
+ ],
282
+ [
283
+ 1727260276.6963248,
284
+ 0.0
285
+ ],
286
+ [
287
+ 1727260281.6966574,
288
+ 0.0
289
+ ],
290
+ [
291
+ 1727260286.696938,
292
+ 0.0
293
+ ],
294
+ [
295
+ 1727260291.6973395,
296
+ 0.0
297
+ ],
298
+ [
299
+ 1727260296.697657,
300
+ 0.0
301
+ ],
302
+ [
303
+ 1727260301.6980677,
304
+ 0.0
305
+ ],
306
+ [
307
+ 1727260306.698276,
308
+ 0.0
309
+ ],
310
+ [
311
+ 1727260311.6986544,
312
+ 0.0
313
+ ]
314
+ ],
315
+ "op_r": [
316
+ [
317
+ 1727260221.6928742,
318
+ 0.0
319
+ ],
320
+ [
321
+ 1727260226.693285,
322
+ 0.0
323
+ ],
324
+ [
325
+ 1727260231.693595,
326
+ 0.0
327
+ ],
328
+ [
329
+ 1727260236.6938233,
330
+ 0.0
331
+ ],
332
+ [
333
+ 1727260241.6942236,
334
+ 0.0
335
+ ],
336
+ [
337
+ 1727260246.6945205,
338
+ 0.0
339
+ ],
340
+ [
341
+ 1727260251.694739,
342
+ 0.0
343
+ ],
344
+ [
345
+ 1727260256.6951063,
346
+ 0.0
347
+ ],
348
+ [
349
+ 1727260261.6954763,
350
+ 0.0
351
+ ],
352
+ [
353
+ 1727260266.695751,
354
+ 0.0
355
+ ],
356
+ [
357
+ 1727260271.6960592,
358
+ 0.0
359
+ ],
360
+ [
361
+ 1727260276.6963248,
362
+ 0.0
363
+ ],
364
+ [
365
+ 1727260281.6966574,
366
+ 0.0
367
+ ],
368
+ [
369
+ 1727260286.696938,
370
+ 0.0
371
+ ],
372
+ [
373
+ 1727260291.6973395,
374
+ 0.0
375
+ ],
376
+ [
377
+ 1727260296.697657,
378
+ 0.0
379
+ ],
380
+ [
381
+ 1727260301.6980677,
382
+ 0.0
383
+ ],
384
+ [
385
+ 1727260306.698276,
386
+ 0.0
387
+ ],
388
+ [
389
+ 1727260311.6986544,
390
+ 0.0
391
+ ]
392
+ ],
393
+ "op_out_bytes": [
394
+ [
395
+ 1727260221.6928742,
396
+ 0.0
397
+ ],
398
+ [
399
+ 1727260226.693285,
400
+ 0.0
401
+ ],
402
+ [
403
+ 1727260231.693595,
404
+ 0.0
405
+ ],
406
+ [
407
+ 1727260236.6938233,
408
+ 0.0
409
+ ],
410
+ [
411
+ 1727260241.6942236,
412
+ 0.0
413
+ ],
414
+ [
415
+ 1727260246.6945205,
416
+ 0.0
417
+ ],
418
+ [
419
+ 1727260251.694739,
420
+ 0.0
421
+ ],
422
+ [
423
+ 1727260256.6951063,
424
+ 0.0
425
+ ],
426
+ [
427
+ 1727260261.6954763,
428
+ 0.0
429
+ ],
430
+ [
431
+ 1727260266.695751,
432
+ 0.0
433
+ ],
434
+ [
435
+ 1727260271.6960592,
436
+ 0.0
437
+ ],
438
+ [
439
+ 1727260276.6963248,
440
+ 0.0
441
+ ],
442
+ [
443
+ 1727260281.6966574,
444
+ 0.0
445
+ ],
446
+ [
447
+ 1727260286.696938,
448
+ 0.0
449
+ ],
450
+ [
451
+ 1727260291.6973395,
452
+ 0.0
453
+ ],
454
+ [
455
+ 1727260296.697657,
456
+ 0.0
457
+ ],
458
+ [
459
+ 1727260301.6980677,
460
+ 0.0
461
+ ],
462
+ [
463
+ 1727260306.698276,
464
+ 0.0
465
+ ],
466
+ [
467
+ 1727260311.6986544,
468
+ 0.0
469
+ ]
470
+ ]
471
+ },
472
+ "operational_status": "working"
473
+ },
474
+ {
475
+ "osd": 1,
476
+ "up": 1,
477
+ "in": 1,
478
+ "weight": 1.0,
479
+ "primary_affinity": 1.0,
480
+ "last_clean_begin": 0,
481
+ "last_clean_end": 0,
482
+ "up_from": 22,
483
+ "up_thru": 22,
484
+ "down_at": 0,
485
+ "lost_at": 0,
486
+ "public_addrs": {
487
+ "addrvec": [
488
+ {
489
+ "type": "v2",
490
+ "nonce": 1173056633,
491
+ "addr": "127.0.0.1:6810"
492
+ },
493
+ {
494
+ "type": "v1",
495
+ "nonce": 1173056633,
496
+ "addr": "127.0.0.1:6811"
497
+ }
498
+ ]
499
+ },
500
+ "cluster_addrs": {
501
+ "addrvec": [
502
+ {
503
+ "type": "v2",
504
+ "nonce": 1173056633,
505
+ "addr": "127.0.0.1:6812"
506
+ },
507
+ {
508
+ "type": "v1",
509
+ "nonce": 1173056633,
510
+ "addr": "127.0.0.1:6813"
511
+ }
512
+ ]
513
+ },
514
+ "heartbeat_back_addrs": {
515
+ "addrvec": [
516
+ {
517
+ "type": "v2",
518
+ "nonce": 1173056633,
519
+ "addr": "127.0.0.1:6816"
520
+ },
521
+ {
522
+ "type": "v1",
523
+ "nonce": 1173056633,
524
+ "addr": "127.0.0.1:6817"
525
+ }
526
+ ]
527
+ },
528
+ "heartbeat_front_addrs": {
529
+ "addrvec": [
530
+ {
531
+ "type": "v2",
532
+ "nonce": 1173056633,
533
+ "addr": "127.0.0.1:6814"
534
+ },
535
+ {
536
+ "type": "v1",
537
+ "nonce": 1173056633,
538
+ "addr": "127.0.0.1:6815"
539
+ }
540
+ ]
541
+ },
542
+ "state": [
543
+ "exists",
544
+ "up"
545
+ ],
546
+ "uuid": "f5bbbe9d-e85b-419c-af5a-a57e2527cad3",
547
+ "public_addr": "127.0.0.1:6811/1173056633",
548
+ "cluster_addr": "127.0.0.1:6813/1173056633",
549
+ "heartbeat_back_addr": "127.0.0.1:6817/1173056633",
550
+ "heartbeat_front_addr": "127.0.0.1:6815/1173056633",
551
+ "id": 1,
552
+ "osd_stats": {
553
+ "osd": 1,
554
+ "up_from": 22,
555
+ "seq": 94489298171,
556
+ "num_pgs": 2,
557
+ "num_osds": 1,
558
+ "num_per_pool_osds": 1,
559
+ "num_per_pool_omap_osds": 1,
560
+ "kb": 67104768,
561
+ "kb_used": 297392,
562
+ "kb_used_data": 296,
563
+ "kb_used_omap": 0,
564
+ "kb_used_meta": 297088,
565
+ "kb_avail": 66807376,
566
+ "statfs": {
567
+ "total": 68715282432,
568
+ "available": 68410753024,
569
+ "internally_reserved": 0,
570
+ "allocated": 303104,
571
+ "data_stored": 115778,
572
+ "data_compressed": 0,
573
+ "data_compressed_allocated": 0,
574
+ "data_compressed_original": 0,
575
+ "omap_allocated": 0,
576
+ "internal_metadata": 304218112
577
+ },
578
+ "hb_peers": [
579
+ 0
580
+ ],
581
+ "snap_trim_queue_len": 0,
582
+ "num_snap_trimming": 0,
583
+ "num_shards_repaired": 0,
584
+ "op_queue_age_hist": {
585
+ "histogram": [],
586
+ "upper_bound": 1
587
+ },
588
+ "perf_stat": {
589
+ "commit_latency_ms": 1.0,
590
+ "apply_latency_ms": 1.0,
591
+ "commit_latency_ns": 0,
592
+ "apply_latency_ns": 0
593
+ },
594
+ "alerts": []
595
+ },
596
+ "tree": {
597
+ "id": 1,
598
+ "device_class": "ssd",
599
+ "type": "osd",
600
+ "type_id": 0,
601
+ "crush_weight": 0.0625,
602
+ "depth": 2,
603
+ "pool_weights": {},
604
+ "exists": 1,
605
+ "status": "up",
606
+ "reweight": 1.0,
607
+ "primary_affinity": 1.0,
608
+ "name": "osd.1"
609
+ },
610
+ "host": {
611
+ "id": -3,
612
+ "name": "pve-deb-work",
613
+ "type": "host",
614
+ "type_id": 1,
615
+ "pool_weights": {},
616
+ "children": [
617
+ 1,
618
+ 0
619
+ ]
620
+ },
621
+ "stats": {
622
+ "op_w": 1.0,
623
+ "op_in_bytes": 1.0,
624
+ "op_r": 1.0,
625
+ "op_out_bytes": 1.0,
626
+ "numpg": 2,
627
+ "stat_bytes": 68715282432,
628
+ "stat_bytes_used": 304529408
629
+ },
630
+ "stats_history": {
631
+ "op_w": [
632
+ [
633
+ 1727260228.751263,
634
+ 0.0
635
+ ],
636
+ [
637
+ 1727260233.7515125,
638
+ 0.0
639
+ ],
640
+ [
641
+ 1727260238.7518487,
642
+ 0.0
643
+ ],
644
+ [
645
+ 1727260243.752178,
646
+ 0.0
647
+ ],
648
+ [
649
+ 1727260248.752556,
650
+ 0.0
651
+ ],
652
+ [
653
+ 1727260253.7527573,
654
+ 0.0
655
+ ],
656
+ [
657
+ 1727260258.7530267,
658
+ 0.0
659
+ ],
660
+ [
661
+ 1727260263.753484,
662
+ 0.0
663
+ ],
664
+ [
665
+ 1727260268.753807,
666
+ 0.0
667
+ ],
668
+ [
669
+ 1727260273.754063,
670
+ 0.0
671
+ ],
672
+ [
673
+ 1727260278.7543082,
674
+ 0.0
675
+ ],
676
+ [
677
+ 1727260283.7546039,
678
+ 0.0
679
+ ],
680
+ [
681
+ 1727260288.754978,
682
+ 0.0
683
+ ],
684
+ [
685
+ 1727260293.7552564,
686
+ 0.0
687
+ ],
688
+ [
689
+ 1727260298.755653,
690
+ 0.0
691
+ ],
692
+ [
693
+ 1727260303.7559133,
694
+ 0.0
695
+ ],
696
+ [
697
+ 1727260308.7562194,
698
+ 0.0
699
+ ],
700
+ [
701
+ 1727260313.7565064,
702
+ 0.0
703
+ ]
704
+ ],
705
+ "op_in_bytes": [
706
+ [
707
+ 1727260228.751263,
708
+ 0.0
709
+ ],
710
+ [
711
+ 1727260233.7515125,
712
+ 0.0
713
+ ],
714
+ [
715
+ 1727260238.7518487,
716
+ 0.0
717
+ ],
718
+ [
719
+ 1727260243.752178,
720
+ 0.0
721
+ ],
722
+ [
723
+ 1727260248.752556,
724
+ 0.0
725
+ ],
726
+ [
727
+ 1727260253.7527573,
728
+ 0.0
729
+ ],
730
+ [
731
+ 1727260258.7530267,
732
+ 0.0
733
+ ],
734
+ [
735
+ 1727260263.753484,
736
+ 0.0
737
+ ],
738
+ [
739
+ 1727260268.753807,
740
+ 0.0
741
+ ],
742
+ [
743
+ 1727260273.754063,
744
+ 0.0
745
+ ],
746
+ [
747
+ 1727260278.7543082,
748
+ 0.0
749
+ ],
750
+ [
751
+ 1727260283.7546039,
752
+ 0.0
753
+ ],
754
+ [
755
+ 1727260288.754978,
756
+ 0.0
757
+ ],
758
+ [
759
+ 1727260293.7552564,
760
+ 0.0
761
+ ],
762
+ [
763
+ 1727260298.755653,
764
+ 0.0
765
+ ],
766
+ [
767
+ 1727260303.7559133,
768
+ 0.0
769
+ ],
770
+ [
771
+ 1727260308.7562194,
772
+ 0.0
773
+ ],
774
+ [
775
+ 1727260313.7565064,
776
+ 0.0
777
+ ]
778
+ ],
779
+ "op_r": [
780
+ [
781
+ 1727260228.751263,
782
+ 0.0
783
+ ],
784
+ [
785
+ 1727260233.7515125,
786
+ 0.0
787
+ ],
788
+ [
789
+ 1727260238.7518487,
790
+ 0.0
791
+ ],
792
+ [
793
+ 1727260243.752178,
794
+ 0.0
795
+ ],
796
+ [
797
+ 1727260248.752556,
798
+ 0.0
799
+ ],
800
+ [
801
+ 1727260253.7527573,
802
+ 0.0
803
+ ],
804
+ [
805
+ 1727260258.7530267,
806
+ 0.0
807
+ ],
808
+ [
809
+ 1727260263.753484,
810
+ 0.0
811
+ ],
812
+ [
813
+ 1727260268.753807,
814
+ 0.0
815
+ ],
816
+ [
817
+ 1727260273.754063,
818
+ 0.0
819
+ ],
820
+ [
821
+ 1727260278.7543082,
822
+ 0.0
823
+ ],
824
+ [
825
+ 1727260283.7546039,
826
+ 0.0
827
+ ],
828
+ [
829
+ 1727260288.754978,
830
+ 0.0
831
+ ],
832
+ [
833
+ 1727260293.7552564,
834
+ 0.0
835
+ ],
836
+ [
837
+ 1727260298.755653,
838
+ 0.0
839
+ ],
840
+ [
841
+ 1727260303.7559133,
842
+ 0.0
843
+ ],
844
+ [
845
+ 1727260308.7562194,
846
+ 0.0
847
+ ],
848
+ [
849
+ 1727260313.7565064,
850
+ 0.0
851
+ ]
852
+ ],
853
+ "op_out_bytes": [
854
+ [
855
+ 1727260228.751263,
856
+ 0.0
857
+ ],
858
+ [
859
+ 1727260233.7515125,
860
+ 0.0
861
+ ],
862
+ [
863
+ 1727260238.7518487,
864
+ 0.0
865
+ ],
866
+ [
867
+ 1727260243.752178,
868
+ 0.0
869
+ ],
870
+ [
871
+ 1727260248.752556,
872
+ 0.0
873
+ ],
874
+ [
875
+ 1727260253.7527573,
876
+ 0.0
877
+ ],
878
+ [
879
+ 1727260258.7530267,
880
+ 0.0
881
+ ],
882
+ [
883
+ 1727260263.753484,
884
+ 0.0
885
+ ],
886
+ [
887
+ 1727260268.753807,
888
+ 0.0
889
+ ],
890
+ [
891
+ 1727260273.754063,
892
+ 0.0
893
+ ],
894
+ [
895
+ 1727260278.7543082,
896
+ 0.0
897
+ ],
898
+ [
899
+ 1727260283.7546039,
900
+ 0.0
901
+ ],
902
+ [
903
+ 1727260288.754978,
904
+ 0.0
905
+ ],
906
+ [
907
+ 1727260293.7552564,
908
+ 0.0
909
+ ],
910
+ [
911
+ 1727260298.755653,
912
+ 0.0
913
+ ],
914
+ [
915
+ 1727260303.7559133,
916
+ 0.0
917
+ ],
918
+ [
919
+ 1727260308.7562194,
920
+ 0.0
921
+ ],
922
+ [
923
+ 1727260313.7565064,
924
+ 0.0
925
+ ]
926
+ ]
927
+ },
928
+ "operational_status": "working"
929
+ }
930
+]
src/go/plugin/go.d/modules/ceph/testdata/v16.2.15/api_pool_stats.json
new
+1923
@@ -0,0 +1,1923 @@
1
+[
2
+ {
3
+ "pool": 1,
4
+ "pool_name": "mySuperPool",
5
+ "flags": 32769,
6
+ "flags_names": "hashpspool,creating",
7
+ "type": "erasure",
8
+ "size": 4,
9
+ "min_size": 3,
10
+ "crush_rule": "erasure-code",
11
+ "peering_crush_bucket_count": 0,
12
+ "peering_crush_bucket_target": 0,
13
+ "peering_crush_bucket_barrier": 0,
14
+ "peering_crush_bucket_mandatory_member": 2147483647,
15
+ "object_hash": 2,
16
+ "pg_autoscale_mode": "on",
17
+ "pg_num": 1,
18
+ "pg_placement_num": 1,
19
+ "pg_placement_num_target": 32,
20
+ "pg_num_target": 32,
21
+ "pg_num_pending": 1,
22
+ "last_pg_merge_meta": {
23
+ "ready_epoch": 0,
24
+ "last_epoch_started": 0,
25
+ "last_epoch_clean": 0,
26
+ "source_pgid": "0.0",
27
+ "source_version": "0'0",
28
+ "target_version": "0'0"
29
+ },
30
+ "auid": 0,
31
+ "snap_mode": "selfmanaged",
32
+ "snap_seq": 0,
33
+ "snap_epoch": 0,
34
+ "pool_snaps": [],
35
+ "quota_max_bytes": 2147483648,
36
+ "quota_max_objects": 0,
37
+ "tiers": [],
38
+ "tier_of": -1,
39
+ "read_tier": -1,
40
+ "write_tier": -1,
41
+ "cache_mode": "none",
42
+ "target_max_bytes": 0,
43
+ "target_max_objects": 0,
44
+ "cache_target_dirty_ratio_micro": 400000,
45
+ "cache_target_dirty_high_ratio_micro": 600000,
46
+ "cache_target_full_ratio_micro": 800000,
47
+ "cache_min_flush_age": 0,
48
+ "cache_min_evict_age": 0,
49
+ "erasure_code_profile": "default",
50
+ "hit_set_params": {
51
+ "type": "none"
52
+ },
53
+ "hit_set_period": 0,
54
+ "hit_set_count": 0,
55
+ "use_gmt_hitset": true,
56
+ "min_read_recency_for_promote": 0,
57
+ "min_write_recency_for_promote": 0,
58
+ "hit_set_grade_decay_rate": 0,
59
+ "hit_set_search_last_n": 0,
60
+ "grade_table": [],
61
+ "stripe_width": 8192,
62
+ "expected_num_objects": 0,
63
+ "fast_read": false,
64
+ "options": {},
65
+ "application_metadata": [],
66
+ "create_time": "2024-09-23T17:27:53.650381+0000",
67
+ "last_change": "18",
68
+ "last_force_op_resend": "0",
69
+ "last_force_op_resend_prenautilus": "0",
70
+ "last_force_op_resend_preluminous": "0",
71
+ "removed_snaps": "[]",
72
+ "pg_status": {
73
+ "creating+incomplete": 1
74
+ },
75
+ "stats": {
76
+ "stored": {
77
+ "latest": 1,
78
+ "rate": 0.0,
79
+ "rates": [
80
+ [
81
+ 1727260045.5636568,
82
+ 0.0
83
+ ],
84
+ [
85
+ 1727260050.5730257,
86
+ 0.0
87
+ ],
88
+ [
89
+ 1727260055.56124,
90
+ 0.0
91
+ ],
92
+ [
93
+ 1727260060.564262,
94
+ 0.0
95
+ ],
96
+ [
97
+ 1727260065.5657525,
98
+ 0.0
99
+ ],
100
+ [
101
+ 1727260070.563676,
102
+ 0.0
103
+ ],
104
+ [
105
+ 1727260105.6695807,
106
+ 0.0
107
+ ],
108
+ [
109
+ 1727260165.6647935,
110
+ 0.0
111
+ ],
112
+ [
113
+ 1727260212.0559795,
114
+ 0.0
115
+ ]
116
+ ]
117
+ },
118
+ "stored_data": {
119
+ "latest": 0,
120
+ "rate": 0.0,
121
+ "rates": [
122
+ [
123
+ 1727260045.5636568,
124
+ 0.0
125
+ ],
126
+ [
127
+ 1727260050.5730257,
128
+ 0.0
129
+ ],
130
+ [
131
+ 1727260055.56124,
132
+ 0.0
133
+ ],
134
+ [
135
+ 1727260060.564262,
136
+ 0.0
137
+ ],
138
+ [
139
+ 1727260065.5657525,
140
+ 0.0
141
+ ],
142
+ [
143
+ 1727260070.563676,
144
+ 0.0
145
+ ],
146
+ [
147
+ 1727260105.6695807,
148
+ 0.0
149
+ ],
150
+ [
151
+ 1727260165.6647935,
152
+ 0.0
153
+ ],
154
+ [
155
+ 1727260212.0559795,
156
+ 0.0
157
+ ]
158
+ ]
159
+ },
160
+ "stored_omap": {
161
+ "latest": 0,
162
+ "rate": 0.0,
163
+ "rates": [
164
+ [
165
+ 1727260045.5636568,
166
+ 0.0
167
+ ],
168
+ [
169
+ 1727260050.5730257,
170
+ 0.0
171
+ ],
172
+ [
173
+ 1727260055.56124,
174
+ 0.0
175
+ ],
176
+ [
177
+ 1727260060.564262,
178
+ 0.0
179
+ ],
180
+ [
181
+ 1727260065.5657525,
182
+ 0.0
183
+ ],
184
+ [
185
+ 1727260070.563676,
186
+ 0.0
187
+ ],
188
+ [
189
+ 1727260105.6695807,
190
+ 0.0
191
+ ],
192
+ [
193
+ 1727260165.6647935,
194
+ 0.0
195
+ ],
196
+ [
197
+ 1727260212.0559795,
198
+ 0.0
199
+ ]
200
+ ]
201
+ },
202
+ "objects": {
203
+ "latest": 1,
204
+ "rate": 0.0,
205
+ "rates": [
206
+ [
207
+ 1727260045.5636568,
208
+ 0.0
209
+ ],
210
+ [
211
+ 1727260050.5730257,
212
+ 0.0
213
+ ],
214
+ [
215
+ 1727260055.56124,
216
+ 0.0
217
+ ],
218
+ [
219
+ 1727260060.564262,
220
+ 0.0
221
+ ],
222
+ [
223
+ 1727260065.5657525,
224
+ 0.0
225
+ ],
226
+ [
227
+ 1727260070.563676,
228
+ 0.0
229
+ ],
230
+ [
231
+ 1727260105.6695807,
232
+ 0.0
233
+ ],
234
+ [
235
+ 1727260165.6647935,
236
+ 0.0
237
+ ],
238
+ [
239
+ 1727260212.0559795,
240
+ 0.0
241
+ ]
242
+ ]
243
+ },
244
+ "kb_used": {
245
+ "latest": 0,
246
+ "rate": 0.0,
247
+ "rates": [
248
+ [
249
+ 1727260045.5636568,
250
+ 0.0
251
+ ],
252
+ [
253
+ 1727260050.5730257,
254
+ 0.0
255
+ ],
256
+ [
257
+ 1727260055.56124,
258
+ 0.0
259
+ ],
260
+ [
261
+ 1727260060.564262,
262
+ 0.0
263
+ ],
264
+ [
265
+ 1727260065.5657525,
266
+ 0.0
267
+ ],
268
+ [
269
+ 1727260070.563676,
270
+ 0.0
271
+ ],
272
+ [
273
+ 1727260105.6695807,
274
+ 0.0
275
+ ],
276
+ [
277
+ 1727260165.6647935,
278
+ 0.0
279
+ ],
280
+ [
281
+ 1727260212.0559795,
282
+ 0.0
283
+ ]
284
+ ]
285
+ },
286
+ "bytes_used": {
287
+ "latest": 1,
288
+ "rate": 0.0,
289
+ "rates": [
290
+ [
291
+ 1727260045.5636568,
292
+ 0.0
293
+ ],
294
+ [
295
+ 1727260050.5730257,
296
+ 0.0
297
+ ],
298
+ [
299
+ 1727260055.56124,
300
+ 0.0
301
+ ],
302
+ [
303
+ 1727260060.564262,
304
+ 0.0
305
+ ],
306
+ [
307
+ 1727260065.5657525,
308
+ 0.0
309
+ ],
310
+ [
311
+ 1727260070.563676,
312
+ 0.0
313
+ ],
314
+ [
315
+ 1727260105.6695807,
316
+ 0.0
317
+ ],
318
+ [
319
+ 1727260165.6647935,
320
+ 0.0
321
+ ],
322
+ [
323
+ 1727260212.0559795,
324
+ 0.0
325
+ ]
326
+ ]
327
+ },
328
+ "data_bytes_used": {
329
+ "latest": 0,
330
+ "rate": 0.0,
331
+ "rates": [
332
+ [
333
+ 1727260045.5636568,
334
+ 0.0
335
+ ],
336
+ [
337
+ 1727260050.5730257,
338
+ 0.0
339
+ ],
340
+ [
341
+ 1727260055.56124,
342
+ 0.0
343
+ ],
344
+ [
345
+ 1727260060.564262,
346
+ 0.0
347
+ ],
348
+ [
349
+ 1727260065.5657525,
350
+ 0.0
351
+ ],
352
+ [
353
+ 1727260070.563676,
354
+ 0.0
355
+ ],
356
+ [
357
+ 1727260105.6695807,
358
+ 0.0
359
+ ],
360
+ [
361
+ 1727260165.6647935,
362
+ 0.0
363
+ ],
364
+ [
365
+ 1727260212.0559795,
366
+ 0.0
367
+ ]
368
+ ]
369
+ },
370
+ "omap_bytes_used": {
371
+ "latest": 0,
372
+ "rate": 0.0,
373
+ "rates": [
374
+ [
375
+ 1727260045.5636568,
376
+ 0.0
377
+ ],
378
+ [
379
+ 1727260050.5730257,
380
+ 0.0
381
+ ],
382
+ [
383
+ 1727260055.56124,
384
+ 0.0
385
+ ],
386
+ [
387
+ 1727260060.564262,
388
+ 0.0
389
+ ],
390
+ [
391
+ 1727260065.5657525,
392
+ 0.0
393
+ ],
394
+ [
395
+ 1727260070.563676,
396
+ 0.0
397
+ ],
398
+ [
399
+ 1727260105.6695807,
400
+ 0.0
401
+ ],
402
+ [
403
+ 1727260165.6647935,
404
+ 0.0
405
+ ],
406
+ [
407
+ 1727260212.0559795,
408
+ 0.0
409
+ ]
410
+ ]
411
+ },
412
+ "percent_used": {
413
+ "latest": 1.0,
414
+ "rate": 0.0,
415
+ "rates": [
416
+ [
417
+ 1727260045.5636568,
418
+ 0.0
419
+ ],
420
+ [
421
+ 1727260050.5730257,
422
+ 0.0
423
+ ],
424
+ [
425
+ 1727260055.56124,
426
+ 0.0
427
+ ],
428
+ [
429
+ 1727260060.564262,
430
+ 0.0
431
+ ],
432
+ [
433
+ 1727260065.5657525,
434
+ 0.0
435
+ ],
436
+ [
437
+ 1727260070.563676,
438
+ 0.0
439
+ ],
440
+ [
441
+ 1727260105.6695807,
442
+ 0.0
443
+ ],
444
+ [
445
+ 1727260165.6647935,
446
+ 0.0
447
+ ],
448
+ [
449
+ 1727260212.0559795,
450
+ 0.0
451
+ ]
452
+ ]
453
+ },
454
+ "max_avail": {
455
+ "latest": 83265085440,
456
+ "rate": 0.0,
457
+ "rates": [
458
+ [
459
+ 1727260045.5636568,
460
+ 0.0
461
+ ],
462
+ [
463
+ 1727260050.5730257,
464
+ 0.0
465
+ ],
466
+ [
467
+ 1727260055.56124,
468
+ 0.0
469
+ ],
470
+ [
471
+ 1727260060.564262,
472
+ 0.0
473
+ ],
474
+ [
475
+ 1727260065.5657525,
476
+ 0.0
477
+ ],
478
+ [
479
+ 1727260070.563676,
480
+ 0.0
481
+ ],
482
+ [
483
+ 1727260105.6695807,
484
+ 0.0
485
+ ],
486
+ [
487
+ 1727260165.6647935,
488
+ 0.0
489
+ ],
490
+ [
491
+ 1727260212.0559795,
492
+ 0.0
493
+ ]
494
+ ]
495
+ },
496
+ "quota_objects": {
497
+ "latest": 0,
498
+ "rate": 0.0,
499
+ "rates": [
500
+ [
501
+ 1727260045.5636568,
502
+ 0.0
503
+ ],
504
+ [
505
+ 1727260050.5730257,
506
+ 0.0
507
+ ],
508
+ [
509
+ 1727260055.56124,
510
+ 0.0
511
+ ],
512
+ [
513
+ 1727260060.564262,
514
+ 0.0
515
+ ],
516
+ [
517
+ 1727260065.5657525,
518
+ 0.0
519
+ ],
520
+ [
521
+ 1727260070.563676,
522
+ 0.0
523
+ ],
524
+ [
525
+ 1727260105.6695807,
526
+ 0.0
527
+ ],
528
+ [
529
+ 1727260165.6647935,
530
+ 0.0
531
+ ],
532
+ [
533
+ 1727260212.0559795,
534
+ 0.0
535
+ ]
536
+ ]
537
+ },
538
+ "quota_bytes": {
539
+ "latest": 2147483648,
540
+ "rate": 0.0,
541
+ "rates": [
542
+ [
543
+ 1727260045.5636568,
544
+ 0.0
545
+ ],
546
+ [
547
+ 1727260050.5730257,
548
+ 0.0
549
+ ],
550
+ [
551
+ 1727260055.56124,
552
+ 0.0
553
+ ],
554
+ [
555
+ 1727260060.564262,
556
+ 0.0
557
+ ],
558
+ [
559
+ 1727260065.5657525,
560
+ 0.0
561
+ ],
562
+ [
563
+ 1727260070.563676,
564
+ 0.0
565
+ ],
566
+ [
567
+ 1727260105.6695807,
568
+ 0.0
569
+ ],
570
+ [
571
+ 1727260165.6647935,
572
+ 0.0
573
+ ],
574
+ [
575
+ 1727260212.0559795,
576
+ 0.0
577
+ ]
578
+ ]
579
+ },
580
+ "dirty": {
581
+ "latest": 0,
582
+ "rate": 0.0,
583
+ "rates": [
584
+ [
585
+ 1727260045.5636568,
586
+ 0.0
587
+ ],
588
+ [
589
+ 1727260050.5730257,
590
+ 0.0
591
+ ],
592
+ [
593
+ 1727260055.56124,
594
+ 0.0
595
+ ],
596
+ [
597
+ 1727260060.564262,
598
+ 0.0
599
+ ],
600
+ [
601
+ 1727260065.5657525,
602
+ 0.0
603
+ ],
604
+ [
605
+ 1727260070.563676,
606
+ 0.0
607
+ ],
608
+ [
609
+ 1727260105.6695807,
610
+ 0.0
611
+ ],
612
+ [
613
+ 1727260165.6647935,
614
+ 0.0
615
+ ],
616
+ [
617
+ 1727260212.0559795,
618
+ 0.0
619
+ ]
620
+ ]
621
+ },
622
+ "rd": {
623
+ "latest": 1,
624
+ "rate": 0.0,
625
+ "rates": [
626
+ [
627
+ 1727260045.5636568,
628
+ 0.0
629
+ ],
630
+ [
631
+ 1727260050.5730257,
632
+ 0.0
633
+ ],
634
+ [
635
+ 1727260055.56124,
636
+ 0.0
637
+ ],
638
+ [
639
+ 1727260060.564262,
640
+ 0.0
641
+ ],
642
+ [
643
+ 1727260065.5657525,
644
+ 0.0
645
+ ],
646
+ [
647
+ 1727260070.563676,
648
+ 0.0
649
+ ],
650
+ [
651
+ 1727260105.6695807,
652
+ 0.0
653
+ ],
654
+ [
655
+ 1727260165.6647935,
656
+ 0.0
657
+ ],
658
+ [
659
+ 1727260212.0559795,
660
+ 0.0
661
+ ]
662
+ ]
663
+ },
664
+ "rd_bytes": {
665
+ "latest": 1,
666
+ "rate": 0.0,
667
+ "rates": [
668
+ [
669
+ 1727260045.5636568,
670
+ 0.0
671
+ ],
672
+ [
673
+ 1727260050.5730257,
674
+ 0.0
675
+ ],
676
+ [
677
+ 1727260055.56124,
678
+ 0.0
679
+ ],
680
+ [
681
+ 1727260060.564262,
682
+ 0.0
683
+ ],
684
+ [
685
+ 1727260065.5657525,
686
+ 0.0
687
+ ],
688
+ [
689
+ 1727260070.563676,
690
+ 0.0
691
+ ],
692
+ [
693
+ 1727260105.6695807,
694
+ 0.0
695
+ ],
696
+ [
697
+ 1727260165.6647935,
698
+ 0.0
699
+ ],
700
+ [
701
+ 1727260212.0559795,
702
+ 0.0
703
+ ]
704
+ ]
705
+ },
706
+ "wr": {
707
+ "latest": 1,
708
+ "rate": 0.0,
709
+ "rates": [
710
+ [
711
+ 1727260045.5636568,
712
+ 0.0
713
+ ],
714
+ [
715
+ 1727260050.5730257,
716
+ 0.0
717
+ ],
718
+ [
719
+ 1727260055.56124,
720
+ 0.0
721
+ ],
722
+ [
723
+ 1727260060.564262,
724
+ 0.0
725
+ ],
726
+ [
727
+ 1727260065.5657525,
728
+ 0.0
729
+ ],
730
+ [
731
+ 1727260070.563676,
732
+ 0.0
733
+ ],
734
+ [
735
+ 1727260105.6695807,
736
+ 0.0
737
+ ],
738
+ [
739
+ 1727260165.6647935,
740
+ 0.0
741
+ ],
742
+ [
743
+ 1727260212.0559795,
744
+ 0.0
745
+ ]
746
+ ]
747
+ },
748
+ "wr_bytes": {
749
+ "latest": 1,
750
+ "rate": 0.0,
751
+ "rates": [
752
+ [
753
+ 1727260045.5636568,
754
+ 0.0
755
+ ],
756
+ [
757
+ 1727260050.5730257,
758
+ 0.0
759
+ ],
760
+ [
761
+ 1727260055.56124,
762
+ 0.0
763
+ ],
764
+ [
765
+ 1727260060.564262,
766
+ 0.0
767
+ ],
768
+ [
769
+ 1727260065.5657525,
770
+ 0.0
771
+ ],
772
+ [
773
+ 1727260070.563676,
774
+ 0.0
775
+ ],
776
+ [
777
+ 1727260105.6695807,
778
+ 0.0
779
+ ],
780
+ [
781
+ 1727260165.6647935,
782
+ 0.0
783
+ ],
784
+ [
785
+ 1727260212.0559795,
786
+ 0.0
787
+ ]
788
+ ]
789
+ },
790
+ "compress_bytes_used": {
791
+ "latest": 0,
792
+ "rate": 0.0,
793
+ "rates": [
794
+ [
795
+ 1727260045.5636568,
796
+ 0.0
797
+ ],
798
+ [
799
+ 1727260050.5730257,
800
+ 0.0
801
+ ],
802
+ [
803
+ 1727260055.56124,
804
+ 0.0
805
+ ],
806
+ [
807
+ 1727260060.564262,
808
+ 0.0
809
+ ],
810
+ [
811
+ 1727260065.5657525,
812
+ 0.0
813
+ ],
814
+ [
815
+ 1727260070.563676,
816
+ 0.0
817
+ ],
818
+ [
819
+ 1727260105.6695807,
820
+ 0.0
821
+ ],
822
+ [
823
+ 1727260165.6647935,
824
+ 0.0
825
+ ],
826
+ [
827
+ 1727260212.0559795,
828
+ 0.0
829
+ ]
830
+ ]
831
+ },
832
+ "compress_under_bytes": {
833
+ "latest": 0,
834
+ "rate": 0.0,
835
+ "rates": [
836
+ [
837
+ 1727260045.5636568,
838
+ 0.0
839
+ ],
840
+ [
841
+ 1727260050.5730257,
842
+ 0.0
843
+ ],
844
+ [
845
+ 1727260055.56124,
846
+ 0.0
847
+ ],
848
+ [
849
+ 1727260060.564262,
850
+ 0.0
851
+ ],
852
+ [
853
+ 1727260065.5657525,
854
+ 0.0
855
+ ],
856
+ [
857
+ 1727260070.563676,
858
+ 0.0
859
+ ],
860
+ [
861
+ 1727260105.6695807,
862
+ 0.0
863
+ ],
864
+ [
865
+ 1727260165.6647935,
866
+ 0.0
867
+ ],
868
+ [
869
+ 1727260212.0559795,
870
+ 0.0
871
+ ]
872
+ ]
873
+ },
874
+ "stored_raw": {
875
+ "latest": 0,
876
+ "rate": 0.0,
877
+ "rates": [
878
+ [
879
+ 1727260045.5636568,
880
+ 0.0
881
+ ],
882
+ [
883
+ 1727260050.5730257,
884
+ 0.0
885
+ ],
886
+ [
887
+ 1727260055.56124,
888
+ 0.0
889
+ ],
890
+ [
891
+ 1727260060.564262,
892
+ 0.0
893
+ ],
894
+ [
895
+ 1727260065.5657525,
896
+ 0.0
897
+ ],
898
+ [
899
+ 1727260070.563676,
900
+ 0.0
901
+ ],
902
+ [
903
+ 1727260105.6695807,
904
+ 0.0
905
+ ],
906
+ [
907
+ 1727260165.6647935,
908
+ 0.0
909
+ ],
910
+ [
911
+ 1727260212.0559795,
912
+ 0.0
913
+ ]
914
+ ]
915
+ },
916
+ "avail_raw": {
917
+ "latest": 166530172973,
918
+ "rate": 0.0,
919
+ "rates": [
920
+ [
921
+ 1727260045.5636568,
922
+ 0.0
923
+ ],
924
+ [
925
+ 1727260050.5730257,
926
+ 0.0
927
+ ],
928
+ [
929
+ 1727260055.56124,
930
+ 0.0
931
+ ],
932
+ [
933
+ 1727260060.564262,
934
+ 0.0
935
+ ],
936
+ [
937
+ 1727260065.5657525,
938
+ 0.0
939
+ ],
940
+ [
941
+ 1727260070.563676,
942
+ 0.0
943
+ ],
944
+ [
945
+ 1727260105.6695807,
946
+ 0.0
947
+ ],
948
+ [
949
+ 1727260165.6647935,
950
+ 0.0
951
+ ],
952
+ [
953
+ 1727260212.0559795,
954
+ 0.0
955
+ ]
956
+ ]
957
+ }
958
+ }
959
+ },
960
+ {
961
+ "pool": 2,
962
+ "pool_name": "device_health_metrics",
963
+ "flags": 1,
964
+ "flags_names": "hashpspool",
965
+ "type": "replicated",
966
+ "size": 2,
967
+ "min_size": 1,
968
+ "crush_rule": "replicated_rule",
969
+ "peering_crush_bucket_count": 0,
970
+ "peering_crush_bucket_target": 0,
971
+ "peering_crush_bucket_barrier": 0,
972
+ "peering_crush_bucket_mandatory_member": 2147483647,
973
+ "object_hash": 2,
974
+ "pg_autoscale_mode": "on",
975
+ "pg_num": 1,
976
+ "pg_placement_num": 1,
977
+ "pg_placement_num_target": 1,
978
+ "pg_num_target": 1,
979
+ "pg_num_pending": 1,
980
+ "last_pg_merge_meta": {
981
+ "ready_epoch": 0,
982
+ "last_epoch_started": 0,
983
+ "last_epoch_clean": 0,
984
+ "source_pgid": "0.0",
985
+ "source_version": "0'0",
986
+ "target_version": "0'0"
987
+ },
988
+ "auid": 0,
989
+ "snap_mode": "selfmanaged",
990
+ "snap_seq": 0,
991
+ "snap_epoch": 0,
992
+ "pool_snaps": [],
993
+ "quota_max_bytes": 0,
994
+ "quota_max_objects": 0,
995
+ "tiers": [],
996
+ "tier_of": -1,
997
+ "read_tier": -1,
998
+ "write_tier": -1,
999
+ "cache_mode": "none",
1000
+ "target_max_bytes": 0,
1001
+ "target_max_objects": 0,
1002
+ "cache_target_dirty_ratio_micro": 400000,
1003
+ "cache_target_dirty_high_ratio_micro": 600000,
1004
+ "cache_target_full_ratio_micro": 800000,
1005
+ "cache_min_flush_age": 0,
1006
+ "cache_min_evict_age": 0,
1007
+ "erasure_code_profile": "",
1008
+ "hit_set_params": {
1009
+ "type": "none"
1010
+ },
1011
+ "hit_set_period": 0,
1012
+ "hit_set_count": 0,
1013
+ "use_gmt_hitset": true,
1014
+ "min_read_recency_for_promote": 0,
1015
+ "min_write_recency_for_promote": 0,
1016
+ "hit_set_grade_decay_rate": 0,
1017
+ "hit_set_search_last_n": 0,
1018
+ "grade_table": [],
1019
+ "stripe_width": 0,
1020
+ "expected_num_objects": 0,
1021
+ "fast_read": false,
1022
+ "options": {
1023
+ "pg_num_max": 32,
1024
+ "pg_num_min": 1
1025
+ },
1026
+ "application_metadata": [
1027
+ "mgr_devicehealth"
1028
+ ],
1029
+ "create_time": "2024-09-24T10:00:22.967240+0000",
1030
+ "last_change": "25",
1031
+ "last_force_op_resend": "0",
1032
+ "last_force_op_resend_prenautilus": "0",
1033
+ "last_force_op_resend_preluminous": "0",
1034
+ "removed_snaps": "[]",
1035
+ "pg_status": {
1036
+ "active+clean": 1
1037
+ },
1038
+ "stats": {
1039
+ "stored": {
1040
+ "latest": 1,
1041
+ "rate": 0.0,
1042
+ "rates": [
1043
+ [
1044
+ 1727260045.5636568,
1045
+ 0.0
1046
+ ],
1047
+ [
1048
+ 1727260050.5730257,
1049
+ 0.0
1050
+ ],
1051
+ [
1052
+ 1727260055.56124,
1053
+ 0.0
1054
+ ],
1055
+ [
1056
+ 1727260060.564262,
1057
+ 0.0
1058
+ ],
1059
+ [
1060
+ 1727260065.5657525,
1061
+ 0.0
1062
+ ],
1063
+ [
1064
+ 1727260070.563676,
1065
+ 0.0
1066
+ ],
1067
+ [
1068
+ 1727260105.6695807,
1069
+ 0.0
1070
+ ],
1071
+ [
1072
+ 1727260165.6647935,
1073
+ 0.0
1074
+ ],
1075
+ [
1076
+ 1727260212.0559795,
1077
+ 0.0
1078
+ ]
1079
+ ]
1080
+ },
1081
+ "stored_data": {
1082
+ "latest": 1,
1083
+ "rate": 0.0,
1084
+ "rates": [
1085
+ [
1086
+ 1727260045.5636568,
1087
+ 0.0
1088
+ ],
1089
+ [
1090
+ 1727260050.5730257,
1091
+ 0.0
1092
+ ],
1093
+ [
1094
+ 1727260055.56124,
1095
+ 0.0
1096
+ ],
1097
+ [
1098
+ 1727260060.564262,
1099
+ 0.0
1100
+ ],
1101
+ [
1102
+ 1727260065.5657525,
1103
+ 0.0
1104
+ ],
1105
+ [
1106
+ 1727260070.563676,
1107
+ 0.0
1108
+ ],
1109
+ [
1110
+ 1727260105.6695807,
1111
+ 0.0
1112
+ ],
1113
+ [
1114
+ 1727260165.6647935,
1115
+ 0.0
1116
+ ],
1117
+ [
1118
+ 1727260212.0559795,
1119
+ 0.0
1120
+ ]
1121
+ ]
1122
+ },
1123
+ "stored_omap": {
1124
+ "latest": 0,
1125
+ "rate": 0.0,
1126
+ "rates": [
1127
+ [
1128
+ 1727260045.5636568,
1129
+ 0.0
1130
+ ],
1131
+ [
1132
+ 1727260050.5730257,
1133
+ 0.0
1134
+ ],
1135
+ [
1136
+ 1727260055.56124,
1137
+ 0.0
1138
+ ],
1139
+ [
1140
+ 1727260060.564262,
1141
+ 0.0
1142
+ ],
1143
+ [
1144
+ 1727260065.5657525,
1145
+ 0.0
1146
+ ],
1147
+ [
1148
+ 1727260070.563676,
1149
+ 0.0
1150
+ ],
1151
+ [
1152
+ 1727260105.6695807,
1153
+ 0.0
1154
+ ],
1155
+ [
1156
+ 1727260165.6647935,
1157
+ 0.0
1158
+ ],
1159
+ [
1160
+ 1727260212.0559795,
1161
+ 0.0
1162
+ ]
1163
+ ]
1164
+ },
1165
+ "objects": {
1166
+ "latest": 3,
1167
+ "rate": 0.0,
1168
+ "rates": [
1169
+ [
1170
+ 1727260045.5636568,
1171
+ 0.0
1172
+ ],
1173
+ [
1174
+ 1727260050.5730257,
1175
+ 0.0
1176
+ ],
1177
+ [
1178
+ 1727260055.56124,
1179
+ 0.0
1180
+ ],
1181
+ [
1182
+ 1727260060.564262,
1183
+ 0.0
1184
+ ],
1185
+ [
1186
+ 1727260065.5657525,
1187
+ 0.0
1188
+ ],
1189
+ [
1190
+ 1727260070.563676,
1191
+ 0.0
1192
+ ],
1193
+ [
1194
+ 1727260105.6695807,
1195
+ 0.0
1196
+ ],
1197
+ [
1198
+ 1727260165.6647935,
1199
+ 0.0
1200
+ ],
1201
+ [
1202
+ 1727260212.0559795,
1203
+ 0.0
1204
+ ]
1205
+ ]
1206
+ },
1207
+ "kb_used": {
1208
+ "latest": 0,
1209
+ "rate": 0.0,
1210
+ "rates": [
1211
+ [
1212
+ 1727260045.5636568,
1213
+ 0.0
1214
+ ],
1215
+ [
1216
+ 1727260050.5730257,
1217
+ 0.0
1218
+ ],
1219
+ [
1220
+ 1727260055.56124,
1221
+ 0.0
1222
+ ],
1223
+ [
1224
+ 1727260060.564262,
1225
+ 0.0
1226
+ ],
1227
+ [
1228
+ 1727260065.5657525,
1229
+ 0.0
1230
+ ],
1231
+ [
1232
+ 1727260070.563676,
1233
+ 0.0
1234
+ ],
1235
+ [
1236
+ 1727260105.6695807,
1237
+ 0.0
1238
+ ],
1239
+ [
1240
+ 1727260165.6647935,
1241
+ 0.0
1242
+ ],
1243
+ [
1244
+ 1727260212.0559795,
1245
+ 0.0
1246
+ ]
1247
+ ]
1248
+ },
1249
+ "bytes_used": {
1250
+ "latest": 1,
1251
+ "rate": 0.0,
1252
+ "rates": [
1253
+ [
1254
+ 1727260045.5636568,
1255
+ 0.0
1256
+ ],
1257
+ [
1258
+ 1727260050.5730257,
1259
+ 0.0
1260
+ ],
1261
+ [
1262
+ 1727260055.56124,
1263
+ 0.0
1264
+ ],
1265
+ [
1266
+ 1727260060.564262,
1267
+ 0.0
1268
+ ],
1269
+ [
1270
+ 1727260065.5657525,
1271
+ 0.0
1272
+ ],
1273
+ [
1274
+ 1727260070.563676,
1275
+ 0.0
1276
+ ],
1277
+ [
1278
+ 1727260105.6695807,
1279
+ 0.0
1280
+ ],
1281
+ [
1282
+ 1727260165.6647935,
1283
+ 0.0
1284
+ ],
1285
+ [
1286
+ 1727260212.0559795,
1287
+ 0.0
1288
+ ]
1289
+ ]
1290
+ },
1291
+ "data_bytes_used": {
1292
+ "latest": 0,
1293
+ "rate": 0.0,
1294
+ "rates": [
1295
+ [
1296
+ 1727260045.5636568,
1297
+ 0.0
1298
+ ],
1299
+ [
1300
+ 1727260050.5730257,
1301
+ 0.0
1302
+ ],
1303
+ [
1304
+ 1727260055.56124,
1305
+ 0.0
1306
+ ],
1307
+ [
1308
+ 1727260060.564262,
1309
+ 0.0
1310
+ ],
1311
+ [
1312
+ 1727260065.5657525,
1313
+ 0.0
1314
+ ],
1315
+ [
1316
+ 1727260070.563676,
1317
+ 0.0
1318
+ ],
1319
+ [
1320
+ 1727260105.6695807,
1321
+ 0.0
1322
+ ],
1323
+ [
1324
+ 1727260165.6647935,
1325
+ 0.0
1326
+ ],
1327
+ [
1328
+ 1727260212.0559795,
1329
+ 0.0
1330
+ ]
1331
+ ]
1332
+ },
1333
+ "omap_bytes_used": {
1334
+ "latest": 0,
1335
+ "rate": 0.0,
1336
+ "rates": [
1337
+ [
1338
+ 1727260045.5636568,
1339
+ 0.0
1340
+ ],
1341
+ [
1342
+ 1727260050.5730257,
1343
+ 0.0
1344
+ ],
1345
+ [
1346
+ 1727260055.56124,
1347
+ 0.0
1348
+ ],
1349
+ [
1350
+ 1727260060.564262,
1351
+ 0.0
1352
+ ],
1353
+ [
1354
+ 1727260065.5657525,
1355
+ 0.0
1356
+ ],
1357
+ [
1358
+ 1727260070.563676,
1359
+ 0.0
1360
+ ],
1361
+ [
1362
+ 1727260105.6695807,
1363
+ 0.0
1364
+ ],
1365
+ [
1366
+ 1727260165.6647935,
1367
+ 0.0
1368
+ ],
1369
+ [
1370
+ 1727260212.0559795,
1371
+ 0.0
1372
+ ]
1373
+ ]
1374
+ },
1375
+ "percent_used": {
1376
+ "latest": 1.0,
1377
+ "rate": 0.0,
1378
+ "rates": [
1379
+ [
1380
+ 1727260045.5636568,
1381
+ 0.0
1382
+ ],
1383
+ [
1384
+ 1727260050.5730257,
1385
+ 0.0
1386
+ ],
1387
+ [
1388
+ 1727260055.56124,
1389
+ 0.0
1390
+ ],
1391
+ [
1392
+ 1727260060.564262,
1393
+ 0.0
1394
+ ],
1395
+ [
1396
+ 1727260065.5657525,
1397
+ 0.0
1398
+ ],
1399
+ [
1400
+ 1727260070.563676,
1401
+ 0.0
1402
+ ],
1403
+ [
1404
+ 1727260105.6695807,
1405
+ 0.0
1406
+ ],
1407
+ [
1408
+ 1727260165.6647935,
1409
+ 0.0
1410
+ ],
1411
+ [
1412
+ 1727260212.0559795,
1413
+ 0.0
1414
+ ]
1415
+ ]
1416
+ },
1417
+ "max_avail": {
1418
+ "latest": 83265085440,
1419
+ "rate": 0.0,
1420
+ "rates": [
1421
+ [
1422
+ 1727260045.5636568,
1423
+ 0.0
1424
+ ],
1425
+ [
1426
+ 1727260050.5730257,
1427
+ 0.0
1428
+ ],
1429
+ [
1430
+ 1727260055.56124,
1431
+ 0.0
1432
+ ],
1433
+ [
1434
+ 1727260060.564262,
1435
+ 0.0
1436
+ ],
1437
+ [
1438
+ 1727260065.5657525,
1439
+ 0.0
1440
+ ],
1441
+ [
1442
+ 1727260070.563676,
1443
+ 0.0
1444
+ ],
1445
+ [
1446
+ 1727260105.6695807,
1447
+ 0.0
1448
+ ],
1449
+ [
1450
+ 1727260165.6647935,
1451
+ 0.0
1452
+ ],
1453
+ [
1454
+ 1727260212.0559795,
1455
+ 0.0
1456
+ ]
1457
+ ]
1458
+ },
1459
+ "quota_objects": {
1460
+ "latest": 0,
1461
+ "rate": 0.0,
1462
+ "rates": [
1463
+ [
1464
+ 1727260045.5636568,
1465
+ 0.0
1466
+ ],
1467
+ [
1468
+ 1727260050.5730257,
1469
+ 0.0
1470
+ ],
1471
+ [
1472
+ 1727260055.56124,
1473
+ 0.0
1474
+ ],
1475
+ [
1476
+ 1727260060.564262,
1477
+ 0.0
1478
+ ],
1479
+ [
1480
+ 1727260065.5657525,
1481
+ 0.0
1482
+ ],
1483
+ [
1484
+ 1727260070.563676,
1485
+ 0.0
1486
+ ],
1487
+ [
1488
+ 1727260105.6695807,
1489
+ 0.0
1490
+ ],
1491
+ [
1492
+ 1727260165.6647935,
1493
+ 0.0
1494
+ ],
1495
+ [
1496
+ 1727260212.0559795,
1497
+ 0.0
1498
+ ]
1499
+ ]
1500
+ },
1501
+ "quota_bytes": {
1502
+ "latest": 0,
1503
+ "rate": 0.0,
1504
+ "rates": [
1505
+ [
1506
+ 1727260045.5636568,
1507
+ 0.0
1508
+ ],
1509
+ [
1510
+ 1727260050.5730257,
1511
+ 0.0
1512
+ ],
1513
+ [
1514
+ 1727260055.56124,
1515
+ 0.0
1516
+ ],
1517
+ [
1518
+ 1727260060.564262,
1519
+ 0.0
1520
+ ],
1521
+ [
1522
+ 1727260065.5657525,
1523
+ 0.0
1524
+ ],
1525
+ [
1526
+ 1727260070.563676,
1527
+ 0.0
1528
+ ],
1529
+ [
1530
+ 1727260105.6695807,
1531
+ 0.0
1532
+ ],
1533
+ [
1534
+ 1727260165.6647935,
1535
+ 0.0
1536
+ ],
1537
+ [
1538
+ 1727260212.0559795,
1539
+ 0.0
1540
+ ]
1541
+ ]
1542
+ },
1543
+ "dirty": {
1544
+ "latest": 0,
1545
+ "rate": 0.0,
1546
+ "rates": [
1547
+ [
1548
+ 1727260045.5636568,
1549
+ 0.0
1550
+ ],
1551
+ [
1552
+ 1727260050.5730257,
1553
+ 0.0
1554
+ ],
1555
+ [
1556
+ 1727260055.56124,
1557
+ 0.0
1558
+ ],
1559
+ [
1560
+ 1727260060.564262,
1561
+ 0.0
1562
+ ],
1563
+ [
1564
+ 1727260065.5657525,
1565
+ 0.0
1566
+ ],
1567
+ [
1568
+ 1727260070.563676,
1569
+ 0.0
1570
+ ],
1571
+ [
1572
+ 1727260105.6695807,
1573
+ 0.0
1574
+ ],
1575
+ [
1576
+ 1727260165.6647935,
1577
+ 0.0
1578
+ ],
1579
+ [
1580
+ 1727260212.0559795,
1581
+ 0.0
1582
+ ]
1583
+ ]
1584
+ },
1585
+ "rd": {
1586
+ "latest": 1,
1587
+ "rate": 0.0,
1588
+ "rates": [
1589
+ [
1590
+ 1727260045.5636568,
1591
+ 0.0
1592
+ ],
1593
+ [
1594
+ 1727260050.5730257,
1595
+ 0.0
1596
+ ],
1597
+ [
1598
+ 1727260055.56124,
1599
+ 0.0
1600
+ ],
1601
+ [
1602
+ 1727260060.564262,
1603
+ 0.0
1604
+ ],
1605
+ [
1606
+ 1727260065.5657525,
1607
+ 0.0
1608
+ ],
1609
+ [
1610
+ 1727260070.563676,
1611
+ 0.0
1612
+ ],
1613
+ [
1614
+ 1727260105.6695807,
1615
+ 0.0
1616
+ ],
1617
+ [
1618
+ 1727260165.6647935,
1619
+ 0.0
1620
+ ],
1621
+ [
1622
+ 1727260212.0559795,
1623
+ 0.0
1624
+ ]
1625
+ ]
1626
+ },
1627
+ "rd_bytes": {
1628
+ "latest": 1,
1629
+ "rate": 0.0,
1630
+ "rates": [
1631
+ [
1632
+ 1727260045.5636568,
1633
+ 0.0
1634
+ ],
1635
+ [
1636
+ 1727260050.5730257,
1637
+ 0.0
1638
+ ],
1639
+ [
1640
+ 1727260055.56124,
1641
+ 0.0
1642
+ ],
1643
+ [
1644
+ 1727260060.564262,
1645
+ 0.0
1646
+ ],
1647
+ [
1648
+ 1727260065.5657525,
1649
+ 0.0
1650
+ ],
1651
+ [
1652
+ 1727260070.563676,
1653
+ 0.0
1654
+ ],
1655
+ [
1656
+ 1727260105.6695807,
1657
+ 0.0
1658
+ ],
1659
+ [
1660
+ 1727260165.6647935,
1661
+ 0.0
1662
+ ],
1663
+ [
1664
+ 1727260212.0559795,
1665
+ 0.0
1666
+ ]
1667
+ ]
1668
+ },
1669
+ "wr": {
1670
+ "latest": 3,
1671
+ "rate": 0.0,
1672
+ "rates": [
1673
+ [
1674
+ 1727260045.5636568,
1675
+ 0.0
1676
+ ],
1677
+ [
1678
+ 1727260050.5730257,
1679
+ 0.0
1680
+ ],
1681
+ [
1682
+ 1727260055.56124,
1683
+ 0.0
1684
+ ],
1685
+ [
1686
+ 1727260060.564262,
1687
+ 0.0
1688
+ ],
1689
+ [
1690
+ 1727260065.5657525,
1691
+ 0.0
1692
+ ],
1693
+ [
1694
+ 1727260070.563676,
1695
+ 0.0
1696
+ ],
1697
+ [
1698
+ 1727260105.6695807,
1699
+ 0.0
1700
+ ],
1701
+ [
1702
+ 1727260165.6647935,
1703
+ 0.0
1704
+ ],
1705
+ [
1706
+ 1727260212.0559795,
1707
+ 0.0
1708
+ ]
1709
+ ]
1710
+ },
1711
+ "wr_bytes": {
1712
+ "latest": 6144,
1713
+ "rate": 0.0,
1714
+ "rates": [
1715
+ [
1716
+ 1727260045.5636568,
1717
+ 0.0
1718
+ ],
1719
+ [
1720
+ 1727260050.5730257,
1721
+ 0.0
1722
+ ],
1723
+ [
1724
+ 1727260055.56124,
1725
+ 0.0
1726
+ ],
1727
+ [
1728
+ 1727260060.564262,
1729
+ 0.0
1730
+ ],
1731
+ [
1732
+ 1727260065.5657525,
1733
+ 0.0
1734
+ ],
1735
+ [
1736
+ 1727260070.563676,
1737
+ 0.0
1738
+ ],
1739
+ [
1740
+ 1727260105.6695807,
1741
+ 0.0
1742
+ ],
1743
+ [
1744
+ 1727260165.6647935,
1745
+ 0.0
1746
+ ],
1747
+ [
1748
+ 1727260212.0559795,
1749
+ 0.0
1750
+ ]
1751
+ ]
1752
+ },
1753
+ "compress_bytes_used": {
1754
+ "latest": 0,
1755
+ "rate": 0.0,
1756
+ "rates": [
1757
+ [
1758
+ 1727260045.5636568,
1759
+ 0.0
1760
+ ],
1761
+ [
1762
+ 1727260050.5730257,
1763
+ 0.0
1764
+ ],
1765
+ [
1766
+ 1727260055.56124,
1767
+ 0.0
1768
+ ],
1769
+ [
1770
+ 1727260060.564262,
1771
+ 0.0
1772
+ ],
1773
+ [
1774
+ 1727260065.5657525,
1775
+ 0.0
1776
+ ],
1777
+ [
1778
+ 1727260070.563676,
1779
+ 0.0
1780
+ ],
1781
+ [
1782
+ 1727260105.6695807,
1783
+ 0.0
1784
+ ],
1785
+ [
1786
+ 1727260165.6647935,
1787
+ 0.0
1788
+ ],
1789
+ [
1790
+ 1727260212.0559795,
1791
+ 0.0
1792
+ ]
1793
+ ]
1794
+ },
1795
+ "compress_under_bytes": {
1796
+ "latest": 0,
1797
+ "rate": 0.0,
1798
+ "rates": [
1799
+ [
1800
+ 1727260045.5636568,
1801
+ 0.0
1802
+ ],
1803
+ [
1804
+ 1727260050.5730257,
1805
+ 0.0
1806
+ ],
1807
+ [
1808
+ 1727260055.56124,
1809
+ 0.0
1810
+ ],
1811
+ [
1812
+ 1727260060.564262,
1813
+ 0.0
1814
+ ],
1815
+ [
1816
+ 1727260065.5657525,
1817
+ 0.0
1818
+ ],
1819
+ [
1820
+ 1727260070.563676,
1821
+ 0.0
1822
+ ],
1823
+ [
1824
+ 1727260105.6695807,
1825
+ 0.0
1826
+ ],
1827
+ [
1828
+ 1727260165.6647935,
1829
+ 0.0
1830
+ ],
1831
+ [
1832
+ 1727260212.0559795,
1833
+ 0.0
1834
+ ]
1835
+ ]
1836
+ },
1837
+ "stored_raw": {
1838
+ "latest": 0,
1839
+ "rate": 0.0,
1840
+ "rates": [
1841
+ [
1842
+ 1727260045.5636568,
1843
+ 0.0
1844
+ ],
1845
+ [
1846
+ 1727260050.5730257,
1847
+ 0.0
1848
+ ],
1849
+ [
1850
+ 1727260055.56124,
1851
+ 0.0
1852
+ ],
1853
+ [
1854
+ 1727260060.564262,
1855
+ 0.0
1856
+ ],
1857
+ [
1858
+ 1727260065.5657525,
1859
+ 0.0
1860
+ ],
1861
+ [
1862
+ 1727260070.563676,
1863
+ 0.0
1864
+ ],
1865
+ [
1866
+ 1727260105.6695807,
1867
+ 0.0
1868
+ ],
1869
+ [
1870
+ 1727260165.6647935,
1871
+ 0.0
1872
+ ],
1873
+ [
1874
+ 1727260212.0559795,
1875
+ 0.0
1876
+ ]
1877
+ ]
1878
+ },
1879
+ "avail_raw": {
1880
+ "latest": 166530172973,
1881
+ "rate": 0.0,
1882
+ "rates": [
1883
+ [
1884
+ 1727260045.5636568,
1885
+ 0.0
1886
+ ],
1887
+ [
1888
+ 1727260050.5730257,
1889
+ 0.0
1890
+ ],
1891
+ [
1892
+ 1727260055.56124,
1893
+ 0.0
1894
+ ],
1895
+ [
1896
+ 1727260060.564262,
1897
+ 0.0
1898
+ ],
1899
+ [
1900
+ 1727260065.5657525,
1901
+ 0.0
1902
+ ],
1903
+ [
1904
+ 1727260070.563676,
1905
+ 0.0
1906
+ ],
1907
+ [
1908
+ 1727260105.6695807,
1909
+ 0.0
1910
+ ],
1911
+ [
1912
+ 1727260165.6647935,
1913
+ 0.0
1914
+ ],
1915
+ [
1916
+ 1727260212.0559795,
1917
+ 0.0
1918
+ ]
1919
+ ]
1920
+ }
1921
+ }
1922
+ }
1923
+]
src/go/plugin/go.d/modules/init.go
+1
@@ -12,6 +12,7 @@ import (
12
_ "github.com/netdata/netdata/go/plugins/plugin/go.d/modules/bind"
13
_ "github.com/netdata/netdata/go/plugins/plugin/go.d/modules/boinc"
14
_ "github.com/netdata/netdata/go/plugins/plugin/go.d/modules/cassandra"
15
+ _ "github.com/netdata/netdata/go/plugins/plugin/go.d/modules/ceph"
16
_ "github.com/netdata/netdata/go/plugins/plugin/go.d/modules/chrony"
17
_ "github.com/netdata/netdata/go/plugins/plugin/go.d/modules/clickhouse"
18
_ "github.com/netdata/netdata/go/plugins/plugin/go.d/modules/cockroachdb"