From bd100182b2b9f4c2a632ec98f96d5d1a152a09f9 Mon Sep 17 00:00:00 2001 From: Krasi Georgiev Date: Wed, 21 Nov 2018 12:57:32 +0200 Subject: [PATCH] added tsdb/head mint maxt metrics (#4888) added the head metrics with the correct suffix. Signed-off-by: Krasi Georgiev --- storage/tsdb/tsdb.go | 42 +++++++++++++++++++++ storage/tsdb/tsdb_export_test.go | 21 +++++++++++ storage/tsdb/tsdb_test.go | 63 ++++++++++++++++++++++++++++++++ 3 files changed, 126 insertions(+) create mode 100644 storage/tsdb/tsdb_export_test.go create mode 100644 storage/tsdb/tsdb_test.go diff --git a/storage/tsdb/tsdb.go b/storage/tsdb/tsdb.go index d04a47a12..c0973342d 100644 --- a/storage/tsdb/tsdb.go +++ b/storage/tsdb/tsdb.go @@ -124,6 +124,46 @@ type Options struct { NoLockfile bool } +var ( + startTime prometheus.GaugeFunc + headMaxTime prometheus.GaugeFunc + headMinTime prometheus.GaugeFunc +) + +func registerMetrics(db *tsdb.DB, r prometheus.Registerer) { + + startTime = prometheus.NewGaugeFunc(prometheus.GaugeOpts{ + Name: "prometheus_tsdb_lowest_timestamp_seconds", + Help: "Lowest timestamp value stored in the database.", + }, func() float64 { + bb := db.Blocks() + if len(bb) == 0 { + return float64(db.Head().MinTime()) / 1000 + } + return float64(db.Blocks()[0].Meta().MinTime) / 1000 + }) + headMinTime = prometheus.NewGaugeFunc(prometheus.GaugeOpts{ + Name: "prometheus_tsdb_head_min_time_seconds", + Help: "Minimum time bound of the head block.", + }, func() float64 { + return float64(db.Head().MinTime()) / 1000 + }) + headMaxTime = prometheus.NewGaugeFunc(prometheus.GaugeOpts{ + Name: "prometheus_tsdb_head_max_time_seconds", + Help: "Maximum timestamp of the head block.", + }, func() float64 { + return float64(db.Head().MaxTime()) / 1000 + }) + + if r != nil { + r.MustRegister( + startTime, + headMaxTime, + headMinTime, + ) + } +} + // Open returns a new storage backed by a TSDB database that is configured for Prometheus. func Open(path string, l log.Logger, r prometheus.Registerer, opts *Options) (*tsdb.DB, error) { if opts.MinBlockDuration > opts.MaxBlockDuration { @@ -149,6 +189,8 @@ func Open(path string, l log.Logger, r prometheus.Registerer, opts *Options) (*t if err != nil { return nil, err } + registerMetrics(db, r) + return db, nil } diff --git a/storage/tsdb/tsdb_export_test.go b/storage/tsdb/tsdb_export_test.go new file mode 100644 index 000000000..5821e9425 --- /dev/null +++ b/storage/tsdb/tsdb_export_test.go @@ -0,0 +1,21 @@ +// Copyright 2017 The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package tsdb + +// Export the internal variables only for tests. +var ( + StartTime = &startTime + HeadMaxTime = &headMaxTime + HeadMinTime = &headMinTime +) diff --git a/storage/tsdb/tsdb_test.go b/storage/tsdb/tsdb_test.go new file mode 100644 index 000000000..85a8e43a9 --- /dev/null +++ b/storage/tsdb/tsdb_test.go @@ -0,0 +1,63 @@ +// Copyright 2017 The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package tsdb_test + +import ( + "testing" + + dto "github.com/prometheus/client_model/go" + "github.com/prometheus/common/model" + "github.com/prometheus/prometheus/pkg/labels" + "github.com/prometheus/prometheus/storage/tsdb" + "github.com/prometheus/prometheus/util/testutil" +) + +func TestMetrics(t *testing.T) { + db := testutil.NewStorage(t) + defer db.Close() + + metrics := &dto.Metric{} + startTime := *tsdb.StartTime + headMinTime := *tsdb.HeadMinTime + headMaxTime := *tsdb.HeadMaxTime + + // Check initial values. + testutil.Ok(t, startTime.Write(metrics)) + testutil.Equals(t, float64(model.Latest)/1000, metrics.Gauge.GetValue()) + + testutil.Ok(t, headMinTime.Write(metrics)) + testutil.Equals(t, float64(model.Latest)/1000, metrics.Gauge.GetValue()) + + testutil.Ok(t, headMaxTime.Write(metrics)) + testutil.Equals(t, float64(model.Earliest)/1000, metrics.Gauge.GetValue()) + + app, err := db.Appender() + testutil.Ok(t, err) + + app.Add(labels.FromStrings(model.MetricNameLabel, "a"), 1, 1) + app.Add(labels.FromStrings(model.MetricNameLabel, "a"), 2, 1) + app.Add(labels.FromStrings(model.MetricNameLabel, "a"), 3, 1) + testutil.Ok(t, app.Commit()) + + // Check after adding some samples. + testutil.Ok(t, startTime.Write(metrics)) + testutil.Equals(t, 0.001, metrics.Gauge.GetValue()) + + testutil.Ok(t, headMinTime.Write(metrics)) + testutil.Equals(t, 0.001, metrics.Gauge.GetValue()) + + testutil.Ok(t, headMaxTime.Write(metrics)) + testutil.Equals(t, 0.003, metrics.Gauge.GetValue()) + +}