230 lines
7.5 KiB
Go
230 lines
7.5 KiB
Go
|
package tsi1
|
||
|
|
||
|
import (
|
||
|
"fmt"
|
||
|
"sort"
|
||
|
|
||
|
"github.com/prometheus/client_golang/prometheus"
|
||
|
)
|
||
|
|
||
|
// namespace is the leading part of all published metrics for the Storage service.
|
||
|
const namespace = "storage"
|
||
|
|
||
|
const cacheSubsystem = "tsi_cache" // sub-system associated with TSI index cache.
|
||
|
const partitionSubsystem = "tsi_index" // sub-system associated with the TSI index.
|
||
|
|
||
|
type cacheMetrics struct {
|
||
|
labels prometheus.Labels
|
||
|
Size *prometheus.GaugeVec // Size of the cache.
|
||
|
|
||
|
// These metrics have an extra label status = {"hit", "miss"}
|
||
|
Gets *prometheus.CounterVec // Number of times item retrieved.
|
||
|
Puts *prometheus.CounterVec // Number of times item inserted.
|
||
|
Deletes *prometheus.CounterVec // Number of times item deleted.
|
||
|
Evictions *prometheus.CounterVec // Number of times item deleted.
|
||
|
}
|
||
|
|
||
|
// newCacheMetrics initialises the prometheus metrics for tracking the Series File.
|
||
|
func newCacheMetrics(labels prometheus.Labels) *cacheMetrics {
|
||
|
var names []string
|
||
|
for k := range labels {
|
||
|
names = append(names, k)
|
||
|
}
|
||
|
sort.Strings(names)
|
||
|
|
||
|
statusNames := append(names, "status")
|
||
|
sort.Strings(statusNames)
|
||
|
|
||
|
return &cacheMetrics{
|
||
|
labels: labels,
|
||
|
Size: prometheus.NewGaugeVec(prometheus.GaugeOpts{
|
||
|
Namespace: namespace,
|
||
|
Subsystem: cacheSubsystem,
|
||
|
Name: "size",
|
||
|
Help: "Number of items residing in the cache.",
|
||
|
}, names),
|
||
|
Gets: prometheus.NewCounterVec(prometheus.CounterOpts{
|
||
|
Namespace: namespace,
|
||
|
Subsystem: cacheSubsystem,
|
||
|
Name: "get_total",
|
||
|
Help: "Total number of gets on cache.",
|
||
|
}, statusNames),
|
||
|
Puts: prometheus.NewCounterVec(prometheus.CounterOpts{
|
||
|
Namespace: namespace,
|
||
|
Subsystem: cacheSubsystem,
|
||
|
Name: "put_total",
|
||
|
Help: "Total number of insertions in cache.",
|
||
|
}, statusNames),
|
||
|
Deletes: prometheus.NewCounterVec(prometheus.CounterOpts{
|
||
|
Namespace: namespace,
|
||
|
Subsystem: cacheSubsystem,
|
||
|
Name: "deletes_total",
|
||
|
Help: "Total number of deletions in cache.",
|
||
|
}, statusNames),
|
||
|
Evictions: prometheus.NewCounterVec(prometheus.CounterOpts{
|
||
|
Namespace: namespace,
|
||
|
Subsystem: cacheSubsystem,
|
||
|
Name: "evictions_total",
|
||
|
Help: "Total number of cache evictions.",
|
||
|
}, names),
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Labels returns a copy of labels for use with RHH metrics.
|
||
|
func (m *cacheMetrics) Labels() prometheus.Labels {
|
||
|
l := make(map[string]string, len(m.labels))
|
||
|
for k, v := range m.labels {
|
||
|
l[k] = v
|
||
|
}
|
||
|
return l
|
||
|
}
|
||
|
|
||
|
// PrometheusCollectors satisfies the prom.PrometheusCollector interface.
|
||
|
func (m *cacheMetrics) PrometheusCollectors() []prometheus.Collector {
|
||
|
return []prometheus.Collector{
|
||
|
m.Size,
|
||
|
m.Gets,
|
||
|
m.Puts,
|
||
|
m.Deletes,
|
||
|
m.Evictions,
|
||
|
}
|
||
|
}
|
||
|
|
||
|
type partitionMetrics struct {
|
||
|
labels prometheus.Labels
|
||
|
SeriesCreated *prometheus.CounterVec // Number of series created in Series File.
|
||
|
SeriesCreatedDuration *prometheus.HistogramVec // Distribution of time to insert series.
|
||
|
SeriesDropped *prometheus.CounterVec // Number of series removed from index.
|
||
|
Series *prometheus.GaugeVec // Number of series.
|
||
|
Measurements *prometheus.GaugeVec // Number of measurements.
|
||
|
DiskSize *prometheus.GaugeVec // Size occupied on disk.
|
||
|
|
||
|
// This metrics has a "type" = {index, log}
|
||
|
FilesTotal *prometheus.GaugeVec // files on disk.
|
||
|
|
||
|
// This metric has a "level" metric.
|
||
|
CompactionsActive *prometheus.GaugeVec // Number of active compactions.
|
||
|
|
||
|
// These metrics have a "level" metric.
|
||
|
// The following metrics include a "status" = {ok, error}` label
|
||
|
CompactionDuration *prometheus.HistogramVec // Duration of compactions.
|
||
|
Compactions *prometheus.CounterVec // Total number of compactions.
|
||
|
}
|
||
|
|
||
|
// newPartitionMetrics initialises the prometheus metrics for tracking the TSI partitions.
|
||
|
func newPartitionMetrics(labels prometheus.Labels) *partitionMetrics {
|
||
|
names := []string{"partition_id"} // All metrics have a partition
|
||
|
for k := range labels {
|
||
|
names = append(names, k)
|
||
|
}
|
||
|
sort.Strings(names)
|
||
|
|
||
|
// type = {"index", "log"}
|
||
|
fileNames := append(names, "type")
|
||
|
sort.Strings(fileNames)
|
||
|
|
||
|
// level = [0, 7]
|
||
|
compactionNames := append(names, "level")
|
||
|
sort.Strings(compactionNames)
|
||
|
|
||
|
// status = {"ok", "error"}
|
||
|
attemptedCompactionNames := append(compactionNames, "status")
|
||
|
sort.Strings(attemptedCompactionNames)
|
||
|
|
||
|
return &partitionMetrics{
|
||
|
labels: labels,
|
||
|
SeriesCreated: prometheus.NewCounterVec(prometheus.CounterOpts{
|
||
|
Namespace: namespace,
|
||
|
Subsystem: partitionSubsystem,
|
||
|
Name: "series_created",
|
||
|
Help: "Number of series created in the partition.",
|
||
|
}, names),
|
||
|
SeriesCreatedDuration: prometheus.NewHistogramVec(prometheus.HistogramOpts{
|
||
|
Namespace: namespace,
|
||
|
Subsystem: partitionSubsystem,
|
||
|
Name: "series_created_duration_ns",
|
||
|
Help: "Time taken in nanosecond to create single series.",
|
||
|
// 30 buckets spaced exponentially between 100ns and ~19 us.
|
||
|
Buckets: prometheus.ExponentialBuckets(100.0, 1.2, 30),
|
||
|
}, names),
|
||
|
SeriesDropped: prometheus.NewCounterVec(prometheus.CounterOpts{
|
||
|
Namespace: namespace,
|
||
|
Subsystem: partitionSubsystem,
|
||
|
Name: "series_dropped",
|
||
|
Help: "Number of series dropped from the partition.",
|
||
|
}, names),
|
||
|
Series: prometheus.NewGaugeVec(prometheus.GaugeOpts{
|
||
|
Namespace: namespace,
|
||
|
Subsystem: partitionSubsystem,
|
||
|
Name: "series_total",
|
||
|
Help: "Number of series in the partition.",
|
||
|
}, names),
|
||
|
Measurements: prometheus.NewGaugeVec(prometheus.GaugeOpts{
|
||
|
Namespace: namespace,
|
||
|
Subsystem: partitionSubsystem,
|
||
|
Name: "measurements_total",
|
||
|
Help: "Number of series in the partition.",
|
||
|
}, names),
|
||
|
FilesTotal: prometheus.NewGaugeVec(prometheus.GaugeOpts{
|
||
|
Namespace: namespace,
|
||
|
Subsystem: partitionSubsystem,
|
||
|
Name: "files_total",
|
||
|
Help: "Number of files in the partition.",
|
||
|
}, fileNames),
|
||
|
DiskSize: prometheus.NewGaugeVec(prometheus.GaugeOpts{
|
||
|
Namespace: namespace,
|
||
|
Subsystem: partitionSubsystem,
|
||
|
Name: "disk_bytes",
|
||
|
Help: "Number of bytes TSI partition is using on disk.",
|
||
|
}, names),
|
||
|
CompactionsActive: prometheus.NewGaugeVec(prometheus.GaugeOpts{
|
||
|
Namespace: namespace,
|
||
|
Subsystem: partitionSubsystem,
|
||
|
Name: "compactions_active",
|
||
|
Help: "Number of active partition compactions.",
|
||
|
}, compactionNames),
|
||
|
CompactionDuration: prometheus.NewHistogramVec(prometheus.HistogramOpts{
|
||
|
Namespace: namespace,
|
||
|
Subsystem: partitionSubsystem,
|
||
|
Name: "compactions_duration_seconds",
|
||
|
Help: "Time taken for a successful compaction of partition.",
|
||
|
// 30 buckets spaced exponentially between 1s and ~10 minutes.
|
||
|
Buckets: prometheus.ExponentialBuckets(1.0, 1.25, 30),
|
||
|
}, compactionNames),
|
||
|
Compactions: prometheus.NewCounterVec(prometheus.CounterOpts{
|
||
|
Namespace: namespace,
|
||
|
Subsystem: partitionSubsystem,
|
||
|
Name: "compactions",
|
||
|
Help: "Number of compactions.",
|
||
|
}, attemptedCompactionNames),
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Labels returns a copy of labels for use with TSI partition metrics.
|
||
|
func (m *partitionMetrics) Labels(partition int) prometheus.Labels {
|
||
|
l := make(map[string]string, len(m.labels))
|
||
|
for k, v := range m.labels {
|
||
|
l[k] = v
|
||
|
}
|
||
|
|
||
|
// N.B all series file metrics include the partition. So it's included here.
|
||
|
l["partition_id"] = fmt.Sprint(partition)
|
||
|
return l
|
||
|
}
|
||
|
|
||
|
// PrometheusCollectors satisfies the prom.PrometheusCollector interface.
|
||
|
func (m *partitionMetrics) PrometheusCollectors() []prometheus.Collector {
|
||
|
return []prometheus.Collector{
|
||
|
m.SeriesCreated,
|
||
|
m.SeriesCreatedDuration,
|
||
|
m.SeriesDropped,
|
||
|
m.Series,
|
||
|
m.Measurements,
|
||
|
m.FilesTotal,
|
||
|
m.DiskSize,
|
||
|
m.CompactionsActive,
|
||
|
m.CompactionDuration,
|
||
|
m.Compactions,
|
||
|
}
|
||
|
}
|