influxdb/tsdb/tsm1/metrics.go

247 lines
7.8 KiB
Go

package tsm1
import (
"sort"
"sync"
"github.com/prometheus/client_golang/prometheus"
)
// The following package variables act as singletons, to be shared by all Engine
// instantiations. This allows multiple Engines to be instantiated within the
// same process.
var (
bms *blockMetrics
mmu sync.RWMutex
)
// PrometheusCollectors returns all prometheus metrics for the tsm1 package.
func PrometheusCollectors() []prometheus.Collector {
mmu.RLock()
defer mmu.RUnlock()
var collectors []prometheus.Collector
if bms != nil {
collectors = append(collectors, bms.compactionMetrics.PrometheusCollectors()...)
collectors = append(collectors, bms.fileMetrics.PrometheusCollectors()...)
collectors = append(collectors, bms.cacheMetrics.PrometheusCollectors()...)
}
return collectors
}
// namespace is the leading part of all published metrics for the Storage service.
const namespace = "storage"
const compactionSubsystem = "compactions" // sub-system associated with metrics for compactions.
const fileStoreSubsystem = "tsm_files" // sub-system associated with metrics for TSM files.
const cacheSubsystem = "cache" // sub-system associated with metrics for the cache.
// blockMetrics are a set of metrics concerned with tracking data about block storage.
type blockMetrics struct {
labels prometheus.Labels
*compactionMetrics
*fileMetrics
*cacheMetrics
}
// newBlockMetrics initialises the prometheus metrics for the block subsystem.
func newBlockMetrics(labels prometheus.Labels) *blockMetrics {
return &blockMetrics{
labels: labels,
compactionMetrics: newCompactionMetrics(labels),
fileMetrics: newFileMetrics(labels),
cacheMetrics: newCacheMetrics(labels),
}
}
// PrometheusCollectors satisfies the prom.PrometheusCollector interface.
func (m *blockMetrics) PrometheusCollectors() []prometheus.Collector {
var metrics []prometheus.Collector
metrics = append(metrics, m.compactionMetrics.PrometheusCollectors()...)
metrics = append(metrics, m.fileMetrics.PrometheusCollectors()...)
metrics = append(metrics, m.cacheMetrics.PrometheusCollectors()...)
return metrics
}
// compactionMetrics are a set of metrics concerned with tracking data about compactions.
type compactionMetrics struct {
CompactionsActive *prometheus.GaugeVec
CompactionDuration *prometheus.HistogramVec
CompactionQueue *prometheus.GaugeVec
// The following metrics include a ``"status" = {ok, error}` label
Compactions *prometheus.CounterVec
}
// newCompactionMetrics initialises the prometheus metrics for compactions.
func newCompactionMetrics(labels prometheus.Labels) *compactionMetrics {
names := []string{"level"} // All compaction metrics have a `level` label.
for k := range labels {
names = append(names, k)
}
sort.Strings(names)
totalCompactionsNames := append(append([]string(nil), names...), []string{"reason", "status"}...)
sort.Strings(totalCompactionsNames)
return &compactionMetrics{
Compactions: prometheus.NewCounterVec(prometheus.CounterOpts{
Namespace: namespace,
Subsystem: compactionSubsystem,
Name: "total",
Help: "Number of times cache snapshotted or TSM compaction attempted.",
}, totalCompactionsNames),
CompactionsActive: prometheus.NewGaugeVec(prometheus.GaugeOpts{
Namespace: namespace,
Subsystem: compactionSubsystem,
Name: "active",
Help: "Number of active compactions.",
}, names),
CompactionDuration: prometheus.NewHistogramVec(prometheus.HistogramOpts{
Namespace: namespace,
Subsystem: compactionSubsystem,
Name: "duration_seconds",
Help: "Time taken for a successful compaction or snapshot.",
// 30 buckets spaced exponentially between 5s and ~53 minutes.
Buckets: prometheus.ExponentialBuckets(5.0, 1.25, 30),
}, names),
CompactionQueue: prometheus.NewGaugeVec(prometheus.GaugeOpts{
Namespace: namespace,
Subsystem: compactionSubsystem,
Name: "queued",
Help: "Number of queued compactions.",
}, names),
}
}
// PrometheusCollectors satisfies the prom.PrometheusCollector interface.
func (m *compactionMetrics) PrometheusCollectors() []prometheus.Collector {
return []prometheus.Collector{
m.Compactions,
m.CompactionsActive,
m.CompactionDuration,
m.CompactionQueue,
}
}
// fileMetrics are a set of metrics concerned with tracking data about compactions.
type fileMetrics struct {
DiskSize *prometheus.GaugeVec
Files *prometheus.GaugeVec
}
// newFileMetrics initialises the prometheus metrics for tracking files on disk.
func newFileMetrics(labels prometheus.Labels) *fileMetrics {
var names []string
for k := range labels {
names = append(names, k)
}
sort.Strings(names)
return &fileMetrics{
DiskSize: prometheus.NewGaugeVec(prometheus.GaugeOpts{
Namespace: namespace,
Subsystem: fileStoreSubsystem,
Name: "disk_bytes",
Help: "Number of bytes TSM files using on disk.",
}, names),
Files: prometheus.NewGaugeVec(prometheus.GaugeOpts{
Namespace: namespace,
Subsystem: fileStoreSubsystem,
Name: "total",
Help: "Number of files.",
}, names),
}
}
// PrometheusCollectors satisfies the prom.PrometheusCollector interface.
func (m *fileMetrics) PrometheusCollectors() []prometheus.Collector {
return []prometheus.Collector{
m.DiskSize,
m.Files,
}
}
// cacheMetrics are a set of metrics concerned with tracking data about the TSM Cache.
type cacheMetrics struct {
MemSize *prometheus.GaugeVec
DiskSize *prometheus.GaugeVec
SnapshotsActive *prometheus.GaugeVec
Age *prometheus.GaugeVec
SnapshottedBytes *prometheus.CounterVec
// The following metrics include a ``"status" = {ok, error, dropped}` label
WrittenBytes *prometheus.CounterVec
Writes *prometheus.CounterVec
}
// newCacheMetrics initialises the prometheus metrics for compactions.
func newCacheMetrics(labels prometheus.Labels) *cacheMetrics {
var names []string
for k := range labels {
names = append(names, k)
}
sort.Strings(names)
writeNames := append(append([]string(nil), names...), "status")
sort.Strings(writeNames)
return &cacheMetrics{
MemSize: prometheus.NewGaugeVec(prometheus.GaugeOpts{
Namespace: namespace,
Subsystem: cacheSubsystem,
Name: "inuse_bytes",
Help: "In-memory size of cache.",
}, names),
DiskSize: prometheus.NewGaugeVec(prometheus.GaugeOpts{
Namespace: namespace,
Subsystem: cacheSubsystem,
Name: "disk_bytes",
Help: "Number of bytes on disk used by snapshot data.",
}, names),
SnapshotsActive: prometheus.NewGaugeVec(prometheus.GaugeOpts{
Namespace: namespace,
Subsystem: cacheSubsystem,
Name: "snapshots_active",
Help: "Number of active concurrent snapshots (>1 when splitting the cache).",
}, names),
Age: prometheus.NewGaugeVec(prometheus.GaugeOpts{
Namespace: namespace,
Subsystem: cacheSubsystem,
Name: "age_seconds",
Help: "Age in seconds of the current cache (time since last snapshot or initialisation).",
}, names),
SnapshottedBytes: prometheus.NewCounterVec(prometheus.CounterOpts{
Namespace: namespace,
Subsystem: cacheSubsystem,
Name: "snapshot_bytes",
Help: "Number of bytes snapshotted.",
}, names),
WrittenBytes: prometheus.NewCounterVec(prometheus.CounterOpts{
Namespace: namespace,
Subsystem: cacheSubsystem,
Name: "written_bytes",
Help: "Number of bytes successfully written to the Cache.",
}, writeNames),
Writes: prometheus.NewCounterVec(prometheus.CounterOpts{
Namespace: namespace,
Subsystem: cacheSubsystem,
Name: "writes_total",
Help: "Number of writes to the Cache.",
}, writeNames),
}
}
// PrometheusCollectors satisfies the prom.PrometheusCollector interface.
func (m *cacheMetrics) PrometheusCollectors() []prometheus.Collector {
return []prometheus.Collector{
m.MemSize,
m.DiskSize,
m.SnapshotsActive,
m.Age,
m.SnapshottedBytes,
m.WrittenBytes,
m.Writes,
}
}