Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
139 changes: 81 additions & 58 deletions extraction/metricfamilyprocessor.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ package extraction
import (
"fmt"
"io"
"math"

dto "github.com/prometheus/client_model/go"

Expand Down Expand Up @@ -85,24 +86,23 @@ func extractCounter(out Ingester, o *ProcessOptions, f *dto.MetricFamily) error
continue
}

sample := new(model.Sample)
sample := &model.Sample{
Metric: model.Metric{},
Value: model.SampleValue(m.Counter.GetValue()),
}
samples = append(samples, sample)

if m.TimestampMs != nil {
sample.Timestamp = model.TimestampFromUnixNano(*m.TimestampMs * 1000000)
} else {
sample.Timestamp = o.Timestamp
}
sample.Metric = model.Metric{}
metric := sample.Metric

metric := sample.Metric
for _, p := range m.Label {
metric[model.LabelName(p.GetName())] = model.LabelValue(p.GetValue())
}

metric[model.MetricNameLabel] = model.LabelValue(f.GetName())

sample.Value = model.SampleValue(m.Counter.GetValue())
}

return out.Ingest(samples)
Expand All @@ -116,24 +116,23 @@ func extractGauge(out Ingester, o *ProcessOptions, f *dto.MetricFamily) error {
continue
}

sample := new(model.Sample)
sample := &model.Sample{
Metric: model.Metric{},
Value: model.SampleValue(m.Gauge.GetValue()),
}
samples = append(samples, sample)

if m.TimestampMs != nil {
sample.Timestamp = model.TimestampFromUnixNano(*m.TimestampMs * 1000000)
} else {
sample.Timestamp = o.Timestamp
}
sample.Metric = model.Metric{}
metric := sample.Metric

metric := sample.Metric
for _, p := range m.Label {
metric[model.LabelName(p.GetName())] = model.LabelValue(p.GetValue())
}

metric[model.MetricNameLabel] = model.LabelValue(f.GetName())

sample.Value = model.SampleValue(m.Gauge.GetValue())
}

return out.Ingest(samples)
Expand All @@ -153,48 +152,50 @@ func extractSummary(out Ingester, o *ProcessOptions, f *dto.MetricFamily) error
}

for _, q := range m.Summary.Quantile {
sample := new(model.Sample)
sample := &model.Sample{
Metric: model.Metric{},
Value: model.SampleValue(q.GetValue()),
Timestamp: timestamp,
}
samples = append(samples, sample)

sample.Timestamp = timestamp
sample.Metric = model.Metric{}
metric := sample.Metric

for _, p := range m.Label {
metric[model.LabelName(p.GetName())] = model.LabelValue(p.GetValue())
}
// BUG(matt): Update other names to "quantile".
metric[model.LabelName("quantile")] = model.LabelValue(fmt.Sprint(q.GetQuantile()))

metric[model.LabelName(model.QuantileLabel)] = model.LabelValue(fmt.Sprint(q.GetQuantile()))
metric[model.MetricNameLabel] = model.LabelValue(f.GetName())

sample.Value = model.SampleValue(q.GetValue())
}

if m.Summary.SampleSum != nil {
sum := new(model.Sample)
sum.Timestamp = timestamp
metric := model.Metric{}
sum := &model.Sample{
Metric: model.Metric{},
Value: model.SampleValue(m.Summary.GetSampleSum()),
Timestamp: timestamp,
}
samples = append(samples, sum)

metric := sum.Metric
for _, p := range m.Label {
metric[model.LabelName(p.GetName())] = model.LabelValue(p.GetValue())
}
metric[model.MetricNameLabel] = model.LabelValue(f.GetName() + "_sum")
sum.Metric = metric
sum.Value = model.SampleValue(m.Summary.GetSampleSum())
samples = append(samples, sum)
}

if m.Summary.SampleCount != nil {
count := new(model.Sample)
count.Timestamp = timestamp
metric := model.Metric{}
count := &model.Sample{
Metric: model.Metric{},
Value: model.SampleValue(m.Summary.GetSampleCount()),
Timestamp: timestamp,
}
samples = append(samples, count)

metric := count.Metric
for _, p := range m.Label {
metric[model.LabelName(p.GetName())] = model.LabelValue(p.GetValue())
}
metric[model.MetricNameLabel] = model.LabelValue(f.GetName() + "_count")
count.Metric = metric
count.Value = model.SampleValue(m.Summary.GetSampleCount())
samples = append(samples, count)
}
}

