Skip to content

Commit

Permalink
Merge pull request #443 from prometheus/beorn7/timestamp
Browse files Browse the repository at this point in the history
Add a wrapper to add a timestamp to a metric
  • Loading branch information
beorn7 authored Aug 21, 2018
2 parents 5b23715 + abaece0 commit 29e6500
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 2 deletions.
38 changes: 36 additions & 2 deletions prometheus/examples_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,12 @@ import (
"runtime"
"sort"
"strings"
"time"

dto "github.com/prometheus/client_model/go"
"github.com/golang/protobuf/proto"
"github.com/prometheus/common/expfmt"

"github.com/golang/protobuf/proto"
dto "github.com/prometheus/client_model/go"

"github.com/prometheus/client_golang/prometheus"
)
Expand Down Expand Up @@ -751,3 +752,36 @@ temperature_kelvin 4.5
// temperature_kelvin{location="inside"} 298.44
// temperature_kelvin{location="outside"} 273.14
}

func ExampleNewMetricWithTimestamp() {
desc := prometheus.NewDesc(
"temperature_kelvin",
"Current temperature in Kelvin.",
nil, nil,
)

// Create a constant gauge from values we got from an external
// temperature reporting system. Those values are reported with a slight
// delay, so we want to add the timestamp of the actual measurement.
temperatureReportedByExternalSystem := 298.15
timeReportedByExternalSystem := time.Date(2009, time.November, 10, 23, 0, 0, 12345678, time.UTC)
s := prometheus.NewMetricWithTimestamp(
timeReportedByExternalSystem,
prometheus.MustNewConstMetric(
desc, prometheus.GaugeValue, temperatureReportedByExternalSystem,
),
)

// Just for demonstration, let's check the state of the gauge by
// (ab)using its Write method (which is usually only used by Prometheus
// internally).
metric := &dto.Metric{}
s.Write(metric)
fmt.Println(proto.MarshalTextString(metric))

// Output:
// gauge: <
// value: 298.15
// >
// timestamp_ms: 1257894000012
}
31 changes: 31 additions & 0 deletions prometheus/metric.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ package prometheus

import (
"strings"
"time"

"github.com/gogo/protobuf/proto"

dto "github.com/prometheus/client_model/go"
)
Expand Down Expand Up @@ -142,3 +145,31 @@ func NewInvalidMetric(desc *Desc, err error) Metric {
func (m *invalidMetric) Desc() *Desc { return m.desc }

func (m *invalidMetric) Write(*dto.Metric) error { return m.err }

type timestampedMetric struct {
Metric
t time.Time
}

func (m timestampedMetric) Write(pb *dto.Metric) error {
e := m.Metric.Write(pb)
pb.TimestampMs = proto.Int64(m.t.Unix()*1000 + int64(m.t.Nanosecond()/1000000))
return e
}

// NewMetricWithTimestamp returns a new Metric wrapping the provided Metric in a
// way that it has an explicit timestamp set to the provided Time. This is only
// useful in rare cases as the timestamp of a Prometheus metric should usually
// be set by the Prometheus server during scraping. Exceptions include mirroring
// metrics with given timestamps from other metric
// sources.
//
// NewMetricWithTimestamp works best with MustNewConstMetric,
// MustNewConstHistogram, and MustNewConstSummary, see example.
//
// Currently, the exposition formats used by Prometheus are limited to
// millisecond resolution. Thus, the provided time will be rounded down to the
// next full millisecond value.
func NewMetricWithTimestamp(t time.Time, m Metric) Metric {
return timestampedMetric{Metric: m, t: t}
}

0 comments on commit 29e6500

Please sign in to comment.