Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 46 additions & 13 deletions cmd/collector.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,29 @@ func (f *ProviderFactory) CreateLogMetricProvider(
)
}

// CreateLabelMetricProvider builds an info-metric provider that emits a
// constant 1 and exposes the string at jsonKey as labelName (e.g. a GUID).
func (f *ProviderFactory) CreateLabelMetricProvider(
fqName string,
help string,
jsonKey string,
labelName string,
) pkg.MetricProvider {
labels := make([]string, 0, len(f.defaultLabels)+1)
labels = append(labels, f.defaultLabels...)
labels = append(labels, labelName)

return pkg.NewLabelMetricProvider(
prometheus.NewDesc(
fqName,
help,
labels,
nil,
),
jsonKey,
)
}

func (f *ProviderFactory) CreateInfoMetricProvider(
fqName string,
help string,
Expand Down Expand Up @@ -155,13 +178,15 @@ func newNvmeCollector(collectorStates map[string]bool) prometheus.Collector {

counterValueFactory.CreateLogMetricProvider(
"nvme_data_units_read",
"Total number of 512-byte data units read from the NVMe device by the host",
"Number of 512-byte data units read by the host. Per the NVMe spec this is "+
"reported in thousands and rounded up, so bytes read = value * 512000 (1000 * 512)",
"data_units_read",
),

counterValueFactory.CreateLogMetricProvider(
"nvme_data_units_written",
"Total number of 512-byte data units written to the NVMe device by the host",
"Number of 512-byte data units written by the host. Per the NVMe spec this is "+
"reported in thousands and rounded up, so bytes written = value * 512000 (1000 * 512)",
"data_units_written",
),

Expand Down Expand Up @@ -254,42 +279,48 @@ func newNvmeCollector(collectorStates map[string]bool) prometheus.Collector {
ocpLogMetricProviders := []pkg.MetricProvider{
counterValueFactory.CreateLogMetricProvider(
"nvme_physical_media_units_written_hi",
"Physical media units written to the device (high 64 bits). Unit size is 1000h sector size",
"Bytes written to the physical media, high 64 bits of a 128-bit byte counter "+
"(per OCP spec the value is in bytes; hi is ~always 0 below ~18 EB)",
"Physical media units written.hi",
),
counterValueFactory.CreateLogMetricProvider(
"nvme_physical_media_units_written_lo",
"Physical media units written to the device (low 64 bits). Unit size is 1000h sector size",
"Bytes written to the physical media, low 64 bits of a 128-bit byte counter "+
"(per OCP spec the value is in bytes)",
"Physical media units written.lo",
),
counterValueFactory.CreateLogMetricProvider(
"nvme_physical_media_units_read_hi",
"Physical media units read from the device (high 64 bits). Unit size is 1000h sector size",
"Bytes read from the physical media, high 64 bits of a 128-bit byte counter "+
"(per OCP spec the value is in bytes; hi is ~always 0 below ~18 EB)",
"Physical media units read.hi",
),
counterValueFactory.CreateLogMetricProvider(
"nvme_physical_media_units_read_lo",
"Physical media units read from the device (low 64 bits). Unit size is 1000h sector size",
"Bytes read from the physical media, low 64 bits of a 128-bit byte counter "+
"(per OCP spec the value is in bytes)",
"Physical media units read.lo",
),
counterValueFactory.CreateLogMetricProvider(
"nvme_bad_user_nand_blocks_raw",
"Raw count of user NAND blocks that have been retired due to errors",
"Bad user nand blocks - Raw",
),
counterValueFactory.CreateLogMetricProvider(
gaugeValueFactory.CreateLogMetricProvider(
"nvme_bad_user_nand_blocks_normalized",
"Normalized value (0-100) of bad user NAND blocks relative to the maximum allowed",
"Normalized value (0-100) of bad user NAND blocks relative to the maximum allowed. "+
"Gauge: this value decreases as blocks are retired, so it is not a counter",
"Bad user nand blocks - Normalized",
),
counterValueFactory.CreateLogMetricProvider(
"nvme_bad_system_nand_blocks_raw",
"Raw count of system area NAND blocks that have been retired due to errors",
"Bad system nand blocks - Raw",
),
counterValueFactory.CreateLogMetricProvider(
gaugeValueFactory.CreateLogMetricProvider(
"nvme_bad_system_nand_blocks_normalized",
"Normalized value (0-100) of bad system NAND blocks relative to the maximum allowed",
"Normalized value (0-100) of bad system NAND blocks relative to the maximum allowed. "+
"Gauge: this value decreases as blocks are retired, so it is not a counter",
"Bad system nand blocks - Normalized",
),
counterValueFactory.CreateLogMetricProvider(
Expand Down Expand Up @@ -397,10 +428,12 @@ func newNvmeCollector(collectorStates map[string]bool) prometheus.Collector {
"Version number of the OCP SMART log page specification",
"Log page version",
),
gaugeValueFactory.CreateLogMetricProvider(
"nvme_log_page_guid",
"GUID (Globally Unique Identifier) of the OCP SMART log page",
gaugeValueFactory.CreateLabelMetricProvider(
"nvme_log_page_guid_info",
"OCP SMART log page GUID, exposed as the 'guid' label on a constant-1 info "+
"metric (it is a 128-bit identifier, not a meaningful number)",
"Log page GUID",
"guid",
),
gaugeValueFactory.CreateLogMetricProvider(
"nvme_errata_version_field",
Expand Down
31 changes: 31 additions & 0 deletions pkg/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,13 @@ type MetricProvider struct {
// jsonKey is the string key that the object needs to access
// in the device JSON to fetch the metric float64 value
jsonKey string

// valueAsLabel, when true, makes GetMetric emit a constant gauge of 1
// and attach the string found at jsonKey as the last label instead of
// parsing it as a float. This is the Prometheus "info metric" pattern,
// used for identifiers/strings (e.g. a 128-bit GUID) that have no
// meaningful numeric value.
valueAsLabel bool
}

// NewMetricProvider is the constructor for MetricProvider objects.
Expand All @@ -33,6 +40,21 @@ func NewMetricProvider(
}
}

// NewLabelMetricProvider builds an "info metric" provider: it emits a constant
// gauge of 1 and attaches the string value at jsonKey as an extra label. Use it
// for identifiers/strings that cannot be represented as a float.
func NewLabelMetricProvider(
desc *prometheus.Desc,
jsonKey string,
) MetricProvider {
return MetricProvider{
Desc: desc,
ValueType: prometheus.GaugeValue,
jsonKey: jsonKey,
valueAsLabel: true,
}
}

// GetMetric computes the metric from the
// data in JSON form.
func (ip MetricProvider) GetMetric(
Expand All @@ -53,6 +75,15 @@ func (ip MetricProvider) GetMetric(
return nil
}

// Info-metric mode: emit a constant 1 with the string value as an extra label.
if ip.valueAsLabel {
labelValues := make([]string, 0, len(labels)+1)
labelValues = append(labelValues, labels...)
labelValues = append(labelValues, result.String())

return prometheus.MustNewConstMetric(ip.Desc, ip.ValueType, 1, labelValues...)
}

// Handle both scalar values (v2.8) and object values (v2.11+)
// In v2.11+, some fields like critical_warning are objects with a "value" field
var value float64
Expand Down
Loading
Loading