Expand All @@ -209,24 +210,23 @@ func extractUntyped(out Ingester, o *ProcessOptions, f *dto.MetricFamily) error
continue
}

sample := new(model.Sample)
sample := &model.Sample{
Metric: model.Metric{},
Value: model.SampleValue(m.Untyped.GetValue()),
}
samples = append(samples, sample)

if m.TimestampMs != nil {
sample.Timestamp = model.TimestampFromUnixNano(*m.TimestampMs * 1000000)
} else {
sample.Timestamp = o.Timestamp
}
sample.Metric = model.Metric{}
metric := sample.Metric

metric := sample.Metric
for _, p := range m.Label {
metric[model.LabelName(p.GetName())] = model.LabelValue(p.GetValue())
}

metric[model.MetricNameLabel] = model.LabelValue(f.GetName())

sample.Value = model.SampleValue(m.Untyped.GetValue())
}

return out.Ingest(samples)
Expand All @@ -245,49 +245,72 @@ func extractHistogram(out Ingester, o *ProcessOptions, f *dto.MetricFamily) erro
timestamp = model.TimestampFromUnixNano(*m.TimestampMs * 1000000)
}

infSeen := false

for _, q := range m.Histogram.Bucket {
sample := new(model.Sample)
sample := &model.Sample{
Metric: model.Metric{},
Value: model.SampleValue(q.GetCumulativeCount()),
Timestamp: timestamp,
}
samples = append(samples, sample)

sample.Timestamp = timestamp
sample.Metric = model.Metric{}
metric := sample.Metric

for _, p := range m.Label {
metric[model.LabelName(p.GetName())] = model.LabelValue(p.GetValue())
}
metric[model.LabelName("le")] = model.LabelValue(fmt.Sprint(q.GetUpperBound()))

metric[model.LabelName(model.BucketLabel)] = model.LabelValue(fmt.Sprint(q.GetUpperBound()))
metric[model.MetricNameLabel] = model.LabelValue(f.GetName() + "_bucket")

sample.Value = model.SampleValue(q.GetCumulativeCount())
if math.IsInf(q.GetUpperBound(), +1) {
infSeen = true
}
}
// TODO: If +Inf bucket is missing, add it.

if m.Histogram.SampleSum != nil {
sum := new(model.Sample)
sum.Timestamp = timestamp
metric := model.Metric{}
sum := &model.Sample{
Metric: model.Metric{},
Value: model.SampleValue(m.Histogram.GetSampleSum()),
Timestamp: timestamp,
}
samples = append(samples, sum)

metric := sum.Metric
for _, p := range m.Label {
metric[model.LabelName(p.GetName())] = model.LabelValue(p.GetValue())
}
metric[model.MetricNameLabel] = model.LabelValue(f.GetName() + "_sum")
sum.Metric = metric
sum.Value = model.SampleValue(m.Histogram.GetSampleSum())
samples = append(samples, sum)
}

if m.Histogram.SampleCount != nil {
count := new(model.Sample)
count.Timestamp = timestamp
metric := model.Metric{}
count := &model.Sample{
Metric: model.Metric{},
Value: model.SampleValue(m.Histogram.GetSampleCount()),
Timestamp: timestamp,
}
samples = append(samples, count)

metric := count.Metric
for _, p := range m.Label {
metric[model.LabelName(p.GetName())] = model.LabelValue(p.GetValue())
}
metric[model.MetricNameLabel] = model.LabelValue(f.GetName() + "_count")
count.Metric = metric
count.Value = model.SampleValue(m.Histogram.GetSampleCount())
samples = append(samples, count)

if !infSeen {
infBucket := &model.Sample{
Metric: model.Metric{},
Value: count.Value,
Timestamp: timestamp,
}
samples = append(samples, infBucket)

metric := infBucket.Metric
for _, p := range m.Label {
metric[model.LabelName(p.GetName())] = model.LabelValue(p.GetValue())
}
metric[model.LabelName(model.BucketLabel)] = model.LabelValue("+Inf")
metric[model.MetricNameLabel] = model.LabelValue(f.GetName() + "_bucket")
}
}
}

