mirror of
https://github.com/prometheus/prometheus.git
synced 2025-08-07 06:37:17 +02:00
Addressed Brian's comments, moved metrics to main.go
Signed-off-by: Bartlomiej Plotka <bwplotka@gmail.com>
This commit is contained in:
parent
5d84e5d895
commit
59c9d6ef45
@ -666,15 +666,16 @@ func main() {
|
|||||||
return errors.New("flag 'storage.tsdb.wal-segment-size' must be set between 10MB and 256MB")
|
return errors.New("flag 'storage.tsdb.wal-segment-size' must be set between 10MB and 256MB")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
db, err := tsdb.Open(
|
db, err := openDBWithMetrics(
|
||||||
cfg.localStoragePath,
|
cfg.localStoragePath,
|
||||||
log.With(logger, "component", "tsdb"),
|
logger,
|
||||||
prometheus.DefaultRegisterer,
|
prometheus.DefaultRegisterer,
|
||||||
&opts,
|
&opts,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrapf(err, "opening storage failed")
|
return errors.Wrapf(err, "opening storage failed")
|
||||||
}
|
}
|
||||||
|
|
||||||
level.Info(logger).Log("fs_type", prom_runtime.Statfs(cfg.localStoragePath))
|
level.Info(logger).Log("fs_type", prom_runtime.Statfs(cfg.localStoragePath))
|
||||||
level.Info(logger).Log("msg", "TSDB started")
|
level.Info(logger).Log("msg", "TSDB started")
|
||||||
level.Debug(logger).Log("msg", "TSDB options",
|
level.Debug(logger).Log("msg", "TSDB options",
|
||||||
@ -745,6 +746,40 @@ func main() {
|
|||||||
level.Info(logger).Log("msg", "See you next time!")
|
level.Info(logger).Log("msg", "See you next time!")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func openDBWithMetrics(dir string, logger log.Logger, reg prometheus.Registerer, opts *tsdb.Options) (*tsdb.DB, error) {
|
||||||
|
db, err := tsdb.Open(
|
||||||
|
dir,
|
||||||
|
log.With(logger, "component", "tsdb"),
|
||||||
|
reg,
|
||||||
|
opts,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
reg.MustRegister(
|
||||||
|
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)
|
||||||
|
}), 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) }),
|
||||||
|
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) }),
|
||||||
|
)
|
||||||
|
|
||||||
|
return db, nil
|
||||||
|
}
|
||||||
|
|
||||||
func reloadConfig(filename string, logger log.Logger, rls ...func(*config.Config) error) (err error) {
|
func reloadConfig(filename string, logger log.Logger, rls ...func(*config.Config) error) (err error) {
|
||||||
level.Info(logger).Log("msg", "Loading configuration file", "filename", filename)
|
level.Info(logger).Log("msg", "Loading configuration file", "filename", filename)
|
||||||
|
|
||||||
|
@ -17,6 +17,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"math"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
@ -24,6 +25,9 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/go-kit/kit/log"
|
||||||
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
|
"github.com/prometheus/common/model"
|
||||||
"github.com/prometheus/prometheus/notifier"
|
"github.com/prometheus/prometheus/notifier"
|
||||||
"github.com/prometheus/prometheus/pkg/labels"
|
"github.com/prometheus/prometheus/pkg/labels"
|
||||||
"github.com/prometheus/prometheus/rules"
|
"github.com/prometheus/prometheus/rules"
|
||||||
@ -232,3 +236,71 @@ func TestWALSegmentSizeBounds(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestTimeMetrics(t *testing.T) {
|
||||||
|
tmpDir, err := ioutil.TempDir("", "time_metrics_e2e")
|
||||||
|
testutil.Ok(t, err)
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
testutil.Ok(t, os.RemoveAll(tmpDir))
|
||||||
|
}()
|
||||||
|
|
||||||
|
reg := prometheus.NewRegistry()
|
||||||
|
db, err := openDBWithMetrics(tmpDir, log.NewNopLogger(), reg, nil)
|
||||||
|
testutil.Ok(t, err)
|
||||||
|
defer func() {
|
||||||
|
testutil.Ok(t, db.Close())
|
||||||
|
}()
|
||||||
|
|
||||||
|
// Check initial values.
|
||||||
|
testutil.Equals(t, map[string]float64{
|
||||||
|
"prometheus_tsdb_lowest_timestamp_seconds": float64(math.MaxInt64) / 1000,
|
||||||
|
"prometheus_tsdb_head_min_time_seconds": float64(math.MaxInt64) / 1000,
|
||||||
|
"prometheus_tsdb_head_max_time_seconds": float64(math.MinInt64) / 1000,
|
||||||
|
}, getCurrentGaugeValuesFor(t, reg,
|
||||||
|
"prometheus_tsdb_lowest_timestamp_seconds",
|
||||||
|
"prometheus_tsdb_head_min_time_seconds",
|
||||||
|
"prometheus_tsdb_head_max_time_seconds",
|
||||||
|
))
|
||||||
|
|
||||||
|
app := db.Appender()
|
||||||
|
_, err = app.Add(labels.FromStrings(model.MetricNameLabel, "a"), 1000, 1)
|
||||||
|
testutil.Ok(t, err)
|
||||||
|
_, err = app.Add(labels.FromStrings(model.MetricNameLabel, "a"), 2000, 1)
|
||||||
|
testutil.Ok(t, err)
|
||||||
|
_, err = app.Add(labels.FromStrings(model.MetricNameLabel, "a"), 3000, 1)
|
||||||
|
testutil.Ok(t, err)
|
||||||
|
testutil.Ok(t, app.Commit())
|
||||||
|
|
||||||
|
testutil.Equals(t, map[string]float64{
|
||||||
|
"prometheus_tsdb_lowest_timestamp_seconds": 1.0,
|
||||||
|
"prometheus_tsdb_head_min_time_seconds": 1.0,
|
||||||
|
"prometheus_tsdb_head_max_time_seconds": 3.0,
|
||||||
|
}, getCurrentGaugeValuesFor(t, reg,
|
||||||
|
"prometheus_tsdb_lowest_timestamp_seconds",
|
||||||
|
"prometheus_tsdb_head_min_time_seconds",
|
||||||
|
"prometheus_tsdb_head_max_time_seconds",
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
func getCurrentGaugeValuesFor(t *testing.T, reg prometheus.Gatherer, metricNames ...string) map[string]float64 {
|
||||||
|
f, err := reg.Gather()
|
||||||
|
testutil.Ok(t, err)
|
||||||
|
|
||||||
|
res := make(map[string]float64, len(metricNames))
|
||||||
|
for _, g := range f {
|
||||||
|
for _, m := range metricNames {
|
||||||
|
if g.GetName() != m {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
testutil.Equals(t, 1, len(g.GetMetric()))
|
||||||
|
if _, ok := res[m]; ok {
|
||||||
|
t.Error("expected only one metric family for", m)
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
res[m] = *g.GetMetric()[0].GetGauge().Value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
@ -15,6 +15,7 @@ package storage
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
"github.com/prometheus/common/model"
|
"github.com/prometheus/common/model"
|
||||||
"github.com/prometheus/prometheus/pkg/labels"
|
"github.com/prometheus/prometheus/pkg/labels"
|
||||||
"github.com/prometheus/prometheus/storage"
|
"github.com/prometheus/prometheus/storage"
|
||||||
@ -33,7 +34,7 @@ func TestSelectSorted(t *testing.T) {
|
|||||||
|
|
||||||
priStorage := teststorage.New(t)
|
priStorage := teststorage.New(t)
|
||||||
defer priStorage.Close()
|
defer priStorage.Close()
|
||||||
app1, _ := priStorage.Appender()
|
app1 := priStorage.Appender()
|
||||||
app1.Add(inputLabel, 0, 0)
|
app1.Add(inputLabel, 0, 0)
|
||||||
inputTotalSize++
|
inputTotalSize++
|
||||||
app1.Add(inputLabel, 1000, 1)
|
app1.Add(inputLabel, 1000, 1)
|
||||||
@ -45,7 +46,7 @@ func TestSelectSorted(t *testing.T) {
|
|||||||
|
|
||||||
remoteStorage1 := teststorage.New(t)
|
remoteStorage1 := teststorage.New(t)
|
||||||
defer remoteStorage1.Close()
|
defer remoteStorage1.Close()
|
||||||
app2, _ := remoteStorage1.Appender()
|
app2 := remoteStorage1.Appender()
|
||||||
app2.Add(inputLabel, 3000, 3)
|
app2.Add(inputLabel, 3000, 3)
|
||||||
inputTotalSize++
|
inputTotalSize++
|
||||||
app2.Add(inputLabel, 4000, 4)
|
app2.Add(inputLabel, 4000, 4)
|
||||||
@ -58,7 +59,7 @@ func TestSelectSorted(t *testing.T) {
|
|||||||
remoteStorage2 := teststorage.New(t)
|
remoteStorage2 := teststorage.New(t)
|
||||||
defer remoteStorage2.Close()
|
defer remoteStorage2.Close()
|
||||||
|
|
||||||
app3, _ := remoteStorage2.Appender()
|
app3 := remoteStorage2.Appender()
|
||||||
app3.Add(inputLabel, 6000, 6)
|
app3.Add(inputLabel, 6000, 6)
|
||||||
inputTotalSize++
|
inputTotalSize++
|
||||||
app3.Add(inputLabel, 7000, 7)
|
app3.Add(inputLabel, 7000, 7)
|
||||||
|
@ -86,7 +86,7 @@ type Iterator interface {
|
|||||||
// Before the iterator has advanced At behaviour is unspecified.
|
// Before the iterator has advanced At behaviour is unspecified.
|
||||||
At() (int64, float64)
|
At() (int64, float64)
|
||||||
// Err returns the current error. It should be used only after iterator is
|
// Err returns the current error. It should be used only after iterator is
|
||||||
// exhausted, so `Next` or `Seek` returns false.
|
// exhausted, that is `Next` or `Seek` returns false.
|
||||||
Err() error
|
Err() error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
33
tsdb/db.go
33
tsdb/db.go
@ -66,7 +66,6 @@ func DefaultOptions() *Options {
|
|||||||
AllowOverlappingBlocks: false,
|
AllowOverlappingBlocks: false,
|
||||||
WALCompression: false,
|
WALCompression: false,
|
||||||
StripeSize: DefaultStripeSize,
|
StripeSize: DefaultStripeSize,
|
||||||
ConvertTimeToSecondsFn: func(i int64) float64 { return float64(i / 1000) },
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -113,9 +112,6 @@ type Options struct {
|
|||||||
// Unit agnostic as long as unit is consistent with MinBlockDuration and RetentionDuration.
|
// Unit agnostic as long as unit is consistent with MinBlockDuration and RetentionDuration.
|
||||||
// Typically it is in milliseconds.
|
// Typically it is in milliseconds.
|
||||||
MaxBlockDuration int64
|
MaxBlockDuration int64
|
||||||
|
|
||||||
// ConvertTimeToSecondsFn function is used for time based values to convert to seconds for metric purposes.
|
|
||||||
ConvertTimeToSecondsFn func(int64) float64
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// DB handles reads and writes of time series falling into
|
// DB handles reads and writes of time series falling into
|
||||||
@ -166,12 +162,9 @@ type dbMetrics struct {
|
|||||||
tombCleanTimer prometheus.Histogram
|
tombCleanTimer prometheus.Histogram
|
||||||
blocksBytes prometheus.Gauge
|
blocksBytes prometheus.Gauge
|
||||||
maxBytes prometheus.Gauge
|
maxBytes prometheus.Gauge
|
||||||
minTime prometheus.GaugeFunc
|
|
||||||
headMaxTime prometheus.GaugeFunc
|
|
||||||
headMinTime prometheus.GaugeFunc
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func newDBMetrics(db *DB, r prometheus.Registerer, convToSecondsFn func(int64) float64) *dbMetrics {
|
func newDBMetrics(db *DB, r prometheus.Registerer) *dbMetrics {
|
||||||
m := &dbMetrics{}
|
m := &dbMetrics{}
|
||||||
|
|
||||||
m.loadedBlocks = prometheus.NewGaugeFunc(prometheus.GaugeOpts{
|
m.loadedBlocks = prometheus.NewGaugeFunc(prometheus.GaugeOpts{
|
||||||
@ -247,25 +240,6 @@ func newDBMetrics(db *DB, r prometheus.Registerer, convToSecondsFn func(int64) f
|
|||||||
Help: "The number of times that blocks were deleted because the maximum number of bytes was exceeded.",
|
Help: "The number of times that blocks were deleted because the maximum number of bytes was exceeded.",
|
||||||
})
|
})
|
||||||
|
|
||||||
// Unit agnostic metrics.
|
|
||||||
m.minTime = 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 convToSecondsFn(db.Head().MinTime())
|
|
||||||
}
|
|
||||||
return convToSecondsFn(db.Blocks()[0].Meta().MinTime)
|
|
||||||
})
|
|
||||||
m.headMinTime = prometheus.NewGaugeFunc(prometheus.GaugeOpts{
|
|
||||||
Name: "prometheus_tsdb_head_min_time_seconds",
|
|
||||||
Help: "Minimum time bound of the head block.",
|
|
||||||
}, func() float64 { return convToSecondsFn(db.Head().MinTime()) })
|
|
||||||
m.headMaxTime = prometheus.NewGaugeFunc(prometheus.GaugeOpts{
|
|
||||||
Name: "prometheus_tsdb_head_max_time_seconds",
|
|
||||||
Help: "Maximum timestamp of the head block.",
|
|
||||||
}, func() float64 { return convToSecondsFn(db.Head().MaxTime()) })
|
|
||||||
if r != nil {
|
if r != nil {
|
||||||
r.MustRegister(
|
r.MustRegister(
|
||||||
m.loadedBlocks,
|
m.loadedBlocks,
|
||||||
@ -281,9 +255,6 @@ func newDBMetrics(db *DB, r prometheus.Registerer, convToSecondsFn func(int64) f
|
|||||||
m.tombCleanTimer,
|
m.tombCleanTimer,
|
||||||
m.blocksBytes,
|
m.blocksBytes,
|
||||||
m.maxBytes,
|
m.maxBytes,
|
||||||
m.minTime,
|
|
||||||
m.headMaxTime,
|
|
||||||
m.headMinTime,
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
return m
|
return m
|
||||||
@ -574,7 +545,7 @@ func open(dir string, l log.Logger, r prometheus.Registerer, opts *Options, rngs
|
|||||||
autoCompact: true,
|
autoCompact: true,
|
||||||
chunkPool: chunkenc.NewPool(),
|
chunkPool: chunkenc.NewPool(),
|
||||||
}
|
}
|
||||||
db.metrics = newDBMetrics(db, r, opts.ConvertTimeToSecondsFn)
|
db.metrics = newDBMetrics(db, r)
|
||||||
|
|
||||||
maxBytes := opts.MaxBytes
|
maxBytes := opts.MaxBytes
|
||||||
if maxBytes < 0 {
|
if maxBytes < 0 {
|
||||||
|
@ -35,8 +35,6 @@ import (
|
|||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
prom_testutil "github.com/prometheus/client_golang/prometheus/testutil"
|
prom_testutil "github.com/prometheus/client_golang/prometheus/testutil"
|
||||||
dto "github.com/prometheus/client_model/go"
|
|
||||||
"github.com/prometheus/common/model"
|
|
||||||
"github.com/prometheus/prometheus/pkg/labels"
|
"github.com/prometheus/prometheus/pkg/labels"
|
||||||
"github.com/prometheus/prometheus/storage"
|
"github.com/prometheus/prometheus/storage"
|
||||||
"github.com/prometheus/prometheus/tsdb/chunks"
|
"github.com/prometheus/prometheus/tsdb/chunks"
|
||||||
@ -2701,41 +2699,3 @@ func TestChunkReader_ConcurrentReads(t *testing.T) {
|
|||||||
}
|
}
|
||||||
testutil.Ok(t, r.Close())
|
testutil.Ok(t, r.Close())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTimeMetrics(t *testing.T) {
|
|
||||||
db, closeFn := openTestDB(t, nil, nil)
|
|
||||||
defer func() {
|
|
||||||
testutil.Ok(t, db.Close())
|
|
||||||
closeFn()
|
|
||||||
}()
|
|
||||||
|
|
||||||
metrics := &dto.Metric{}
|
|
||||||
|
|
||||||
// Check initial values.
|
|
||||||
testutil.Ok(t, db.metrics.minTime.Write(metrics))
|
|
||||||
testutil.Equals(t, float64(math.MaxInt64)/1000, metrics.Gauge.GetValue())
|
|
||||||
|
|
||||||
testutil.Ok(t, db.metrics.headMinTime.Write(metrics))
|
|
||||||
testutil.Equals(t, float64(math.MaxInt64)/1000, metrics.Gauge.GetValue())
|
|
||||||
|
|
||||||
testutil.Ok(t, db.metrics.headMaxTime.Write(metrics))
|
|
||||||
testutil.Equals(t, float64(math.MinInt64)/1000, metrics.Gauge.GetValue())
|
|
||||||
|
|
||||||
app := db.Appender()
|
|
||||||
|
|
||||||
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, db.metrics.minTime.Write(metrics))
|
|
||||||
testutil.Equals(t, 0.0, metrics.Gauge.GetValue())
|
|
||||||
|
|
||||||
testutil.Ok(t, db.metrics.headMinTime.Write(metrics))
|
|
||||||
testutil.Equals(t, 0.0, metrics.Gauge.GetValue())
|
|
||||||
|
|
||||||
testutil.Ok(t, db.metrics.headMaxTime.Write(metrics))
|
|
||||||
testutil.Equals(t, 0.0, metrics.Gauge.GetValue())
|
|
||||||
|
|
||||||
}
|
|
||||||
|
@ -234,8 +234,6 @@ func (opts TSDBOptions) ToTSDBOptions() tsdb.Options {
|
|||||||
StripeSize: opts.StripeSize,
|
StripeSize: opts.StripeSize,
|
||||||
MinBlockDuration: int64(time.Duration(opts.MinBlockDuration) / time.Millisecond),
|
MinBlockDuration: int64(time.Duration(opts.MinBlockDuration) / time.Millisecond),
|
||||||
MaxBlockDuration: int64(time.Duration(opts.MaxBlockDuration) / time.Millisecond),
|
MaxBlockDuration: int64(time.Duration(opts.MaxBlockDuration) / time.Millisecond),
|
||||||
|
|
||||||
ConvertTimeToSecondsFn: func(i int64) float64 { return float64(i / 1000) },
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user