Files

83 lines
2.1 KiB
Go

package libprometheus
import (
"context"
"io"
"time"
dto "github.com/prometheus/client_model/go"
"github.com/prometheus/common/expfmt"
prommodel "github.com/prometheus/common/model"
"github.com/prometheus/prometheus/model/labels"
"github.com/prometheus/prometheus/storage"
"github.com/rs/zerolog/log"
)
// AppendExpositionSamples parses Prometheus exposition-format metrics from r
// and appends them as samples to the given Appendable.
func AppendExpositionSamples(ctx context.Context, db storage.Appendable, r io.Reader) error {
parser := expfmt.NewTextParser(prommodel.UTF8Validation)
metricFamilies, err := parser.TextToMetricFamilies(r)
if err != nil {
return err
}
app := db.Appender(ctx)
now := time.Now().UnixMilli()
for name, mf := range metricFamilies {
if !supportsScalarMetricType(mf.GetType()) {
continue
}
for _, m := range mf.GetMetric() {
lbls := LabelsFromMetric(name, m)
value := ValueFromMetric(m, mf.GetType())
if _, err := app.Append(0, lbls, now, value); err != nil {
log.Debug().Err(err).Str("metric", name).Msg("failed to append metric sample")
}
}
}
return app.Commit()
}
func supportsScalarMetricType(mtype dto.MetricType) bool {
switch mtype {
case dto.MetricType_COUNTER, dto.MetricType_GAUGE, dto.MetricType_UNTYPED:
return true
default:
return false
}
}
// LabelsFromMetric builds a labels.Labels from a metric name and its label pairs.
func LabelsFromMetric(name string, m *dto.Metric) labels.Labels {
b := labels.NewScratchBuilder(1 + len(m.GetLabel()))
b.Add(string(prommodel.MetricNameLabel), name)
for _, lp := range m.GetLabel() {
b.Add(lp.GetName(), lp.GetValue())
}
b.Sort()
return b.Labels()
}
// ValueFromMetric extracts the numeric value from a metric based on its type.
func ValueFromMetric(m *dto.Metric, mtype dto.MetricType) float64 {
switch mtype {
case dto.MetricType_COUNTER:
if c := m.GetCounter(); c != nil {
return c.GetValue()
}
case dto.MetricType_GAUGE:
if g := m.GetGauge(); g != nil {
return g.GetValue()
}
case dto.MetricType_UNTYPED:
if u := m.GetUntyped(); u != nil {
return u.GetValue()
}
}
return 0
}