Expand Down
8 changes: 8 additions & 0 deletions model/labelname.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,14 @@ const (
// JobLabel is the label name indicating the job from which a timeseries
// was scraped.
JobLabel LabelName = "job"

// BucketLabel is used for the label that defines the upper bound of a
// bucket of a histogram ("le" -> "less or equal").
BucketLabel = "le"

// QuantileLabel is used for the label that defines the quantile in a
// summary.
QuantileLabel = "quantile"
)

// A LabelName is a key for a LabelSet or Metric. It has a value associated
Expand Down
28 changes: 28 additions & 0 deletions prometheus/benchmark_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -129,3 +129,31 @@ func BenchmarkSummaryNoLabels(b *testing.B) {
m.Observe(3.1415)
}
}

func BenchmarkHistogramWithLabelValues(b *testing.B) {
m := NewHistogramVec(
HistogramOpts{
Name: "benchmark_histogram",
Help: "A histogram to benchmark it.",
},
[]string{"one", "two", "three"},
)
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
m.WithLabelValues("eins", "zwei", "drei").Observe(3.1415)
}
}

func BenchmarkHistogramNoLabels(b *testing.B) {
m := NewHistogram(HistogramOpts{
Name: "benchmark_histogram",
Help: "A histogram to benchmark it.",
},
)
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
m.Observe(3.1415)
}
}
2 changes: 1 addition & 1 deletion prometheus/counter.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ func (c *counter) Add(v float64) {
// CounterVec is a Collector that bundles a set of Counters that all share the
// same Desc, but have different values for their variable labels. This is used
// if you want to count the same thing partitioned by various dimensions
// (e.g. number of http requests, partitioned by response code and
// (e.g. number of HTTP requests, partitioned by response code and
// method). Create instances with NewCounterVec.
//
// CounterVec embeds MetricVec. See there for a full list of methods with
Expand Down
52 changes: 49 additions & 3 deletions prometheus/examples_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ func ExampleCounterVec() {
httpReqs := prometheus.NewCounterVec(
prometheus.CounterOpts{
Name: "http_requests_total",
Help: "How many HTTP requests processed, partitioned by status code and http method.",
Help: "How many HTTP requests processed, partitioned by status code and HTTP method.",
ConstLabels: prometheus.Labels{"env": *binaryVersion},
},
[]string{"code", "method"},
Expand Down Expand Up @@ -200,7 +200,7 @@ func ExampleRegister() {
fmt.Println("taskCounter registered.")
}
// Don't forget to tell the HTTP server about the Prometheus handler.
// (In a real program, you still need to start the http server...)
// (In a real program, you still need to start the HTTP server...)
http.Handle("/metrics", prometheus.Handler())

// Now you can start workers and give every one of them a pointer to
Expand Down Expand Up @@ -240,7 +240,7 @@ func ExampleRegister() {

// Prometheus will not allow you to ever export metrics with
// inconsistent help strings or label names. After unregistering, the
// unregistered metrics will cease to show up in the /metrics http
// unregistered metrics will cease to show up in the /metrics HTTP
// response, but the registry still remembers that those metrics had
// been exported before. For this example, we will now choose a
// different name. (In a real program, you would obviously not export
Expand Down Expand Up @@ -452,3 +452,49 @@ func ExampleSummaryVec() {
// >
// ]
}

func ExampleHistogram() {
temps := prometheus.NewHistogram(prometheus.HistogramOpts{
Name: "pond_temperature_celsius",
Help: "The temperature of the frog pond.", // Sorry, we can't measure how badly it smells.
Buckets: prometheus.LinearBuckets(20, 5, 5), // 5 buckets, each 5 centigrade wide.
})

// Simulate some observations.
for i := 0; i < 1000; i++ {
temps.Observe(30 + math.Floor(120*math.Sin(float64(i)*0.1))/10)
}

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

// Output:
// histogram: <
// sample_count: 1000
// sample_sum: 29969.50000000001
// bucket: <
// cumulative_count: 192
// upper_bound: 20
// >
// bucket: <
// cumulative_count: 366
// upper_bound: 25
// >
// bucket: <
// cumulative_count: 501
// upper_bound: 30
// >
// bucket: <
// cumulative_count: 638
// upper_bound: 35
// >
// bucket: <
// cumulative_count: 816
// upper_bound: 40
// >
// >
}
Loading