Skip to content

Commit 01a3547

Browse files
committed
Add separate metrics for non-numeric fields
Every report group (PV, VG, LV) had its own info metric where non-numeric fields like `pv_attr` were reported as a label. Every unique combination of labels produces a new time series. From https://prometheus.io/docs/practices/naming/#labels: > Remember that every unique combination of key-value label pairs > represents a new time series, which can dramatically increase the > amount of data stored. Do not use labels to store dimensions with high > cardinality (many different label values), such as user IDs, email > addresses, or other unbounded sets of values. With this change the labels on the info metrics are reduced to names (e.g. `pv_name` and `lv_full_name`). Everything else is moved to separate metrics. A command line flag, enabled by default, retains the labels on the info metric. Related to issue #31.
1 parent 80d797e commit 01a3547

26 files changed

+5050
-76
lines changed

README.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,11 @@ directly using [Go][golang] or [GoReleaser][goreleaser].
3737
## Example metrics
3838

3939
```
40-
lvm_pv_info{pv_fmt="lvm2",pv_name="/dev/sda1",pv_uuid="yc1zVe-…"} 1
41-
lvm_pv_info{pv_fmt="lvm2",pv_name="/dev/sdb1",pv_uuid="WVIH97-…"} 1
40+
lvm_pv_info{pv_name="/dev/sda1",pv_uuid="yc1zVe-…"} 1
41+
lvm_pv_info{pv_name="/dev/sdb1",pv_uuid="WVIH97-…"} 1
42+
43+
lvm_pv_fmt{pv_fmt="lvm2",pv_uuid="yc1zVe-…"} 1
44+
lvm_pv_fmt{pv_fmt="lvm2",pv_uuid="WVIH97-…"} 1
4245
4346
lvm_pv_free_bytes{pv_uuid="WVIH97-…"} 9.14358272e+08
4447
lvm_pv_free_bytes{pv_uuid="yc1zVe-…"} 1.040187392e+09

collector_test.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,9 +73,13 @@ func TestCollector(t *testing.T) {
7373
{name: "issue30-lockargs"},
7474
} {
7575
t.Run(tc.name, func(t *testing.T) {
76-
for _, enableLegacyInfoLabels := range []bool{false} {
76+
for _, enableLegacyInfoLabels := range []bool{false, true} {
7777
expectedName := tc.name
7878

79+
if enableLegacyInfoLabels {
80+
expectedName += "-legacy"
81+
}
82+
7983
t.Run(strconv.FormatBool(enableLegacyInfoLabels), func(t *testing.T) {
8084
c := newCollector(enableLegacyInfoLabels)
8185
c.load = func(ctx context.Context) (*lvmreport.ReportData, error) {

field.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,13 @@ func fromNumeric(value string) (float64, error) {
88
return strconv.ParseFloat(value, 64)
99
}
1010

11+
type fieldFlag uint
12+
13+
const (
14+
// Whether the field should be included as a label on an info metric.
15+
asInfoLabel fieldFlag = 1 << iota
16+
)
17+
1118
type field interface {
1219
Name() string
1320
MetricName() string
@@ -20,6 +27,8 @@ type textField struct {
2027
fieldName string
2128
desc string
2229

30+
flags fieldFlag
31+
2332
metricName string
2433
}
2534

groupcollector.go

Lines changed: 57 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -27,22 +27,40 @@ func (f *groupField) collect(ch chan<- prometheus.Metric, rawValue string, keyVa
2727
return nil
2828
}
2929

30+
type groupTextField struct {
31+
metricDesc *prometheus.Desc
32+
}
33+
34+
func (f *groupTextField) collect(ch chan<- prometheus.Metric, rawValue string, keyValues []string) error {
35+
labels := defaultStringSlicePool.get()
36+
defer defaultStringSlicePool.put(labels)
37+
38+
labels = append(labels, keyValues...)
39+
labels = append(labels, rawValue)
40+
41+
ch <- prometheus.MustNewConstMetric(f.metricDesc, prometheus.GaugeValue, 1, labels...)
42+
43+
return nil
44+
}
45+
3046
type groupCollector struct {
3147
name lvmreport.GroupName
3248

3349
infoDesc *prometheus.Desc
3450
unknownDesc *prometheus.Desc
3551

36-
keyFields []string
37-
textFields []string
38-
numericFields map[string]*groupField
39-
knownFields map[string]struct{}
52+
keyFields []string
53+
textFields map[string]*groupTextField
54+
numericFields map[string]*groupField
55+
infoLabelFields []string
56+
knownFields map[string]struct{}
4057
}
4158

4259
func newGroupCollector(enableLegacyInfoLabels bool, g *group) *groupCollector {
4360
c := &groupCollector{
4461
name: g.name,
4562
unknownDesc: prometheus.NewDesc("unknown_field_count", "Fields reported by LVM not recognized by exporter", []string{"group", "details"}, nil),
63+
textFields: map[string]*groupTextField{},
4664
numericFields: map[string]*groupField{},
4765
knownFields: map[string]struct{}{},
4866
}
@@ -55,15 +73,18 @@ func newGroupCollector(enableLegacyInfoLabels bool, g *group) *groupCollector {
5573
keyLabelNames = append(keyLabelNames, f.metricName)
5674
}
5775

58-
infoLabelNames := slices.Clone(keyLabelNames)
59-
6076
for _, f := range g.textFields {
61-
c.textFields = append(c.textFields, f.fieldName)
6277
c.knownFields[f.fieldName] = struct{}{}
63-
infoLabelNames = append(infoLabelNames, f.metricName)
64-
}
6578

66-
c.infoDesc = prometheus.NewDesc(g.infoMetricName, "", infoLabelNames, nil)
79+
if f.flags&asInfoLabel == 0 {
80+
textLabelNames := slices.Clone(keyLabelNames)
81+
textLabelNames = append(textLabelNames, f.metricName)
82+
83+
c.textFields[f.fieldName] = &groupTextField{
84+
metricDesc: prometheus.NewDesc(f.metricName, f.desc, textLabelNames, nil),
85+
}
86+
}
87+
}
6788

6889
for _, f := range g.numericFields {
6990
info := &groupField{
@@ -77,13 +98,28 @@ func newGroupCollector(enableLegacyInfoLabels bool, g *group) *groupCollector {
7798
c.knownFields[f.fieldName] = struct{}{}
7899
}
79100

101+
infoLabelNames := slices.Clone(keyLabelNames)
102+
103+
for _, f := range g.textFields {
104+
if enableLegacyInfoLabels || f.flags&asInfoLabel != 0 {
105+
c.infoLabelFields = append(c.infoLabelFields, f.fieldName)
106+
infoLabelNames = append(infoLabelNames, f.metricName)
107+
}
108+
}
109+
110+
c.infoDesc = prometheus.NewDesc(g.infoMetricName, "", infoLabelNames, nil)
111+
80112
return c
81113
}
82114

83115
func (c *groupCollector) describe(ch chan<- *prometheus.Desc) {
84116
ch <- c.infoDesc
85117
ch <- c.unknownDesc
86118

119+
for _, info := range c.textFields {
120+
ch <- info.metricDesc
121+
}
122+
87123
for _, info := range c.numericFields {
88124
ch <- info.metricDesc
89125
}
@@ -103,26 +139,31 @@ func (c *groupCollector) collect(ch chan<- prometheus.Metric, data *lvmreport.Re
103139

104140
infoValues := slices.Clone(keyValues)
105141

106-
for _, name := range c.textFields {
142+
for _, name := range c.infoLabelFields {
107143
infoValues = append(infoValues, row[name])
108144
}
109145

110146
ch <- prometheus.MustNewConstMetric(c.infoDesc, prometheus.GaugeValue, 1, infoValues...)
111147

112148
for fieldName, rawValue := range row {
113-
if rawValue == "" {
114-
continue
149+
var collector interface {
150+
collect(chan<- prometheus.Metric, string, []string) error
115151
}
116152

117-
info, ok := c.numericFields[fieldName]
118-
if !ok {
153+
if info, ok := c.textFields[fieldName]; ok {
154+
collector = info
155+
} else if rawValue == "" {
156+
continue
157+
} else if info, ok := c.numericFields[fieldName]; ok {
158+
collector = info
159+
} else {
119160
if _, ok := c.knownFields[fieldName]; !ok {
120161
unknown[fieldName] = struct{}{}
121162
}
122163
continue
123164
}
124165

125-
if err := info.collect(ch, rawValue, keyValues); err != nil {
166+
if err := collector.collect(ch, rawValue, keyValues); err != nil {
126167
allErrors.Append(fmt.Errorf("field %s: %w", fieldName, err))
127168
continue
128169
}

lv.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ var lvGroup = &group{
9797
{
9898
fieldName: "lv_full_name",
9999
metricName: "lv_full_name",
100+
flags: asInfoLabel,
100101
desc: "Full name of LV including its VG, namely VG/LV",
101102
},
102103
{
@@ -132,6 +133,7 @@ var lvGroup = &group{
132133
{
133134
fieldName: "lv_name",
134135
metricName: "lv_name",
136+
flags: asInfoLabel,
135137
desc: "Name; LVs created for internal use are enclosed in brackets",
136138
},
137139
{

pool.go

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package main
2+
3+
import (
4+
"sync"
5+
)
6+
7+
var defaultStringSlicePool = newStringSlicePool()
8+
9+
type stringSlicePool struct {
10+
pool sync.Pool
11+
}
12+
13+
func newStringSlicePool() *stringSlicePool {
14+
return &stringSlicePool{
15+
pool: sync.Pool{
16+
New: func() any {
17+
return []string(nil)
18+
},
19+
},
20+
}
21+
}
22+
23+
// get returns an empty string slice. The caller has ownership of the slice
24+
// until the slice is put back into the pool.
25+
func (p *stringSlicePool) get() []string {
26+
return p.pool.Get().([]string)[:0]
27+
}
28+
29+
func (p *stringSlicePool) put(s []string) {
30+
// All elements must be accessible.
31+
s = s[:cap(s)]
32+
33+
// Remove references to values.
34+
clear(s)
35+
36+
p.pool.Put(s)
37+
}

pool_test.go

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package main
2+
3+
import (
4+
"math/rand/v2"
5+
"slices"
6+
"strconv"
7+
"testing"
8+
)
9+
10+
func TestStringSlicePool(t *testing.T) {
11+
p := newStringSlicePool()
12+
13+
for range 100 {
14+
s := p.get()
15+
16+
if len(s) > 0 {
17+
t.Errorf("get() returned non-empty slice: %q", s)
18+
}
19+
20+
count := rand.IntN(100)
21+
22+
for i := range count {
23+
s = append(s, strconv.Itoa(i))
24+
}
25+
26+
switch rand.IntN(3) {
27+
case 1:
28+
s = s[:0]
29+
case 2:
30+
s = s[:count/2]
31+
}
32+
33+
p.put(s)
34+
35+
if idx := slices.IndexFunc(s[:count], func(value string) bool {
36+
return value != ""
37+
}); idx != -1 {
38+
t.Errorf("Slice was not cleared: %q", s[:count])
39+
}
40+
}
41+
}

pv.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,12 @@ var pvGroup = &group{
1212
textFields: []*textField{
1313
{fieldName: "pv_attr", metricName: "pv_attr"},
1414
{fieldName: "pv_fmt", metricName: "pv_fmt", desc: "Type of metadata"},
15-
{fieldName: "pv_name", metricName: "pv_name", desc: "Name"},
15+
{
16+
fieldName: "pv_name",
17+
metricName: "pv_name",
18+
flags: asInfoLabel,
19+
desc: "Name",
20+
},
1621
{fieldName: "pv_tags", metricName: "pv_tags"},
1722
},
1823
numericFields: []*numericField{

testdata/group-collector-with-error.golden

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22
# TYPE lvm_m_count gauge
33
lvm_m_count{m_key1="2"} 22
44
lvm_m_count{m_key1="3"} 11.5
5+
# HELP lvm_m_info1
6+
# TYPE lvm_m_info1 gauge
7+
lvm_m_info1{m_info1="info:2",m_key1="2"} 1
58
# HELP lvm_test_info
69
# TYPE lvm_test_info gauge
710
lvm_test_info{m_info1="",m_key1="1"} 1
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# HELP lvm_lv_info
2+
# TYPE lvm_lv_info gauge
3+
lvm_lv_info{lv_active="",lv_allocation_policy="",lv_ancestors="",lv_attr="",lv_convert_lv="",lv_convert_lv_uuid="",lv_data_lv="",lv_data_lv_uuid="",lv_descendants="",lv_dm_path="",lv_full_ancestors="",lv_full_descendants="",lv_full_name="",lv_health_status="",lv_host="",lv_kernel_cache_policy="",lv_kernel_cache_settings="",lv_kernel_discards="",lv_kernel_metadata_format="",lv_kernel_read_ahead_bytes="",lv_layout="",lv_lockargs="",lv_metadata_lv="",lv_metadata_lv_uuid="",lv_mirror_log="",lv_mirror_log_uuid="",lv_modules="",lv_move_pv="",lv_move_pv_uuid="",lv_name="[vpool0_vdata]",lv_origin="",lv_origin_uuid="",lv_parent="",lv_path="",lv_permissions="",lv_pool_lv="",lv_pool_lv_uuid="",lv_raid_sync_action="",lv_raidintegritymode="",lv_role="",lv_tags="",lv_uuid="tHnHR1-bjg8-ycJX-eyhR-heEp-L4qs-S510dO",lv_vdo_compression_state="",lv_vdo_index_state="",lv_vdo_operating_mode="",lv_when_full=""} 1
4+
lvm_lv_info{lv_active="",lv_allocation_policy="",lv_ancestors="",lv_attr="",lv_convert_lv="",lv_convert_lv_uuid="",lv_data_lv="",lv_data_lv_uuid="",lv_descendants="",lv_dm_path="",lv_full_ancestors="",lv_full_descendants="",lv_full_name="",lv_health_status="",lv_host="",lv_kernel_cache_policy="",lv_kernel_cache_settings="",lv_kernel_discards="",lv_kernel_metadata_format="",lv_kernel_read_ahead_bytes="",lv_layout="",lv_lockargs="",lv_metadata_lv="",lv_metadata_lv_uuid="",lv_mirror_log="",lv_mirror_log_uuid="",lv_modules="",lv_move_pv="",lv_move_pv_uuid="",lv_name="lv_data",lv_origin="",lv_origin_uuid="",lv_parent="",lv_path="",lv_permissions="",lv_pool_lv="",lv_pool_lv_uuid="",lv_raid_sync_action="",lv_raidintegritymode="",lv_role="",lv_tags="",lv_uuid="5UyOrx-zG6u-w7cF-G2Ny-HmVd-0lsb-4J6lG2",lv_vdo_compression_state="",lv_vdo_index_state="",lv_vdo_operating_mode="",lv_when_full=""} 1
5+
lvm_lv_info{lv_active="",lv_allocation_policy="",lv_ancestors="",lv_attr="",lv_convert_lv="",lv_convert_lv_uuid="",lv_data_lv="",lv_data_lv_uuid="",lv_descendants="",lv_dm_path="",lv_full_ancestors="",lv_full_descendants="",lv_full_name="",lv_health_status="",lv_host="",lv_kernel_cache_policy="",lv_kernel_cache_settings="",lv_kernel_discards="",lv_kernel_metadata_format="",lv_kernel_read_ahead_bytes="",lv_layout="",lv_lockargs="",lv_metadata_lv="",lv_metadata_lv_uuid="",lv_mirror_log="",lv_mirror_log_uuid="",lv_modules="",lv_move_pv="",lv_move_pv_uuid="",lv_name="lv_db_backup",lv_origin="",lv_origin_uuid="",lv_parent="",lv_path="",lv_permissions="",lv_pool_lv="",lv_pool_lv_uuid="",lv_raid_sync_action="",lv_raidintegritymode="",lv_role="",lv_tags="",lv_uuid="r7Btja-nL3P-Co38-X2K4-DLWS-LMhT-LajcQa",lv_vdo_compression_state="online",lv_vdo_index_state="online",lv_vdo_operating_mode="normal",lv_when_full=""} 1
6+
lvm_lv_info{lv_active="",lv_allocation_policy="",lv_ancestors="",lv_attr="",lv_convert_lv="",lv_convert_lv_uuid="",lv_data_lv="",lv_data_lv_uuid="",lv_descendants="",lv_dm_path="",lv_full_ancestors="",lv_full_descendants="",lv_full_name="",lv_health_status="",lv_host="",lv_kernel_cache_policy="",lv_kernel_cache_settings="",lv_kernel_discards="",lv_kernel_metadata_format="",lv_kernel_read_ahead_bytes="",lv_layout="",lv_lockargs="",lv_metadata_lv="",lv_metadata_lv_uuid="",lv_mirror_log="",lv_mirror_log_uuid="",lv_modules="",lv_move_pv="",lv_move_pv_uuid="",lv_name="root",lv_origin="",lv_origin_uuid="",lv_parent="",lv_path="",lv_permissions="",lv_pool_lv="",lv_pool_lv_uuid="",lv_raid_sync_action="",lv_raidintegritymode="",lv_role="",lv_tags="",lv_uuid="cqZnVQ-FUPG-btWz-3fff-cMX5-wViK-8MM3QY",lv_vdo_compression_state="",lv_vdo_index_state="",lv_vdo_operating_mode="",lv_when_full=""} 1
7+
lvm_lv_info{lv_active="",lv_allocation_policy="",lv_ancestors="",lv_attr="",lv_convert_lv="",lv_convert_lv_uuid="",lv_data_lv="",lv_data_lv_uuid="",lv_descendants="",lv_dm_path="",lv_full_ancestors="",lv_full_descendants="",lv_full_name="",lv_health_status="",lv_host="",lv_kernel_cache_policy="",lv_kernel_cache_settings="",lv_kernel_discards="",lv_kernel_metadata_format="",lv_kernel_read_ahead_bytes="",lv_layout="",lv_lockargs="",lv_metadata_lv="",lv_metadata_lv_uuid="",lv_mirror_log="",lv_mirror_log_uuid="",lv_modules="",lv_move_pv="",lv_move_pv_uuid="",lv_name="swap",lv_origin="",lv_origin_uuid="",lv_parent="",lv_path="",lv_permissions="",lv_pool_lv="",lv_pool_lv_uuid="",lv_raid_sync_action="",lv_raidintegritymode="",lv_role="",lv_tags="",lv_uuid="lGs7Tn-1Fyv-jMHN-aniN-r8qk-duEI-B9Xl9e",lv_vdo_compression_state="",lv_vdo_index_state="",lv_vdo_operating_mode="",lv_when_full=""} 1
8+
lvm_lv_info{lv_active="",lv_allocation_policy="",lv_ancestors="",lv_attr="",lv_convert_lv="",lv_convert_lv_uuid="",lv_data_lv="",lv_data_lv_uuid="",lv_descendants="",lv_dm_path="",lv_full_ancestors="",lv_full_descendants="",lv_full_name="",lv_health_status="",lv_host="",lv_kernel_cache_policy="",lv_kernel_cache_settings="",lv_kernel_discards="",lv_kernel_metadata_format="",lv_kernel_read_ahead_bytes="",lv_layout="",lv_lockargs="",lv_metadata_lv="",lv_metadata_lv_uuid="",lv_mirror_log="",lv_mirror_log_uuid="",lv_modules="",lv_move_pv="",lv_move_pv_uuid="",lv_name="vpool0",lv_origin="",lv_origin_uuid="",lv_parent="",lv_path="",lv_permissions="",lv_pool_lv="",lv_pool_lv_uuid="",lv_raid_sync_action="",lv_raidintegritymode="",lv_role="",lv_tags="",lv_uuid="dylifl-81AF-n2mG-kFKo-Ntxe-mnNQ-3eB7fF",lv_vdo_compression_state="online",lv_vdo_index_state="online",lv_vdo_operating_mode="normal",lv_when_full=""} 1
9+
# HELP lvm_lv_vdo_compression_state For vdo pools, whether compression is running
10+
# TYPE lvm_lv_vdo_compression_state gauge
11+
lvm_lv_vdo_compression_state{lv_uuid="5UyOrx-zG6u-w7cF-G2Ny-HmVd-0lsb-4J6lG2",lv_vdo_compression_state=""} 1
12+
lvm_lv_vdo_compression_state{lv_uuid="cqZnVQ-FUPG-btWz-3fff-cMX5-wViK-8MM3QY",lv_vdo_compression_state=""} 1
13+
lvm_lv_vdo_compression_state{lv_uuid="dylifl-81AF-n2mG-kFKo-Ntxe-mnNQ-3eB7fF",lv_vdo_compression_state="online"} 1
14+
lvm_lv_vdo_compression_state{lv_uuid="lGs7Tn-1Fyv-jMHN-aniN-r8qk-duEI-B9Xl9e",lv_vdo_compression_state=""} 1
15+
lvm_lv_vdo_compression_state{lv_uuid="r7Btja-nL3P-Co38-X2K4-DLWS-LMhT-LajcQa",lv_vdo_compression_state="online"} 1
16+
lvm_lv_vdo_compression_state{lv_uuid="tHnHR1-bjg8-ycJX-eyhR-heEp-L4qs-S510dO",lv_vdo_compression_state=""} 1
17+
# HELP lvm_lv_vdo_index_state For vdo pools, state of index for deduplication
18+
# TYPE lvm_lv_vdo_index_state gauge
19+
lvm_lv_vdo_index_state{lv_uuid="5UyOrx-zG6u-w7cF-G2Ny-HmVd-0lsb-4J6lG2",lv_vdo_index_state=""} 1
20+
lvm_lv_vdo_index_state{lv_uuid="cqZnVQ-FUPG-btWz-3fff-cMX5-wViK-8MM3QY",lv_vdo_index_state=""} 1
21+
lvm_lv_vdo_index_state{lv_uuid="dylifl-81AF-n2mG-kFKo-Ntxe-mnNQ-3eB7fF",lv_vdo_index_state="online"} 1
22+
lvm_lv_vdo_index_state{lv_uuid="lGs7Tn-1Fyv-jMHN-aniN-r8qk-duEI-B9Xl9e",lv_vdo_index_state=""} 1
23+
lvm_lv_vdo_index_state{lv_uuid="r7Btja-nL3P-Co38-X2K4-DLWS-LMhT-LajcQa",lv_vdo_index_state="online"} 1
24+
lvm_lv_vdo_index_state{lv_uuid="tHnHR1-bjg8-ycJX-eyhR-heEp-L4qs-S510dO",lv_vdo_index_state=""} 1
25+
# HELP lvm_lv_vdo_operating_mode For vdo pools, its current operating mode
26+
# TYPE lvm_lv_vdo_operating_mode gauge
27+
lvm_lv_vdo_operating_mode{lv_uuid="5UyOrx-zG6u-w7cF-G2Ny-HmVd-0lsb-4J6lG2",lv_vdo_operating_mode=""} 1
28+
lvm_lv_vdo_operating_mode{lv_uuid="cqZnVQ-FUPG-btWz-3fff-cMX5-wViK-8MM3QY",lv_vdo_operating_mode=""} 1
29+
lvm_lv_vdo_operating_mode{lv_uuid="dylifl-81AF-n2mG-kFKo-Ntxe-mnNQ-3eB7fF",lv_vdo_operating_mode="normal"} 1
30+
lvm_lv_vdo_operating_mode{lv_uuid="lGs7Tn-1Fyv-jMHN-aniN-r8qk-duEI-B9Xl9e",lv_vdo_operating_mode=""} 1
31+
lvm_lv_vdo_operating_mode{lv_uuid="r7Btja-nL3P-Co38-X2K4-DLWS-LMhT-LajcQa",lv_vdo_operating_mode="normal"} 1
32+
lvm_lv_vdo_operating_mode{lv_uuid="tHnHR1-bjg8-ycJX-eyhR-heEp-L4qs-S510dO",lv_vdo_operating_mode=""} 1
33+
# HELP lvm_lv_vdo_saving_percent For vdo pools, percentage of saved space
34+
# TYPE lvm_lv_vdo_saving_percent gauge
35+
lvm_lv_vdo_saving_percent{lv_uuid="dylifl-81AF-n2mG-kFKo-Ntxe-mnNQ-3eB7fF"} 55.37
36+
lvm_lv_vdo_saving_percent{lv_uuid="r7Btja-nL3P-Co38-X2K4-DLWS-LMhT-LajcQa"} 55.37
37+
# HELP lvm_lv_vdo_used_size_bytes For vdo pools, currently used space
38+
# TYPE lvm_lv_vdo_used_size_bytes gauge
39+
lvm_lv_vdo_used_size_bytes{lv_uuid="dylifl-81AF-n2mG-kFKo-Ntxe-mnNQ-3eB7fF"} 2.78899963904e+12
40+
lvm_lv_vdo_used_size_bytes{lv_uuid="r7Btja-nL3P-Co38-X2K4-DLWS-LMhT-LajcQa"} 2.78899963904e+12
41+
# HELP lvm_unknown_field_count Fields reported by LVM not recognized by exporter
42+
# TYPE lvm_unknown_field_count gauge
43+
lvm_unknown_field_count{details="",group="lv"} 0
44+
lvm_unknown_field_count{details="",group="pv"} 0
45+
lvm_unknown_field_count{details="",group="vg"} 0
46+
# HELP lvm_up Whether scrape was successful
47+
# TYPE lvm_up gauge
48+
lvm_up{status=""} 1

0 commit comments

Comments
 (0)