1
0
Fork 0

Adding upstream version 1.34.4.

Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
Daniel Baumann 2025-05-24 07:26:29 +02:00
parent e393c3af3f
commit 4978089aab
Signed by: daniel
GPG key ID: FBB4F0E80A80222F
4963 changed files with 677545 additions and 0 deletions

View file

@ -0,0 +1,154 @@
# OpenMetrics Format Parser Plugin
This plugin allows to parse the [OpenMetrics Text Format][] into Telegraf
metrics. It is used internally in [prometheus input](/plugins/inputs/prometheus)
but can also be used by e.g.
[http_listener_v2](/plugins/inputs/http_listener_v2) to simulate a Pushgateway.
The plugin allows to output different metric formats as described in the
[Metric Formats section](#metric-formats).
[OpenMetrics Text Format]: https://github.com/prometheus/OpenMetrics/blob/v1.0.0/specification/OpenMetrics.md
## Configuration
```toml
[[inputs.file]]
files = ["example"]
## Data format to consume.
## Each data format has its own unique set of configuration options, read
## more about them here:
## https://github.com/influxdata/telegraf/blob/master/docs/DATA_FORMATS_INPUT.md
data_format = "openmetrics"
```
## Metric Formats
The metric_version setting controls how telegraf translates OpenMetrics'
metrics to Telegraf metrics. There are two options.
### `v1` format
In this version, the OpenMetrics metric-family name becomes the Telegraf metric
name, labels become tags and values become fields. The fields are named based
on the type of the OpenMetric metric. This option produces metrics that are
dense (contrary to the sparse metrics of`v2`).
Example:
```text
# TYPE acme_http_router_request_seconds summary
# UNIT acme_http_router_request_seconds seconds
# HELP acme_http_router_request_seconds Latency though all of ACME's HTTP request router.
acme_http_router_request_seconds_sum{path="/api/v1",method="GET"} 9036.32
acme_http_router_request_seconds_count{path="/api/v1",method="GET"} 807283.0
acme_http_router_request_seconds{path="/api/v1",method="GET",quantile="0.5"} 1.29854
acme_http_router_request_seconds{path="/api/v1",method="GET",quantile="0.9"} 54.85479
acme_http_router_request_seconds{path="/api/v1",method="GET",quantile="0.99"} 6884.32324
acme_http_router_request_seconds_created{path="/api/v1",method="GET"} 1605281325.0
acme_http_router_request_seconds_sum{path="/api/v2",method="POST"} 479.3
acme_http_router_request_seconds_count{path="/api/v2",method="POST"} 34.0
acme_http_router_request_seconds_created{path="/api/v2",method="POST"} 1605281325.0
acme_http_router_request_seconds{path="/api/v2",method="POST",quantile="0.5"} 0.85412
acme_http_router_request_seconds{path="/api/v2",method="POST",quantile="0.9"} 1.15429
acme_http_router_request_seconds{path="/api/v2",method="POST",quantile="0.99"} 3698.48132
# TYPE go_goroutines gauge
# HELP go_goroutines Number of goroutines that currently exist.
go_goroutines 69
# TYPE process_cpu_seconds counter
# UNIT process_cpu_seconds seconds
# HELP process_cpu_seconds Total user and system CPU time spent in seconds.
process_cpu_seconds_total 4.20072246e+06
# EOF```
becomes
```text
acme_http_router_request_seconds,unit=seconds,path=/api/v1,method=GET sum=9036.32,count=807283.0,created=1605281325.0,0.5=1.29854,0.9=54.85479,0.99=6884.32324
acme_http_router_request_seconds,unit=seconds,path=/api/v2,method=POST sum=479.3,count=34.0,created=1605281325.0,0.5=0.85412,0.9=1.15429,0.99=3698.48132
go_goroutines gauge=69
process_cpu_seconds,unit=seconds counter=4200722.46
```
This is especially useful and efficient for outputs with row-oriented data
models.
### `v2` format
In this version, each OpenMetrics MetricPoint becomes a Telegraf metric with
a few exceptions for complex types like histograms. All Telegraf metrics are
named `prometheus` with OpenMetrics' labels become tags and the field-name is
based on the OpenMetrics metric-name.
Example:
Example:
```text
# TYPE acme_http_router_request_seconds summary
# UNIT acme_http_router_request_seconds seconds
# HELP acme_http_router_request_seconds Latency though all of ACME's HTTP request router.
acme_http_router_request_seconds_sum{path="/api/v1",method="GET"} 9036.32
acme_http_router_request_seconds_count{path="/api/v1",method="GET"} 807283.0
acme_http_router_request_seconds{path="/api/v1",method="GET",quantile="0.5"} 1.29854
acme_http_router_request_seconds{path="/api/v1",method="GET",quantile="0.9"} 54.85479
acme_http_router_request_seconds{path="/api/v1",method="GET",quantile="0.99"} 6884.32324
acme_http_router_request_seconds_created{path="/api/v1",method="GET"} 1605281325.0
acme_http_router_request_seconds_sum{path="/api/v2",method="POST"} 479.3
acme_http_router_request_seconds_count{path="/api/v2",method="POST"} 34.0
acme_http_router_request_seconds_created{path="/api/v2",method="POST"} 1605281325.0
acme_http_router_request_seconds{path="/api/v2",method="POST",quantile="0.5"} 0.85412
acme_http_router_request_seconds{path="/api/v2",method="POST",quantile="0.9"} 1.15429
acme_http_router_request_seconds{path="/api/v2",method="POST",quantile="0.99"} 3698.48132
# TYPE go_goroutines gauge
# HELP go_goroutines Number of goroutines that currently exist.
go_goroutines 69
# TYPE process_cpu_seconds counter
# UNIT process_cpu_seconds seconds
# HELP process_cpu_seconds Total user and system CPU time spent in seconds.
process_cpu_seconds_total 4.20072246e+06
# EOF```
becomes
```text
prometheus,method=GET,path=/api/v1,unit=seconds acme_http_router_request_seconds_count=807283,acme_http_router_request_seconds_created=1605281325,acme_http_router_request_seconds_sum=9036.32
prometheus,method=GET,path=/api/v1,quantile=0.5,unit=seconds acme_http_router_request_seconds=1.29854
prometheus,method=GET,path=/api/v1,quantile=0.9,unit=seconds acme_http_router_request_seconds=54.85479
prometheus,method=GET,path=/api/v1,quantile=0.99,unit=seconds acme_http_router_request_seconds=6884.32324
prometheus,method=POST,path=/api/v2,unit=seconds acme_http_router_request_seconds_count=34,acme_http_router_request_seconds_created=1605281325,acme_http_router_request_seconds_sum=479.3
prometheus,method=POST,path=/api/v2,quantile=0.5,unit=seconds acme_http_router_request_seconds=0.85412
prometheus,method=POST,path=/api/v2,quantile=0.9,unit=seconds acme_http_router_request_seconds=1.15429
prometheus,method=POST,path=/api/v2,quantile=0.99,unit=seconds acme_http_router_request_seconds=3698.48132
prometheus go_goroutines=69
prometheus,unit=seconds process_cpu_seconds=4200722.46
```
The resulting metrics are sparse, but for some outputs they may be easier to
process or query, including those that are more efficient with column-oriented
data. The telegraf metric name is the same for all metrics in the input
instance. It can be set with the `name_override` setting and defaults to
"prometheus". To have multiple metric names, you can use multiple instances of
the plugin, each with its own `name_override`.
`metric_version = 2` uses the same histogram format as the histogram aggregator
## Regenerating OpenMetrics code
Download the latest version of the protocol-buffer definition
```text
wget https://raw.githubusercontent.com/OpenObservability/OpenMetrics/main/proto/openmetrics_data_model.proto
```
and generate the go-code for the definition using
```text
protoc --proto_path=. \
--go_out=. \
--go_opt=paths=source_relative \
--go_opt=Mopenmetrics_data_model.proto=github.com/influxdata/telegraf/plugins/parsers/openmetrics \
openmetrics_data_model.proto
```

View file

@ -0,0 +1,163 @@
package openmetrics
import (
"math"
"strconv"
"strings"
"time"
"github.com/influxdata/telegraf"
"github.com/influxdata/telegraf/metric"
)
func (p *Parser) extractMetricsV1(ometrics *MetricFamily) []telegraf.Metric {
now := time.Now()
// Convert each prometheus metrics to the corresponding telegraf metrics.
// You will get one telegraf metric with one field per prometheus metric
// for "simple" types like Gauge and Counter but a telegraf metric with
// multiple fields for "complex" types like Summary or Histogram.
var metrics []telegraf.Metric
metricName := ometrics.GetName()
metricType := ometrics.GetType()
for _, om := range ometrics.GetMetrics() {
// Extract the timestamp of the metric if it exists and should
// not be ignored.
t := now
// Convert the labels to tags
tags := getTagsFromLabels(om, p.DefaultTags)
if ometrics.Unit != "" {
tags["unit"] = ometrics.Unit
}
// Iterate over the metric points and construct a metric for each
for _, omp := range om.GetMetricPoints() {
if omp.Timestamp != nil {
t = omp.GetTimestamp().AsTime()
}
// Construct the metrics
switch metricType {
case MetricType_UNKNOWN:
x := omp.GetUnknownValue().GetValue()
if x == nil {
continue
}
var value float64
switch v := x.(type) {
case *UnknownValue_DoubleValue:
value = v.DoubleValue
case *UnknownValue_IntValue:
value = float64(v.IntValue)
}
if math.IsNaN(value) {
continue
}
fields := map[string]interface{}{"value": value}
metrics = append(metrics, metric.New(metricName, tags, fields, t, telegraf.Untyped))
case MetricType_GAUGE:
x := omp.GetGaugeValue().GetValue()
if x == nil {
continue
}
var value float64
switch v := x.(type) {
case *GaugeValue_DoubleValue:
value = v.DoubleValue
case *GaugeValue_IntValue:
value = float64(v.IntValue)
}
if math.IsNaN(value) {
continue
}
fields := map[string]interface{}{"gauge": value}
metrics = append(metrics, metric.New(metricName, tags, fields, t, telegraf.Gauge))
case MetricType_COUNTER:
x := omp.GetCounterValue().GetTotal()
if x == nil {
continue
}
var value float64
switch v := x.(type) {
case *CounterValue_DoubleValue:
value = v.DoubleValue
case *CounterValue_IntValue:
value = float64(v.IntValue)
}
if math.IsNaN(value) {
continue
}
fields := map[string]interface{}{"counter": value}
metrics = append(metrics, metric.New(metricName, tags, fields, t, telegraf.Counter))
case MetricType_STATE_SET:
stateset := omp.GetStateSetValue()
// Collect the fields
fields := make(map[string]interface{}, len(stateset.States))
for _, state := range stateset.GetStates() {
fname := strings.ReplaceAll(state.GetName(), " ", "_")
fields[fname] = state.GetEnabled()
}
metrics = append(metrics, metric.New(metricName, tags, fields, t, telegraf.Untyped))
case MetricType_INFO:
info := omp.GetInfoValue().GetInfo()
fields := map[string]interface{}{"info": uint64(1)}
mptags := make(map[string]string, len(tags)+len(info))
for k, v := range tags {
mptags[k] = v
}
for _, itag := range info {
mptags[itag.Name] = itag.Value
}
metrics = append(metrics, metric.New(metricName, mptags, fields, t, telegraf.Untyped))
case MetricType_HISTOGRAM, MetricType_GAUGE_HISTOGRAM:
histogram := omp.GetHistogramValue()
// Collect the fields
fields := make(map[string]interface{}, len(histogram.Buckets)+3)
fields["count"] = float64(histogram.GetCount())
if s := histogram.GetSum(); s != nil {
switch v := s.(type) {
case *HistogramValue_DoubleValue:
fields["sum"] = v.DoubleValue
case *HistogramValue_IntValue:
fields["sum"] = float64(v.IntValue)
}
}
if ts := histogram.GetCreated(); ts != nil {
fields["created"] = float64(ts.Seconds) + float64(ts.Nanos)/float64(time.Nanosecond)
}
for _, b := range histogram.Buckets {
fname := strconv.FormatFloat(b.GetUpperBound(), 'g', -1, 64)
fields[fname] = float64(b.GetCount())
}
metrics = append(metrics, metric.New(metricName, tags, fields, t, telegraf.Histogram))
case MetricType_SUMMARY:
summary := omp.GetSummaryValue()
// Collect the fields
fields := make(map[string]interface{}, len(summary.Quantile)+2)
fields["count"] = float64(summary.GetCount())
if s := summary.GetSum(); s != nil {
switch v := s.(type) {
case *SummaryValue_DoubleValue:
fields["sum"] = v.DoubleValue
case *SummaryValue_IntValue:
fields["sum"] = float64(v.IntValue)
}
}
if ts := summary.GetCreated(); ts != nil {
fields["created"] = float64(ts.Seconds) + float64(ts.Nanos)/float64(time.Second)
}
for _, q := range summary.GetQuantile() {
if v := q.GetValue(); !math.IsNaN(v) {
fname := strconv.FormatFloat(q.GetQuantile(), 'g', -1, 64)
fields[fname] = v
}
}
metrics = append(metrics, metric.New(metricName, tags, fields, t, telegraf.Summary))
}
}
}
return metrics
}

View file

@ -0,0 +1,189 @@
package openmetrics
import (
"math"
"strconv"
"strings"
"time"
"github.com/influxdata/telegraf"
"github.com/influxdata/telegraf/metric"
)
func (p *Parser) extractMetricsV2(ometrics *MetricFamily) []telegraf.Metric {
now := time.Now()
// Convert each openmetric metric to a corresponding telegraf metric
// with one field each. The process will filter NaNs in values and skip
// the corresponding metrics.
var metrics []telegraf.Metric
metricName := ometrics.GetName()
metricType := ometrics.GetType()
for _, om := range ometrics.GetMetrics() {
// Extract the timestamp of the metric if it exists and should
// not be ignored.
t := now
// Convert the labels to tags
tags := getTagsFromLabels(om, p.DefaultTags)
if ometrics.Unit != "" {
tags["unit"] = ometrics.Unit
}
// Construct the metrics
for _, omp := range om.GetMetricPoints() {
if omp.Timestamp != nil {
t = omp.GetTimestamp().AsTime()
}
switch metricType {
case MetricType_UNKNOWN:
x := omp.GetUnknownValue().GetValue()
if x == nil {
continue
}
var value float64
switch v := x.(type) {
case *UnknownValue_DoubleValue:
value = v.DoubleValue
case *UnknownValue_IntValue:
value = float64(v.IntValue)
}
if math.IsNaN(value) {
continue
}
fields := map[string]interface{}{metricName: value}
metrics = append(metrics, metric.New("openmetric", tags, fields, t, telegraf.Untyped))
case MetricType_GAUGE:
x := omp.GetGaugeValue().GetValue()
if x == nil {
continue
}
var value float64
switch v := x.(type) {
case *GaugeValue_DoubleValue:
value = v.DoubleValue
case *GaugeValue_IntValue:
value = float64(v.IntValue)
}
if math.IsNaN(value) {
continue
}
fields := map[string]interface{}{metricName: value}
metrics = append(metrics, metric.New("openmetric", tags, fields, t, telegraf.Gauge))
case MetricType_COUNTER:
x := omp.GetCounterValue().GetTotal()
if x == nil {
continue
}
var value float64
switch v := x.(type) {
case *CounterValue_DoubleValue:
value = v.DoubleValue
case *CounterValue_IntValue:
value = float64(v.IntValue)
}
if math.IsNaN(value) {
continue
}
fields := map[string]interface{}{metricName: value}
metrics = append(metrics, metric.New("openmetric", tags, fields, t, telegraf.Counter))
case MetricType_STATE_SET:
stateset := omp.GetStateSetValue()
// Add one metric per state
for _, state := range stateset.GetStates() {
sn := strings.ReplaceAll(state.GetName(), " ", "_")
fields := map[string]interface{}{metricName + "_" + sn: state.GetEnabled()}
metrics = append(metrics, metric.New("openmetric", tags, fields, t, telegraf.Untyped))
}
case MetricType_INFO:
info := omp.GetInfoValue().GetInfo()
mptags := make(map[string]string, len(tags)+len(info))
for k, v := range tags {
mptags[k] = v
}
for _, itag := range info {
mptags[itag.Name] = itag.Value
}
fields := map[string]interface{}{metricName + "_info": uint64(1)}
metrics = append(metrics, metric.New("openmetric", mptags, fields, t, telegraf.Untyped))
case MetricType_HISTOGRAM, MetricType_GAUGE_HISTOGRAM:
histogram := omp.GetHistogramValue()
// Add an overall metric containing the number of samples and and its sum
histFields := make(map[string]interface{})
histFields[metricName+"_count"] = float64(histogram.GetCount())
if s := histogram.GetSum(); s != nil {
switch v := s.(type) {
case *HistogramValue_DoubleValue:
histFields[metricName+"_sum"] = v.DoubleValue
case *HistogramValue_IntValue:
histFields[metricName+"_sum"] = float64(v.IntValue)
}
}
if ts := histogram.GetCreated(); ts != nil {
histFields[metricName+"_created"] = float64(ts.Seconds) + float64(ts.Nanos)/float64(time.Nanosecond)
}
metrics = append(metrics, metric.New("openmetric", tags, histFields, t, telegraf.Histogram))
// Add one metric per histogram bucket
var infSeen bool
for _, b := range histogram.GetBuckets() {
bucketTags := tags
bucketTags["le"] = strconv.FormatFloat(b.GetUpperBound(), 'g', -1, 64)
bucketFields := map[string]interface{}{
metricName + "_bucket": float64(b.GetCount()),
}
m := metric.New("openmetric", bucketTags, bucketFields, t, telegraf.Histogram)
metrics = append(metrics, m)
// Record if any of the buckets marks an infinite upper bound
infSeen = infSeen || math.IsInf(b.GetUpperBound(), +1)
}
// Infinity bucket is required for proper function of histogram in openmetric
if !infSeen {
infTags := tags
infTags["le"] = "+Inf"
infFields := map[string]interface{}{
metricName + "_bucket": float64(histogram.GetCount()),
}
m := metric.New("openmetric", infTags, infFields, t, telegraf.Histogram)
metrics = append(metrics, m)
}
case MetricType_SUMMARY:
summary := omp.GetSummaryValue()
// Add an overall metric containing the number of samples and and its sum
summaryFields := make(map[string]interface{})
summaryFields[metricName+"_count"] = float64(summary.GetCount())
if s := summary.GetSum(); s != nil {
switch v := s.(type) {
case *SummaryValue_DoubleValue:
summaryFields[metricName+"_sum"] = v.DoubleValue
case *SummaryValue_IntValue:
summaryFields[metricName+"_sum"] = float64(v.IntValue)
}
}
if ts := summary.GetCreated(); ts != nil {
summaryFields[metricName+"_created"] = float64(ts.Seconds) + float64(ts.Nanos)/float64(time.Nanosecond)
}
metrics = append(metrics, metric.New("openmetric", tags, summaryFields, t, telegraf.Summary))
// Add one metric per quantile
for _, q := range summary.Quantile {
quantileTags := tags
quantileTags["quantile"] = strconv.FormatFloat(q.GetQuantile(), 'g', -1, 64)
quantileFields := map[string]interface{}{
metricName: q.GetValue(),
}
m := metric.New("openmetric", quantileTags, quantileFields, t, telegraf.Summary)
metrics = append(metrics, m)
}
}
}
}
return metrics
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,214 @@
syntax = "proto3";
// The OpenMetrics protobuf schema which defines the protobuf wire format.
// Ensure to interpret "required" as semantically required for a valid message.
// All string fields MUST be UTF-8 encoded strings.
package openmetrics;
import "google/protobuf/timestamp.proto";
// The top-level container type that is encoded and sent over the wire.
message MetricSet {
// Each MetricFamily has one or more MetricPoints for a single Metric.
repeated MetricFamily metric_families = 1;
}
// One or more Metrics for a single MetricFamily, where each Metric
// has one or more MetricPoints.
message MetricFamily {
// Required.
string name = 1;
// Optional.
MetricType type = 2;
// Optional.
string unit = 3;
// Optional.
string help = 4;
// Optional.
repeated Metric metrics = 5;
}
// The type of a Metric.
enum MetricType {
// Unknown must use unknown MetricPoint values.
UNKNOWN = 0;
// Gauge must use gauge MetricPoint values.
GAUGE = 1;
// Counter must use counter MetricPoint values.
COUNTER = 2;
// State set must use state set MetricPoint values.
STATE_SET = 3;
// Info must use info MetricPoint values.
INFO = 4;
// Histogram must use histogram value MetricPoint values.
HISTOGRAM = 5;
// Gauge histogram must use histogram value MetricPoint values.
GAUGE_HISTOGRAM = 6;
// Summary quantiles must use summary value MetricPoint values.
SUMMARY = 7;
}
// A single metric with a unique set of labels within a metric family.
message Metric {
// Optional.
repeated Label labels = 1;
// Optional.
repeated MetricPoint metric_points = 2;
}
// A name-value pair. These are used in multiple places: identifying
// timeseries, value of INFO metrics, and exemplars in Histograms.
message Label {
// Required.
string name = 1;
// Required.
string value = 2;
}
// A MetricPoint in a Metric.
message MetricPoint {
// Required.
oneof value {
UnknownValue unknown_value = 1;
GaugeValue gauge_value = 2;
CounterValue counter_value = 3;
HistogramValue histogram_value = 4;
StateSetValue state_set_value = 5;
InfoValue info_value = 6;
SummaryValue summary_value = 7;
}
// Optional.
google.protobuf.Timestamp timestamp = 8;
}
// Value for UNKNOWN MetricPoint.
message UnknownValue {
// Required.
oneof value {
double double_value = 1;
int64 int_value = 2;
}
}
// Value for GAUGE MetricPoint.
message GaugeValue {
// Required.
oneof value {
double double_value = 1;
int64 int_value = 2;
}
}
// Value for COUNTER MetricPoint.
message CounterValue {
// Required.
oneof total {
double double_value = 1;
uint64 int_value = 2;
}
// The time values began being collected for this counter.
// Optional.
google.protobuf.Timestamp created = 3;
// Optional.
Exemplar exemplar = 4;
}
// Value for HISTOGRAM or GAUGE_HISTOGRAM MetricPoint.
message HistogramValue {
// Optional.
oneof sum {
double double_value = 1;
int64 int_value = 2;
}
// Optional.
uint64 count = 3;
// The time values began being collected for this histogram.
// Optional.
google.protobuf.Timestamp created = 4;
// Optional.
repeated Bucket buckets = 5;
// Bucket is the number of values for a bucket in the histogram
// with an optional exemplar.
message Bucket {
// Required.
uint64 count = 1;
// Optional.
double upper_bound = 2;
// Optional.
Exemplar exemplar = 3;
}
}
message Exemplar {
// Required.
double value = 1;
// Optional.
google.protobuf.Timestamp timestamp = 2;
// Labels are additional information about the exemplar value (e.g. trace id).
// Optional.
repeated Label label = 3;
}
// Value for STATE_SET MetricPoint.
message StateSetValue {
// Optional.
repeated State states = 1;
message State {
// Required.
bool enabled = 1;
// Required.
string name = 2;
}
}
// Value for INFO MetricPoint.
message InfoValue {
// Optional.
repeated Label info = 1;
}
// Value for SUMMARY MetricPoint.
message SummaryValue {
// Optional.
oneof sum {
double double_value = 1;
int64 int_value = 2;
}
// Optional.
uint64 count = 3;
// The time sum and count values began being collected for this summary.
// Optional.
google.protobuf.Timestamp created = 4;
// Optional.
repeated Quantile quantile = 5;
message Quantile {
// Required.
double quantile = 1;
// Required.
double value = 2;
}
}

View file

@ -0,0 +1,143 @@
package openmetrics
import (
"bytes"
"errors"
"fmt"
"mime"
"net/http"
"github.com/prometheus/common/expfmt"
"google.golang.org/protobuf/proto"
"github.com/influxdata/telegraf"
"github.com/influxdata/telegraf/plugins/parsers"
)
func AcceptsContent(header http.Header) bool {
contentType := header.Get("Content-Type")
if contentType == "" {
return false
}
mediaType, params, err := mime.ParseMediaType(contentType)
if err != nil {
return false
}
switch mediaType {
case expfmt.OpenMetricsType:
return true
case "application/openmetrics-protobuf":
return params["version"] == "1.0.0"
}
return false
}
type Parser struct {
IgnoreTimestamp bool `toml:"openmetrics_ignore_timestamp"`
MetricVersion int `toml:"openmetrics_metric_version"`
Header http.Header `toml:"-"` // set by the input plugin
DefaultTags map[string]string `toml:"-"`
Log telegraf.Logger `toml:"-"`
}
func (p *Parser) SetDefaultTags(tags map[string]string) {
p.DefaultTags = tags
}
func (p *Parser) Parse(data []byte) ([]telegraf.Metric, error) {
// Determine the metric transport-type derived from the response header
contentType := p.Header.Get("Content-Type")
var mediaType string
var params map[string]string
if contentType == "" {
// Fallback to text type if no content-type is given
mediaType = expfmt.OpenMetricsType
} else {
var err error
mediaType, params, err = mime.ParseMediaType(contentType)
if err != nil {
return nil, fmt.Errorf("unknown media-type in %q", contentType)
}
}
// Parse the raw data into OpenMetrics metrics
var metricFamilies []*MetricFamily
switch mediaType {
case expfmt.OpenMetricsType:
// Make sure we have a finishing newline but no trailing one
data = bytes.TrimPrefix(data, []byte("\n"))
if !bytes.HasSuffix(data, []byte("\n")) {
data = append(data, []byte("\n")...)
}
var err error
metricFamilies, err = TextToMetricFamilies(data)
if err != nil {
return nil, fmt.Errorf("parsing text format failed: %w", err)
}
case "application/openmetrics-protobuf":
if version := params["version"]; version != "1.0.0" {
return nil, fmt.Errorf("unsupported binary version %q", version)
}
var metricSet MetricSet
if err := proto.Unmarshal(data, &metricSet); err != nil {
return nil, fmt.Errorf("parsing binary format failed: %w", err)
}
metricFamilies = metricSet.GetMetricFamilies()
}
// Convert the OpenMetrics metrics into Telegraf metrics
var metrics []telegraf.Metric
for _, mf := range metricFamilies {
switch p.MetricVersion {
case 0, 2:
metrics = append(metrics, p.extractMetricsV2(mf)...)
case 1:
metrics = append(metrics, p.extractMetricsV1(mf)...)
default:
return nil, fmt.Errorf("unknown metric version %d", p.MetricVersion)
}
}
return metrics, nil
}
func (p *Parser) ParseLine(line string) (telegraf.Metric, error) {
metrics, err := p.Parse([]byte(line))
if err != nil {
return nil, err
}
if len(metrics) < 1 {
return nil, errors.New("no metrics in line")
}
if len(metrics) > 1 {
return nil, errors.New("more than one metric in line")
}
return metrics[0], nil
}
func getTagsFromLabels(m *Metric, defaultTags map[string]string) map[string]string {
result := make(map[string]string, len(defaultTags)+len(m.Labels))
for key, value := range defaultTags {
result[key] = value
}
for _, label := range m.Labels {
if v := label.GetValue(); v != "" {
result[label.Name] = v
}
}
return result
}
func init() {
parsers.Add("openmetrics",
func(string) telegraf.Parser {
return &Parser{}
},
)
}

View file

@ -0,0 +1,178 @@
package openmetrics
import (
"net/http"
"os"
"path/filepath"
"testing"
"github.com/google/go-cmp/cmp"
"github.com/stretchr/testify/require"
"github.com/influxdata/telegraf/config"
"github.com/influxdata/telegraf/models"
"github.com/influxdata/telegraf/testutil"
test "github.com/influxdata/telegraf/testutil/plugin_input"
)
func TestCases(t *testing.T) {
// Get all directories in testcases
folders, err := os.ReadDir("testcases")
require.NoError(t, err)
// Make sure testdata contains data
require.NotEmpty(t, folders)
for _, f := range folders {
fname := f.Name()
testdataPath := filepath.Join("testcases", fname)
configFilename := filepath.Join(testdataPath, "telegraf.conf")
// Run tests as metric version 1
t.Run(fname+"_v1", func(t *testing.T) {
// Load the configuration
cfg := config.NewConfig()
require.NoError(t, cfg.LoadConfig(configFilename))
require.Len(t, cfg.Inputs, 1)
// Tune plugin
plugin := cfg.Inputs[0].Input.(*test.Plugin)
plugin.Path = testdataPath
plugin.UseTypeTag = "_type"
plugin.ExpectedFilename = "expected_v1.out"
parser := plugin.Parser.(*models.RunningParser).Parser.(*Parser)
parser.MetricVersion = 1
if raw, found := plugin.AdditionalParams["headers"]; found {
headers, ok := raw.(map[string]interface{})
require.Truef(t, ok, "unknown header type %T", raw)
parser.Header = make(http.Header)
for k, rv := range headers {
v, ok := rv.(string)
require.Truef(t, ok, "unknown header value type %T for %q", raw, k)
parser.Header.Add(k, v)
}
}
require.NoError(t, plugin.Init())
// Gather data and check errors
var acc testutil.Accumulator
err := plugin.Gather(&acc)
switch len(plugin.ExpectedErrors) {
case 0:
require.NoError(t, err)
case 1:
require.ErrorContains(t, err, plugin.ExpectedErrors[0])
default:
require.Contains(t, plugin.ExpectedErrors, err.Error())
}
// Determine checking options
options := []cmp.Option{
testutil.SortMetrics(),
}
if plugin.ShouldIgnoreTimestamp || parser.IgnoreTimestamp {
options = append(options, testutil.IgnoreTime())
}
// Check the resulting metrics
actual := acc.GetTelegrafMetrics()
testutil.RequireMetricsEqual(t, plugin.Expected, actual, options...)
// Special checks
if parser.IgnoreTimestamp {
t.Log("testing ignore-timestamp case")
for i, m := range actual {
expected := plugin.Expected[i]
require.Greaterf(t, m.Time(), expected.Time(), "metric time not after prometheus value in %d", i)
}
}
})
// Run tests as metric version 2
t.Run(fname+"_v2", func(t *testing.T) {
// Load the configuration
cfg := config.NewConfig()
require.NoError(t, cfg.LoadConfig(configFilename))
require.Len(t, cfg.Inputs, 1)
// Tune plugin
plugin := cfg.Inputs[0].Input.(*test.Plugin)
plugin.Path = testdataPath
plugin.UseTypeTag = "_type"
plugin.ExpectedFilename = "expected_v2.out"
parser := plugin.Parser.(*models.RunningParser).Parser.(*Parser)
parser.MetricVersion = 2
if raw, found := plugin.AdditionalParams["headers"]; found {
headers, ok := raw.(map[string]interface{})
require.Truef(t, ok, "unknown header type %T", raw)
parser.Header = make(http.Header)
for k, rv := range headers {
v, ok := rv.(string)
require.Truef(t, ok, "unknown header value type %T for %q", raw, k)
parser.Header.Add(k, v)
}
}
require.NoError(t, plugin.Init())
// Gather data and check errors
var acc testutil.Accumulator
err := plugin.Gather(&acc)
switch len(plugin.ExpectedErrors) {
case 0:
require.NoError(t, err)
case 1:
require.ErrorContains(t, err, plugin.ExpectedErrors[0])
default:
require.Contains(t, plugin.ExpectedErrors, err.Error())
}
// Determine checking options
options := []cmp.Option{
testutil.SortMetrics(),
}
if plugin.ShouldIgnoreTimestamp || parser.IgnoreTimestamp {
options = append(options, testutil.IgnoreTime())
}
// Check the resulting metrics
actual := acc.GetTelegrafMetrics()
testutil.RequireMetricsEqual(t, plugin.Expected, actual, options...)
// Special checks
if parser.IgnoreTimestamp {
t.Log("testing ignore-timestamp case")
for i, m := range actual {
expected := plugin.Expected[i]
require.Greaterf(t, m.Time(), expected.Time(), "metric time not after prometheus value in %d", i)
}
}
})
}
}
func BenchmarkParsingMetricVersion1(b *testing.B) {
plugin := &Parser{MetricVersion: 1}
benchmarkData, err := os.ReadFile(filepath.FromSlash("testcases/benchmark/input.txt"))
require.NoError(b, err)
require.NotEmpty(b, benchmarkData)
for n := 0; n < b.N; n++ {
//nolint:errcheck // Benchmarking so skip the error check to avoid the unnecessary operations
plugin.Parse(benchmarkData)
}
}
func BenchmarkParsingMetricVersion2(b *testing.B) {
plugin := &Parser{MetricVersion: 2}
benchmarkData, err := os.ReadFile(filepath.FromSlash("testcases/benchmark/input.txt"))
require.NoError(b, err)
require.NotEmpty(b, benchmarkData)
for n := 0; n < b.N; n++ {
//nolint:errcheck // Benchmarking so skip the error check to avoid the unnecessary operations
plugin.Parse(benchmarkData)
}
}

View file

@ -0,0 +1,46 @@
process_start_time_seconds,_type=gauge gauge=1606393397
dovecot_build,revision=38ecc424a,version=2.4.devel info=1u
dovecot_auth_success,_type=counter counter=892
dovecot_auth_success_duration_seconds,_type=counter counter=0.085479
dovecot_imap_command,_type=counter,cmd_name=LIST counter=423
dovecot_imap_command,_type=counter,cmd_name=LIST,tagged_reply_state=OK counter=423
dovecot_imap_command,_type=counter,cmd_name=STATUS counter=468
dovecot_imap_command,_type=counter,cmd_name=STATUS,tagged_reply_state=OK counter=468
dovecot_imap_command,_type=counter,cmd_name=SELECT counter=890
dovecot_imap_command,_type=counter,cmd_name=SELECT,tagged_reply_state=OK counter=890
dovecot_imap_command,_type=counter,cmd_name=APPEND counter=449
dovecot_imap_command,_type=counter,cmd_name=APPEND,tagged_reply_state=OK counter=449
dovecot_imap_command,_type=counter,cmd_name=LOGOUT counter=892
dovecot_imap_command,_type=counter,cmd_name=LOGOUT,tagged_reply_state=OK counter=892
dovecot_imap_command,_type=counter,cmd_name=UID\ FETCH counter=888
dovecot_imap_command,_type=counter,cmd_name=UID\ FETCH,tagged_reply_state=OK counter=888
dovecot_imap_command,_type=counter,cmd_name=FETCH counter=2148
dovecot_imap_command,_type=counter,cmd_name=FETCH,tagged_reply_state=OK counter=2148
dovecot_imap_command,_type=counter,cmd_name=STORE counter=794
dovecot_imap_command,_type=counter,cmd_name=STORE,tagged_reply_state=OK counter=794
dovecot_imap_command,_type=counter,cmd_name=EXPUNGE counter=888
dovecot_imap_command,_type=counter,cmd_name=EXPUNGE,tagged_reply_state=OK counter=888
dovecot_imap_command_duration_seconds,_type=counter,cmd_name=LIST counter=0.099115
dovecot_imap_command_duration_seconds,_type=counter,cmd_name=LIST,tagged_reply_state=OK counter=0.099115
dovecot_imap_command_duration_seconds,_type=counter,cmd_name=STATUS counter=0.161195
dovecot_imap_command_duration_seconds,_type=counter,cmd_name=STATUS,tagged_reply_state=OK counter=0.161195
dovecot_imap_command_duration_seconds,_type=counter,cmd_name=SELECT counter=0.184907
dovecot_imap_command_duration_seconds,_type=counter,cmd_name=SELECT,tagged_reply_state=OK counter=0.184907
dovecot_imap_command_duration_seconds,_type=counter,cmd_name=APPEND counter=0.273893
dovecot_imap_command_duration_seconds,_type=counter,cmd_name=APPEND,tagged_reply_state=OK counter=0.273893
dovecot_imap_command_duration_seconds,_type=counter,cmd_name=LOGOUT counter=0.033494
dovecot_imap_command_duration_seconds,_type=counter,cmd_name=LOGOUT,tagged_reply_state=OK counter=0.033494
dovecot_imap_command_duration_seconds,_type=counter,cmd_name=UID\ FETCH counter=0.181319
dovecot_imap_command_duration_seconds,_type=counter,cmd_name=UID\ FETCH,tagged_reply_state=OK counter=0.181319
dovecot_imap_command_duration_seconds,_type=counter,cmd_name=FETCH counter=1.169456
dovecot_imap_command_duration_seconds,_type=counter,cmd_name=FETCH,tagged_reply_state=OK counter=1.169456
dovecot_imap_command_duration_seconds,_type=counter,cmd_name=STORE counter=0.368621
dovecot_imap_command_duration_seconds,_type=counter,cmd_name=STORE,tagged_reply_state=OK counter=0.368621
dovecot_imap_command_duration_seconds,_type=counter,cmd_name=EXPUNGE counter=0.247657
dovecot_imap_command_duration_seconds,_type=counter,cmd_name=EXPUNGE,tagged_reply_state=OK counter=0.247657
dovecot_smtp_command,_type=histogram,cmd_name=LHLO,status_code=250 +Inf=1,10=0,100=1,1000=1,10000=1,100000=1,count=1,sum=0.00002
dovecot_smtp_command,_type=histogram,cmd_name=MAIL,status_code=250 +Inf=1,10=0,100=1,1000=1,10000=1,100000=1,count=1,sum=0.000021
dovecot_smtp_command,_type=histogram,cmd_name=RCPT,status_code=250 +Inf=1,10=0,100=0,1000=1,10000=1,100000=1,count=1,sum=0.000195
dovecot_smtp_command,_type=histogram,cmd_name=DATA,status_code=250 +Inf=1,10=0,100=0,1000=0,10000=1,100000=1,count=1,sum=0.001249
dovecot_smtp_command,_type=histogram,cmd_name=QUIT,status_code=221 +Inf=1,10=1,100=1,1000=1,10000=1,100000=1,count=1,sum=0.00001
dovecot_mail_delivery,_type=histogram +Inf=1,10=0,100=0,1000=1,10000=1,100000=1,count=1,sum=0.000656

View file

@ -0,0 +1,82 @@
openmetric,_type=gauge process_start_time_seconds=1606393397
openmetric,_type=untyped,version=2.4.devel,revision=38ecc424a dovecot_build_info=1u
openmetric,_type=counter dovecot_auth_success=892
openmetric,_type=counter dovecot_auth_success_duration_seconds=0.085479
openmetric,_type=counter,cmd_name=LIST dovecot_imap_command=423
openmetric,_type=counter,cmd_name=LIST,tagged_reply_state=OK dovecot_imap_command=423
openmetric,_type=counter,cmd_name=STATUS dovecot_imap_command=468
openmetric,_type=counter,cmd_name=STATUS,tagged_reply_state=OK dovecot_imap_command=468
openmetric,_type=counter,cmd_name=SELECT dovecot_imap_command=890
openmetric,_type=counter,cmd_name=SELECT,tagged_reply_state=OK dovecot_imap_command=890
openmetric,_type=counter,cmd_name=APPEND dovecot_imap_command=449
openmetric,_type=counter,cmd_name=APPEND,tagged_reply_state=OK dovecot_imap_command=449
openmetric,_type=counter,cmd_name=LOGOUT dovecot_imap_command=892
openmetric,_type=counter,cmd_name=LOGOUT,tagged_reply_state=OK dovecot_imap_command=892
openmetric,_type=counter,cmd_name=UID\ FETCH dovecot_imap_command=888
openmetric,_type=counter,cmd_name=UID\ FETCH,tagged_reply_state=OK dovecot_imap_command=888
openmetric,_type=counter,cmd_name=FETCH dovecot_imap_command=2148
openmetric,_type=counter,cmd_name=FETCH,tagged_reply_state=OK dovecot_imap_command=2148
openmetric,_type=counter,cmd_name=STORE dovecot_imap_command=794
openmetric,_type=counter,cmd_name=STORE,tagged_reply_state=OK dovecot_imap_command=794
openmetric,_type=counter,cmd_name=EXPUNGE dovecot_imap_command=888
openmetric,_type=counter,cmd_name=EXPUNGE,tagged_reply_state=OK dovecot_imap_command=888
openmetric,_type=counter,cmd_name=LIST dovecot_imap_command_duration_seconds=0.099115
openmetric,_type=counter,cmd_name=LIST,tagged_reply_state=OK dovecot_imap_command_duration_seconds=0.099115
openmetric,_type=counter,cmd_name=STATUS dovecot_imap_command_duration_seconds=0.161195
openmetric,_type=counter,cmd_name=STATUS,tagged_reply_state=OK dovecot_imap_command_duration_seconds=0.161195
openmetric,_type=counter,cmd_name=SELECT dovecot_imap_command_duration_seconds=0.184907
openmetric,_type=counter,cmd_name=SELECT,tagged_reply_state=OK dovecot_imap_command_duration_seconds=0.184907
openmetric,_type=counter,cmd_name=APPEND dovecot_imap_command_duration_seconds=0.273893
openmetric,_type=counter,cmd_name=APPEND,tagged_reply_state=OK dovecot_imap_command_duration_seconds=0.273893
openmetric,_type=counter,cmd_name=LOGOUT dovecot_imap_command_duration_seconds=0.033494
openmetric,_type=counter,cmd_name=LOGOUT,tagged_reply_state=OK dovecot_imap_command_duration_seconds=0.033494
openmetric,_type=counter,cmd_name=UID\ FETCH dovecot_imap_command_duration_seconds=0.181319
openmetric,_type=counter,cmd_name=UID\ FETCH,tagged_reply_state=OK dovecot_imap_command_duration_seconds=0.181319
openmetric,_type=counter,cmd_name=FETCH dovecot_imap_command_duration_seconds=1.169456
openmetric,_type=counter,cmd_name=FETCH,tagged_reply_state=OK dovecot_imap_command_duration_seconds=1.169456
openmetric,_type=counter,cmd_name=STORE dovecot_imap_command_duration_seconds=0.368621
openmetric,_type=counter,cmd_name=STORE,tagged_reply_state=OK dovecot_imap_command_duration_seconds=0.368621
openmetric,_type=counter,cmd_name=EXPUNGE dovecot_imap_command_duration_seconds=0.247657
openmetric,_type=counter,cmd_name=EXPUNGE,tagged_reply_state=OK dovecot_imap_command_duration_seconds=0.247657
openmetric,_type=histogram,cmd_name=LHLO,status_code=250 dovecot_smtp_command_count=1,dovecot_smtp_command_sum=0.00002
openmetric,_type=histogram,cmd_name=LHLO,le=10,status_code=250 dovecot_smtp_command_bucket=0
openmetric,_type=histogram,cmd_name=LHLO,le=100,status_code=250 dovecot_smtp_command_bucket=1
openmetric,_type=histogram,cmd_name=LHLO,le=1000,status_code=250 dovecot_smtp_command_bucket=1
openmetric,_type=histogram,cmd_name=LHLO,le=10000,status_code=250 dovecot_smtp_command_bucket=1
openmetric,_type=histogram,cmd_name=LHLO,le=100000,status_code=250 dovecot_smtp_command_bucket=1
openmetric,_type=histogram,cmd_name=LHLO,le=+Inf,status_code=250 dovecot_smtp_command_bucket=1
openmetric,_type=histogram,cmd_name=MAIL,status_code=250 dovecot_smtp_command_count=1,dovecot_smtp_command_sum=0.000021
openmetric,_type=histogram,cmd_name=MAIL,le=10,status_code=250 dovecot_smtp_command_bucket=0
openmetric,_type=histogram,cmd_name=MAIL,le=100,status_code=250 dovecot_smtp_command_bucket=1
openmetric,_type=histogram,cmd_name=MAIL,le=1000,status_code=250 dovecot_smtp_command_bucket=1
openmetric,_type=histogram,cmd_name=MAIL,le=10000,status_code=250 dovecot_smtp_command_bucket=1
openmetric,_type=histogram,cmd_name=MAIL,le=100000,status_code=250 dovecot_smtp_command_bucket=1
openmetric,_type=histogram,cmd_name=MAIL,le=+Inf,status_code=250 dovecot_smtp_command_bucket=1
openmetric,_type=histogram,cmd_name=RCPT,status_code=250 dovecot_smtp_command_count=1,dovecot_smtp_command_sum=0.000195
openmetric,_type=histogram,cmd_name=RCPT,le=10,status_code=250 dovecot_smtp_command_bucket=0
openmetric,_type=histogram,cmd_name=RCPT,le=100,status_code=250 dovecot_smtp_command_bucket=0
openmetric,_type=histogram,cmd_name=RCPT,le=1000,status_code=250 dovecot_smtp_command_bucket=1
openmetric,_type=histogram,cmd_name=RCPT,le=10000,status_code=250 dovecot_smtp_command_bucket=1
openmetric,_type=histogram,cmd_name=RCPT,le=100000,status_code=250 dovecot_smtp_command_bucket=1
openmetric,_type=histogram,cmd_name=RCPT,le=+Inf,status_code=250 dovecot_smtp_command_bucket=1
openmetric,_type=histogram,cmd_name=DATA,status_code=250 dovecot_smtp_command_count=1,dovecot_smtp_command_sum=0.001249
openmetric,_type=histogram,cmd_name=DATA,le=10,status_code=250 dovecot_smtp_command_bucket=0
openmetric,_type=histogram,cmd_name=DATA,le=100,status_code=250 dovecot_smtp_command_bucket=0
openmetric,_type=histogram,cmd_name=DATA,le=1000,status_code=250 dovecot_smtp_command_bucket=0
openmetric,_type=histogram,cmd_name=DATA,le=10000,status_code=250 dovecot_smtp_command_bucket=1
openmetric,_type=histogram,cmd_name=DATA,le=100000,status_code=250 dovecot_smtp_command_bucket=1
openmetric,_type=histogram,cmd_name=DATA,le=+Inf,status_code=250 dovecot_smtp_command_bucket=1
openmetric,_type=histogram,cmd_name=QUIT,status_code=221 dovecot_smtp_command_count=1,dovecot_smtp_command_sum=0.00001
openmetric,_type=histogram,cmd_name=QUIT,le=10,status_code=221 dovecot_smtp_command_bucket=1
openmetric,_type=histogram,cmd_name=QUIT,le=100,status_code=221 dovecot_smtp_command_bucket=1
openmetric,_type=histogram,cmd_name=QUIT,le=1000,status_code=221 dovecot_smtp_command_bucket=1
openmetric,_type=histogram,cmd_name=QUIT,le=10000,status_code=221 dovecot_smtp_command_bucket=1
openmetric,_type=histogram,cmd_name=QUIT,le=100000,status_code=221 dovecot_smtp_command_bucket=1
openmetric,_type=histogram,cmd_name=QUIT,le=+Inf,status_code=221 dovecot_smtp_command_bucket=1
openmetric,_type=histogram dovecot_mail_delivery_count=1,dovecot_mail_delivery_sum=0.000656
openmetric,_type=histogram,le=10 dovecot_mail_delivery_bucket=0
openmetric,_type=histogram,le=100 dovecot_mail_delivery_bucket=0
openmetric,_type=histogram,le=1000 dovecot_mail_delivery_bucket=1
openmetric,_type=histogram,le=10000 dovecot_mail_delivery_bucket=1
openmetric,_type=histogram,le=100000 dovecot_mail_delivery_bucket=1
openmetric,_type=histogram,le=+Inf dovecot_mail_delivery_bucket=1

View file

@ -0,0 +1,107 @@
# HELP process_start_time_seconds Timestamp of service start
# TYPE process_start_time_seconds gauge
process_start_time_seconds 1606393397
# HELP dovecot_build Dovecot build information
# TYPE dovecot_build info
dovecot_build_info{version="2.4.devel",revision="38ecc424a"} 1
# HELP dovecot_auth_success Total number of all events of this kind
# TYPE dovecot_auth_success counter
dovecot_auth_success_total 892
# HELP dovecot_auth_success_duration_seconds Total duration of all events of this kind
# TYPE dovecot_auth_success_duration_seconds counter
dovecot_auth_success_duration_seconds_total 0.085479
# HELP dovecot_imap_command Total number of all events of this kind
# TYPE dovecot_imap_command counter
dovecot_imap_command_total{cmd_name="LIST"} 423
dovecot_imap_command_total{cmd_name="LIST",tagged_reply_state="OK"} 423
dovecot_imap_command_total{cmd_name="STATUS"} 468
dovecot_imap_command_total{cmd_name="STATUS",tagged_reply_state="OK"} 468
dovecot_imap_command_total{cmd_name="SELECT"} 890
dovecot_imap_command_total{cmd_name="SELECT",tagged_reply_state="OK"} 890
dovecot_imap_command_total{cmd_name="APPEND"} 449
dovecot_imap_command_total{cmd_name="APPEND",tagged_reply_state="OK"} 449
dovecot_imap_command_total{cmd_name="LOGOUT"} 892
dovecot_imap_command_total{cmd_name="LOGOUT",tagged_reply_state="OK"} 892
dovecot_imap_command_total{cmd_name="UID FETCH"} 888
dovecot_imap_command_total{cmd_name="UID FETCH",tagged_reply_state="OK"} 888
dovecot_imap_command_total{cmd_name="FETCH"} 2148
dovecot_imap_command_total{cmd_name="FETCH",tagged_reply_state="OK"} 2148
dovecot_imap_command_total{cmd_name="STORE"} 794
dovecot_imap_command_total{cmd_name="STORE",tagged_reply_state="OK"} 794
dovecot_imap_command_total{cmd_name="EXPUNGE"} 888
dovecot_imap_command_total{cmd_name="EXPUNGE",tagged_reply_state="OK"} 888
dovecot_imap_command_count 7840
# HELP dovecot_imap_command_duration_seconds Total duration of all events of this kind
# TYPE dovecot_imap_command_duration_seconds counter
dovecot_imap_command_duration_seconds_total{cmd_name="LIST"} 0.099115
dovecot_imap_command_duration_seconds_total{cmd_name="LIST",tagged_reply_state="OK"} 0.099115
dovecot_imap_command_duration_seconds_total{cmd_name="STATUS"} 0.161195
dovecot_imap_command_duration_seconds_total{cmd_name="STATUS",tagged_reply_state="OK"} 0.161195
dovecot_imap_command_duration_seconds_total{cmd_name="SELECT"} 0.184907
dovecot_imap_command_duration_seconds_total{cmd_name="SELECT",tagged_reply_state="OK"} 0.184907
dovecot_imap_command_duration_seconds_total{cmd_name="APPEND"} 0.273893
dovecot_imap_command_duration_seconds_total{cmd_name="APPEND",tagged_reply_state="OK"} 0.273893
dovecot_imap_command_duration_seconds_total{cmd_name="LOGOUT"} 0.033494
dovecot_imap_command_duration_seconds_total{cmd_name="LOGOUT",tagged_reply_state="OK"} 0.033494
dovecot_imap_command_duration_seconds_total{cmd_name="UID FETCH"} 0.181319
dovecot_imap_command_duration_seconds_total{cmd_name="UID FETCH",tagged_reply_state="OK"} 0.181319
dovecot_imap_command_duration_seconds_total{cmd_name="FETCH"} 1.169456
dovecot_imap_command_duration_seconds_total{cmd_name="FETCH",tagged_reply_state="OK"} 1.169456
dovecot_imap_command_duration_seconds_total{cmd_name="STORE"} 0.368621
dovecot_imap_command_duration_seconds_total{cmd_name="STORE",tagged_reply_state="OK"} 0.368621
dovecot_imap_command_duration_seconds_total{cmd_name="EXPUNGE"} 0.247657
dovecot_imap_command_duration_seconds_total{cmd_name="EXPUNGE",tagged_reply_state="OK"} 0.247657
dovecot_imap_command_duration_seconds_sum 2.719657
# HELP dovecot_smtp_command Histogram
# TYPE dovecot_smtp_command histogram
dovecot_smtp_command_bucket{cmd_name="LHLO",status_code="250",le="10"} 0
dovecot_smtp_command_bucket{cmd_name="LHLO",status_code="250",le="100"} 1
dovecot_smtp_command_bucket{cmd_name="LHLO",status_code="250",le="1000"} 1
dovecot_smtp_command_bucket{cmd_name="LHLO",status_code="250",le="10000"} 1
dovecot_smtp_command_bucket{cmd_name="LHLO",status_code="250",le="100000"} 1
dovecot_smtp_command_bucket{cmd_name="LHLO",status_code="250",le="+Inf"} 1
dovecot_smtp_command_sum{cmd_name="LHLO",status_code="250"} 0.000020
dovecot_smtp_command_count{cmd_name="LHLO",status_code="250"} 1
dovecot_smtp_command_bucket{cmd_name="MAIL",status_code="250",le="10"} 0
dovecot_smtp_command_bucket{cmd_name="MAIL",status_code="250",le="100"} 1
dovecot_smtp_command_bucket{cmd_name="MAIL",status_code="250",le="1000"} 1
dovecot_smtp_command_bucket{cmd_name="MAIL",status_code="250",le="10000"} 1
dovecot_smtp_command_bucket{cmd_name="MAIL",status_code="250",le="100000"} 1
dovecot_smtp_command_bucket{cmd_name="MAIL",status_code="250",le="+Inf"} 1
dovecot_smtp_command_sum{cmd_name="MAIL",status_code="250"} 0.000021
dovecot_smtp_command_count{cmd_name="MAIL",status_code="250"} 1
dovecot_smtp_command_bucket{cmd_name="RCPT",status_code="250",le="10"} 0
dovecot_smtp_command_bucket{cmd_name="RCPT",status_code="250",le="100"} 0
dovecot_smtp_command_bucket{cmd_name="RCPT",status_code="250",le="1000"} 1
dovecot_smtp_command_bucket{cmd_name="RCPT",status_code="250",le="10000"} 1
dovecot_smtp_command_bucket{cmd_name="RCPT",status_code="250",le="100000"} 1
dovecot_smtp_command_bucket{cmd_name="RCPT",status_code="250",le="+Inf"} 1
dovecot_smtp_command_sum{cmd_name="RCPT",status_code="250"} 0.000195
dovecot_smtp_command_count{cmd_name="RCPT",status_code="250"} 1
dovecot_smtp_command_bucket{cmd_name="DATA",status_code="250",le="10"} 0
dovecot_smtp_command_bucket{cmd_name="DATA",status_code="250",le="100"} 0
dovecot_smtp_command_bucket{cmd_name="DATA",status_code="250",le="1000"} 0
dovecot_smtp_command_bucket{cmd_name="DATA",status_code="250",le="10000"} 1
dovecot_smtp_command_bucket{cmd_name="DATA",status_code="250",le="100000"} 1
dovecot_smtp_command_bucket{cmd_name="DATA",status_code="250",le="+Inf"} 1
dovecot_smtp_command_sum{cmd_name="DATA",status_code="250"} 0.001249
dovecot_smtp_command_count{cmd_name="DATA",status_code="250"} 1
dovecot_smtp_command_bucket{cmd_name="QUIT",status_code="221",le="10"} 1
dovecot_smtp_command_bucket{cmd_name="QUIT",status_code="221",le="100"} 1
dovecot_smtp_command_bucket{cmd_name="QUIT",status_code="221",le="1000"} 1
dovecot_smtp_command_bucket{cmd_name="QUIT",status_code="221",le="10000"} 1
dovecot_smtp_command_bucket{cmd_name="QUIT",status_code="221",le="100000"} 1
dovecot_smtp_command_bucket{cmd_name="QUIT",status_code="221",le="+Inf"} 1
dovecot_smtp_command_sum{cmd_name="QUIT",status_code="221"} 0.000010
dovecot_smtp_command_count{cmd_name="QUIT",status_code="221"} 1
# HELP dovecot_mail_delivery Histogram
# TYPE dovecot_mail_delivery histogram
dovecot_mail_delivery_bucket{le="10"} 0
dovecot_mail_delivery_bucket{le="100"} 0
dovecot_mail_delivery_bucket{le="1000"} 1
dovecot_mail_delivery_bucket{le="10000"} 1
dovecot_mail_delivery_bucket{le="100000"} 1
dovecot_mail_delivery_bucket{le="+Inf"} 1
dovecot_mail_delivery_sum 0.000656
dovecot_mail_delivery_count 1
# EOF

View file

@ -0,0 +1,4 @@
[[inputs.test]]
files = ["input.txt"]
data_format = "openmetrics"

View file

@ -0,0 +1,4 @@
acme_http_router_request_seconds,_type=summary,unit=seconds,path=/api/v1,method=GET sum=9036.32,count=807283.0,created=1605281325.0,0.5=1.29854,0.9=54.85479,0.99=6884.32324
acme_http_router_request_seconds,_type=summary,unit=seconds,path=/api/v2,method=POST sum=479.3,count=34.0,created=1605281325.0,0.5=0.85412,0.9=1.15429,0.99=3698.48132
go_goroutines,_type=gauge gauge=69
process_cpu_seconds,_type=counter,unit=seconds counter=4200722.46

View file

@ -0,0 +1,10 @@
openmetric,_type=summary,method=GET,path=/api/v1,unit=seconds acme_http_router_request_seconds_count=807283,acme_http_router_request_seconds_created=1605281325,acme_http_router_request_seconds_sum=9036.32
openmetric,_type=summary,method=GET,path=/api/v1,quantile=0.5,unit=seconds acme_http_router_request_seconds=1.29854
openmetric,_type=summary,method=GET,path=/api/v1,quantile=0.9,unit=seconds acme_http_router_request_seconds=54.85479
openmetric,_type=summary,method=GET,path=/api/v1,quantile=0.99,unit=seconds acme_http_router_request_seconds=6884.32324
openmetric,_type=summary,method=POST,path=/api/v2,unit=seconds acme_http_router_request_seconds_count=34,acme_http_router_request_seconds_created=1605281325,acme_http_router_request_seconds_sum=479.3
openmetric,_type=summary,method=POST,path=/api/v2,quantile=0.5,unit=seconds acme_http_router_request_seconds=0.85412
openmetric,_type=summary,method=POST,path=/api/v2,quantile=0.9,unit=seconds acme_http_router_request_seconds=1.15429
openmetric,_type=summary,method=POST,path=/api/v2,quantile=0.99,unit=seconds acme_http_router_request_seconds=3698.48132
openmetric,_type=gauge go_goroutines=69
openmetric,_type=counter,unit=seconds process_cpu_seconds=4200722.46

View file

@ -0,0 +1,23 @@
# TYPE acme_http_router_request_seconds summary
# UNIT acme_http_router_request_seconds seconds
# HELP acme_http_router_request_seconds Latency though all of ACME's HTTP request router.
acme_http_router_request_seconds_sum{path="/api/v1",method="GET"} 9036.32
acme_http_router_request_seconds_count{path="/api/v1",method="GET"} 807283.0
acme_http_router_request_seconds{path="/api/v1",method="GET",quantile="0.5"} 1.29854
acme_http_router_request_seconds{path="/api/v1",method="GET",quantile="0.9"} 54.85479
acme_http_router_request_seconds{path="/api/v1",method="GET",quantile="0.99"} 6884.32324
acme_http_router_request_seconds_created{path="/api/v1",method="GET"} 1605281325.0
acme_http_router_request_seconds_sum{path="/api/v2",method="POST"} 479.3
acme_http_router_request_seconds_count{path="/api/v2",method="POST"} 34.0
acme_http_router_request_seconds_created{path="/api/v2",method="POST"} 1605281325.0
acme_http_router_request_seconds{path="/api/v2",method="POST",quantile="0.5"} 0.85412
acme_http_router_request_seconds{path="/api/v2",method="POST",quantile="0.9"} 1.15429
acme_http_router_request_seconds{path="/api/v2",method="POST",quantile="0.99"} 3698.48132
# TYPE go_goroutines gauge
# HELP go_goroutines Number of goroutines that currently exist.
go_goroutines 69
# TYPE process_cpu_seconds counter
# UNIT process_cpu_seconds seconds
# HELP process_cpu_seconds Total user and system CPU time spent in seconds.
process_cpu_seconds_total 4.20072246e+06
# EOF

View file

@ -0,0 +1,4 @@
[[inputs.test]]
files = ["input.txt"]
data_format = "openmetrics"

View file

@ -0,0 +1,46 @@
process_start_time_seconds,_type=gauge gauge=1606393397
dovecot_build,revision=38ecc424a,version=2.4.devel info=1u
dovecot_auth_success,_type=counter counter=892
dovecot_auth_success_duration_seconds,_type=counter counter=0.085479
dovecot_imap_command,_type=counter,cmd_name=LIST counter=423
dovecot_imap_command,_type=counter,cmd_name=LIST,tagged_reply_state=OK counter=423
dovecot_imap_command,_type=counter,cmd_name=STATUS counter=468
dovecot_imap_command,_type=counter,cmd_name=STATUS,tagged_reply_state=OK counter=468
dovecot_imap_command,_type=counter,cmd_name=SELECT counter=890
dovecot_imap_command,_type=counter,cmd_name=SELECT,tagged_reply_state=OK counter=890
dovecot_imap_command,_type=counter,cmd_name=APPEND counter=449
dovecot_imap_command,_type=counter,cmd_name=APPEND,tagged_reply_state=OK counter=449
dovecot_imap_command,_type=counter,cmd_name=LOGOUT counter=892
dovecot_imap_command,_type=counter,cmd_name=LOGOUT,tagged_reply_state=OK counter=892
dovecot_imap_command,_type=counter,cmd_name=UID\ FETCH counter=888
dovecot_imap_command,_type=counter,cmd_name=UID\ FETCH,tagged_reply_state=OK counter=888
dovecot_imap_command,_type=counter,cmd_name=FETCH counter=2148
dovecot_imap_command,_type=counter,cmd_name=FETCH,tagged_reply_state=OK counter=2148
dovecot_imap_command,_type=counter,cmd_name=STORE counter=794
dovecot_imap_command,_type=counter,cmd_name=STORE,tagged_reply_state=OK counter=794
dovecot_imap_command,_type=counter,cmd_name=EXPUNGE counter=888
dovecot_imap_command,_type=counter,cmd_name=EXPUNGE,tagged_reply_state=OK counter=888
dovecot_imap_command_duration_seconds,_type=counter,cmd_name=LIST counter=0.099115
dovecot_imap_command_duration_seconds,_type=counter,cmd_name=LIST,tagged_reply_state=OK counter=0.099115
dovecot_imap_command_duration_seconds,_type=counter,cmd_name=STATUS counter=0.161195
dovecot_imap_command_duration_seconds,_type=counter,cmd_name=STATUS,tagged_reply_state=OK counter=0.161195
dovecot_imap_command_duration_seconds,_type=counter,cmd_name=SELECT counter=0.184907
dovecot_imap_command_duration_seconds,_type=counter,cmd_name=SELECT,tagged_reply_state=OK counter=0.184907
dovecot_imap_command_duration_seconds,_type=counter,cmd_name=APPEND counter=0.273893
dovecot_imap_command_duration_seconds,_type=counter,cmd_name=APPEND,tagged_reply_state=OK counter=0.273893
dovecot_imap_command_duration_seconds,_type=counter,cmd_name=LOGOUT counter=0.033494
dovecot_imap_command_duration_seconds,_type=counter,cmd_name=LOGOUT,tagged_reply_state=OK counter=0.033494
dovecot_imap_command_duration_seconds,_type=counter,cmd_name=UID\ FETCH counter=0.181319
dovecot_imap_command_duration_seconds,_type=counter,cmd_name=UID\ FETCH,tagged_reply_state=OK counter=0.181319
dovecot_imap_command_duration_seconds,_type=counter,cmd_name=FETCH counter=1.169456
dovecot_imap_command_duration_seconds,_type=counter,cmd_name=FETCH,tagged_reply_state=OK counter=1.169456
dovecot_imap_command_duration_seconds,_type=counter,cmd_name=STORE counter=0.368621
dovecot_imap_command_duration_seconds,_type=counter,cmd_name=STORE,tagged_reply_state=OK counter=0.368621
dovecot_imap_command_duration_seconds,_type=counter,cmd_name=EXPUNGE counter=0.247657
dovecot_imap_command_duration_seconds,_type=counter,cmd_name=EXPUNGE,tagged_reply_state=OK counter=0.247657
dovecot_smtp_command,_type=histogram,cmd_name=LHLO,status_code=250 +Inf=1,10=0,100=1,1000=1,10000=1,100000=1,count=1,sum=0.00002
dovecot_smtp_command,_type=histogram,cmd_name=MAIL,status_code=250 +Inf=1,10=0,100=1,1000=1,10000=1,100000=1,count=1,sum=0.000021
dovecot_smtp_command,_type=histogram,cmd_name=RCPT,status_code=250 +Inf=1,10=0,100=0,1000=1,10000=1,100000=1,count=1,sum=0.000195
dovecot_smtp_command,_type=histogram,cmd_name=DATA,status_code=250 +Inf=1,10=0,100=0,1000=0,10000=1,100000=1,count=1,sum=0.001249
dovecot_smtp_command,_type=histogram,cmd_name=QUIT,status_code=221 +Inf=1,10=1,100=1,1000=1,10000=1,100000=1,count=1,sum=0.00001
dovecot_mail_delivery,_type=histogram +Inf=1,10=0,100=0,1000=1,10000=1,100000=1,count=1,sum=0.000656

View file

@ -0,0 +1,82 @@
openmetric,_type=gauge process_start_time_seconds=1606393397
openmetric,_type=untyped,version=2.4.devel,revision=38ecc424a dovecot_build_info=1u
openmetric,_type=counter dovecot_auth_success=892
openmetric,_type=counter dovecot_auth_success_duration_seconds=0.085479
openmetric,_type=counter,cmd_name=LIST dovecot_imap_command=423
openmetric,_type=counter,cmd_name=LIST,tagged_reply_state=OK dovecot_imap_command=423
openmetric,_type=counter,cmd_name=STATUS dovecot_imap_command=468
openmetric,_type=counter,cmd_name=STATUS,tagged_reply_state=OK dovecot_imap_command=468
openmetric,_type=counter,cmd_name=SELECT dovecot_imap_command=890
openmetric,_type=counter,cmd_name=SELECT,tagged_reply_state=OK dovecot_imap_command=890
openmetric,_type=counter,cmd_name=APPEND dovecot_imap_command=449
openmetric,_type=counter,cmd_name=APPEND,tagged_reply_state=OK dovecot_imap_command=449
openmetric,_type=counter,cmd_name=LOGOUT dovecot_imap_command=892
openmetric,_type=counter,cmd_name=LOGOUT,tagged_reply_state=OK dovecot_imap_command=892
openmetric,_type=counter,cmd_name=UID\ FETCH dovecot_imap_command=888
openmetric,_type=counter,cmd_name=UID\ FETCH,tagged_reply_state=OK dovecot_imap_command=888
openmetric,_type=counter,cmd_name=FETCH dovecot_imap_command=2148
openmetric,_type=counter,cmd_name=FETCH,tagged_reply_state=OK dovecot_imap_command=2148
openmetric,_type=counter,cmd_name=STORE dovecot_imap_command=794
openmetric,_type=counter,cmd_name=STORE,tagged_reply_state=OK dovecot_imap_command=794
openmetric,_type=counter,cmd_name=EXPUNGE dovecot_imap_command=888
openmetric,_type=counter,cmd_name=EXPUNGE,tagged_reply_state=OK dovecot_imap_command=888
openmetric,_type=counter,cmd_name=LIST dovecot_imap_command_duration_seconds=0.099115
openmetric,_type=counter,cmd_name=LIST,tagged_reply_state=OK dovecot_imap_command_duration_seconds=0.099115
openmetric,_type=counter,cmd_name=STATUS dovecot_imap_command_duration_seconds=0.161195
openmetric,_type=counter,cmd_name=STATUS,tagged_reply_state=OK dovecot_imap_command_duration_seconds=0.161195
openmetric,_type=counter,cmd_name=SELECT dovecot_imap_command_duration_seconds=0.184907
openmetric,_type=counter,cmd_name=SELECT,tagged_reply_state=OK dovecot_imap_command_duration_seconds=0.184907
openmetric,_type=counter,cmd_name=APPEND dovecot_imap_command_duration_seconds=0.273893
openmetric,_type=counter,cmd_name=APPEND,tagged_reply_state=OK dovecot_imap_command_duration_seconds=0.273893
openmetric,_type=counter,cmd_name=LOGOUT dovecot_imap_command_duration_seconds=0.033494
openmetric,_type=counter,cmd_name=LOGOUT,tagged_reply_state=OK dovecot_imap_command_duration_seconds=0.033494
openmetric,_type=counter,cmd_name=UID\ FETCH dovecot_imap_command_duration_seconds=0.181319
openmetric,_type=counter,cmd_name=UID\ FETCH,tagged_reply_state=OK dovecot_imap_command_duration_seconds=0.181319
openmetric,_type=counter,cmd_name=FETCH dovecot_imap_command_duration_seconds=1.169456
openmetric,_type=counter,cmd_name=FETCH,tagged_reply_state=OK dovecot_imap_command_duration_seconds=1.169456
openmetric,_type=counter,cmd_name=STORE dovecot_imap_command_duration_seconds=0.368621
openmetric,_type=counter,cmd_name=STORE,tagged_reply_state=OK dovecot_imap_command_duration_seconds=0.368621
openmetric,_type=counter,cmd_name=EXPUNGE dovecot_imap_command_duration_seconds=0.247657
openmetric,_type=counter,cmd_name=EXPUNGE,tagged_reply_state=OK dovecot_imap_command_duration_seconds=0.247657
openmetric,_type=histogram,cmd_name=LHLO,status_code=250 dovecot_smtp_command_count=1,dovecot_smtp_command_sum=0.00002
openmetric,_type=histogram,cmd_name=LHLO,le=10,status_code=250 dovecot_smtp_command_bucket=0
openmetric,_type=histogram,cmd_name=LHLO,le=100,status_code=250 dovecot_smtp_command_bucket=1
openmetric,_type=histogram,cmd_name=LHLO,le=1000,status_code=250 dovecot_smtp_command_bucket=1
openmetric,_type=histogram,cmd_name=LHLO,le=10000,status_code=250 dovecot_smtp_command_bucket=1
openmetric,_type=histogram,cmd_name=LHLO,le=100000,status_code=250 dovecot_smtp_command_bucket=1
openmetric,_type=histogram,cmd_name=LHLO,le=+Inf,status_code=250 dovecot_smtp_command_bucket=1
openmetric,_type=histogram,cmd_name=MAIL,status_code=250 dovecot_smtp_command_count=1,dovecot_smtp_command_sum=0.000021
openmetric,_type=histogram,cmd_name=MAIL,le=10,status_code=250 dovecot_smtp_command_bucket=0
openmetric,_type=histogram,cmd_name=MAIL,le=100,status_code=250 dovecot_smtp_command_bucket=1
openmetric,_type=histogram,cmd_name=MAIL,le=1000,status_code=250 dovecot_smtp_command_bucket=1
openmetric,_type=histogram,cmd_name=MAIL,le=10000,status_code=250 dovecot_smtp_command_bucket=1
openmetric,_type=histogram,cmd_name=MAIL,le=100000,status_code=250 dovecot_smtp_command_bucket=1
openmetric,_type=histogram,cmd_name=MAIL,le=+Inf,status_code=250 dovecot_smtp_command_bucket=1
openmetric,_type=histogram,cmd_name=RCPT,status_code=250 dovecot_smtp_command_count=1,dovecot_smtp_command_sum=0.000195
openmetric,_type=histogram,cmd_name=RCPT,le=10,status_code=250 dovecot_smtp_command_bucket=0
openmetric,_type=histogram,cmd_name=RCPT,le=100,status_code=250 dovecot_smtp_command_bucket=0
openmetric,_type=histogram,cmd_name=RCPT,le=1000,status_code=250 dovecot_smtp_command_bucket=1
openmetric,_type=histogram,cmd_name=RCPT,le=10000,status_code=250 dovecot_smtp_command_bucket=1
openmetric,_type=histogram,cmd_name=RCPT,le=100000,status_code=250 dovecot_smtp_command_bucket=1
openmetric,_type=histogram,cmd_name=RCPT,le=+Inf,status_code=250 dovecot_smtp_command_bucket=1
openmetric,_type=histogram,cmd_name=DATA,status_code=250 dovecot_smtp_command_count=1,dovecot_smtp_command_sum=0.001249
openmetric,_type=histogram,cmd_name=DATA,le=10,status_code=250 dovecot_smtp_command_bucket=0
openmetric,_type=histogram,cmd_name=DATA,le=100,status_code=250 dovecot_smtp_command_bucket=0
openmetric,_type=histogram,cmd_name=DATA,le=1000,status_code=250 dovecot_smtp_command_bucket=0
openmetric,_type=histogram,cmd_name=DATA,le=10000,status_code=250 dovecot_smtp_command_bucket=1
openmetric,_type=histogram,cmd_name=DATA,le=100000,status_code=250 dovecot_smtp_command_bucket=1
openmetric,_type=histogram,cmd_name=DATA,le=+Inf,status_code=250 dovecot_smtp_command_bucket=1
openmetric,_type=histogram,cmd_name=QUIT,status_code=221 dovecot_smtp_command_count=1,dovecot_smtp_command_sum=0.00001
openmetric,_type=histogram,cmd_name=QUIT,le=10,status_code=221 dovecot_smtp_command_bucket=1
openmetric,_type=histogram,cmd_name=QUIT,le=100,status_code=221 dovecot_smtp_command_bucket=1
openmetric,_type=histogram,cmd_name=QUIT,le=1000,status_code=221 dovecot_smtp_command_bucket=1
openmetric,_type=histogram,cmd_name=QUIT,le=10000,status_code=221 dovecot_smtp_command_bucket=1
openmetric,_type=histogram,cmd_name=QUIT,le=100000,status_code=221 dovecot_smtp_command_bucket=1
openmetric,_type=histogram,cmd_name=QUIT,le=+Inf,status_code=221 dovecot_smtp_command_bucket=1
openmetric,_type=histogram dovecot_mail_delivery_count=1,dovecot_mail_delivery_sum=0.000656
openmetric,_type=histogram,le=10 dovecot_mail_delivery_bucket=0
openmetric,_type=histogram,le=100 dovecot_mail_delivery_bucket=0
openmetric,_type=histogram,le=1000 dovecot_mail_delivery_bucket=1
openmetric,_type=histogram,le=10000 dovecot_mail_delivery_bucket=1
openmetric,_type=histogram,le=100000 dovecot_mail_delivery_bucket=1
openmetric,_type=histogram,le=+Inf dovecot_mail_delivery_bucket=1

View file

@ -0,0 +1,6 @@
[[inputs.test]]
files = ["input.bin"]
data_format = "openmetrics"
[inputs.test.additional_params]
headers = {Content-Type = "application/openmetrics-protobuf;version=1.0.0"}

View file

@ -0,0 +1 @@
device_versioning,_type=untyped,location=office,device=machine,version=1.29.2,environment=production,build=42 info=1u

View file

@ -0,0 +1 @@
openmetric,_type=untyped,location=office,device=machine,version=1.29.2,environment=production,build=42 device_versioning_info=1u

View file

@ -0,0 +1,14 @@

device_versioning"A test info metric*f

locationoffice

devicemachine=2;

version1.29.2

environment
production
build42

View file

@ -0,0 +1,6 @@
[[inputs.test]]
files = ["input.bin"]
data_format = "openmetrics"
[inputs.test.additional_params]
headers = {Content-Type = "application/openmetrics-protobuf;version=1.0.0"}

View file

@ -0,0 +1 @@
get_token_fail_count,_type=counter counter=8

View file

@ -0,0 +1 @@
openmetric,_type=counter get_token_fail_count=8

View file

@ -0,0 +1,4 @@
# TYPE get_token_fail_count counter
# HELP get_token_fail_count help
get_token_fail_count_total 8 123 # {a="b"} 0.5
# EOF

View file

@ -0,0 +1,4 @@
[[inputs.test]]
files = ["input.txt"]
data_format = "openmetrics"

View file

@ -0,0 +1,3 @@
go_memstats_gc_cpu_fraction,_type=gauge gauge=-0.00014404354379774563
go_memstats_gc_sys_bytes,_type=gauge gauge=60936192
go_memstats_heap_alloc_bytes,_type=gauge gauge=1581062048

View file

@ -0,0 +1,3 @@
openmetric,_type=gauge go_memstats_gc_cpu_fraction=-0.00014404354379774563
openmetric,_type=gauge go_memstats_gc_sys_bytes=60936192
openmetric,_type=gauge go_memstats_heap_alloc_bytes=1581062048

View file

@ -0,0 +1,10 @@
# HELP go_memstats_gc_cpu_fraction The fraction of this program's available CPU time used by the GC since the program started.
# TYPE go_memstats_gc_cpu_fraction gauge
go_memstats_gc_cpu_fraction -0.00014404354379774563
# HELP go_memstats_gc_sys_bytes Number of bytes used for garbage collection system metadata.
# TYPE go_memstats_gc_sys_bytes gauge
go_memstats_gc_sys_bytes 6.0936192e+07
# HELP go_memstats_heap_alloc_bytes Number of heap bytes allocated and still in use.
# TYPE go_memstats_heap_alloc_bytes gauge
go_memstats_heap_alloc_bytes 1.581062048e+09
# EOF

View file

@ -0,0 +1,3 @@
[[inputs.test]]
files = ["input.txt"]
data_format = "openmetrics"

View file

@ -0,0 +1 @@
apiserver_request_latencies_microseconds,_type=histogram,unit=microseconds,resource=bindings,verb=POST +Inf=2025,125000=1994,1e+06=2005,250000=1997,2e+06=2012,4e+06=2017,500000=2000,8e+06=2024,count=2025,sum=102726334

View file

@ -0,0 +1,9 @@
openmetric,_type=histogram,unit=microseconds,resource=bindings,verb=POST apiserver_request_latencies_microseconds_count=2025,apiserver_request_latencies_microseconds_sum=102726334
openmetric,_type=histogram,le=125000,unit=microseconds,resource=bindings,verb=POST apiserver_request_latencies_microseconds_bucket=1994
openmetric,_type=histogram,le=250000,unit=microseconds,resource=bindings,verb=POST apiserver_request_latencies_microseconds_bucket=1997
openmetric,_type=histogram,le=500000,unit=microseconds,resource=bindings,verb=POST apiserver_request_latencies_microseconds_bucket=2000
openmetric,_type=histogram,le=1e+06,unit=microseconds,resource=bindings,verb=POST apiserver_request_latencies_microseconds_bucket=2005
openmetric,_type=histogram,le=2e+06,unit=microseconds,resource=bindings,verb=POST apiserver_request_latencies_microseconds_bucket=2012
openmetric,_type=histogram,le=4e+06,unit=microseconds,resource=bindings,verb=POST apiserver_request_latencies_microseconds_bucket=2017
openmetric,_type=histogram,le=8e+06,unit=microseconds,resource=bindings,verb=POST apiserver_request_latencies_microseconds_bucket=2024
openmetric,_type=histogram,le=+Inf,unit=microseconds,resource=bindings,verb=POST apiserver_request_latencies_microseconds_bucket=2025

View file

@ -0,0 +1,14 @@
# HELP apiserver_request_latencies_microseconds Response latency distribution in microseconds for each verb, resource and client.
# TYPE apiserver_request_latencies_microseconds histogram
# UNIT apiserver_request_latencies_microseconds microseconds
apiserver_request_latencies_microseconds_bucket{resource="bindings",verb="POST",le="125000"} 1994
apiserver_request_latencies_microseconds_bucket{resource="bindings",verb="POST",le="250000"} 1997
apiserver_request_latencies_microseconds_bucket{resource="bindings",verb="POST",le="500000"} 2000
apiserver_request_latencies_microseconds_bucket{resource="bindings",verb="POST",le="1e+06"} 2005
apiserver_request_latencies_microseconds_bucket{resource="bindings",verb="POST",le="2e+06"} 2012
apiserver_request_latencies_microseconds_bucket{resource="bindings",verb="POST",le="4e+06"} 2017
apiserver_request_latencies_microseconds_bucket{resource="bindings",verb="POST",le="8e+06"} 2024
apiserver_request_latencies_microseconds_bucket{resource="bindings",verb="POST",le="+Inf"} 2025
apiserver_request_latencies_microseconds_sum{resource="bindings",verb="POST"} 1.02726334e+08
apiserver_request_latencies_microseconds_count{resource="bindings",verb="POST"} 2025
# EOF

View file

@ -0,0 +1,4 @@
[[inputs.test]]
files = ["input.txt"]
data_format = "openmetrics"

View file

@ -0,0 +1 @@
apiserver_request_latencies_microseconds,_type=histogram,unit=microseconds,resource=bindings,verb=POST +Inf=2025,125000=1994,1e+06=2005,250000=1997,2e+06=2012,4e+06=2017,500000=2000,8e+06=2024,count=2025,sum=102726334

View file

@ -0,0 +1,9 @@
openmetric,_type=histogram,unit=microseconds,resource=bindings,verb=POST apiserver_request_latencies_microseconds_count=2025,apiserver_request_latencies_microseconds_sum=102726334
openmetric,_type=histogram,le=125000,unit=microseconds,resource=bindings,verb=POST apiserver_request_latencies_microseconds_bucket=1994
openmetric,_type=histogram,le=250000,unit=microseconds,resource=bindings,verb=POST apiserver_request_latencies_microseconds_bucket=1997
openmetric,_type=histogram,le=500000,unit=microseconds,resource=bindings,verb=POST apiserver_request_latencies_microseconds_bucket=2000
openmetric,_type=histogram,le=1e+06,unit=microseconds,resource=bindings,verb=POST apiserver_request_latencies_microseconds_bucket=2005
openmetric,_type=histogram,le=2e+06,unit=microseconds,resource=bindings,verb=POST apiserver_request_latencies_microseconds_bucket=2012
openmetric,_type=histogram,le=4e+06,unit=microseconds,resource=bindings,verb=POST apiserver_request_latencies_microseconds_bucket=2017
openmetric,_type=histogram,le=8e+06,unit=microseconds,resource=bindings,verb=POST apiserver_request_latencies_microseconds_bucket=2024
openmetric,_type=histogram,le=+Inf,unit=microseconds,resource=bindings,verb=POST apiserver_request_latencies_microseconds_bucket=2025

View file

@ -0,0 +1,14 @@
# HELP apiserver_request_latencies_microseconds Response latency distribution in microseconds for each verb, resource and client.
# TYPE apiserver_request_latencies_microseconds histogram
# UNIT apiserver_request_latencies_microseconds microseconds
apiserver_request_latencies_microseconds_bucket{resource="bindings",verb="POST",le="125000"} 1994
apiserver_request_latencies_microseconds_bucket{resource="bindings",verb="POST",le="250000"} 1997
apiserver_request_latencies_microseconds_bucket{resource="bindings",verb="POST",le="500000"} 2000
apiserver_request_latencies_microseconds_bucket{resource="bindings",verb="POST",le="1e+06"} 2005
apiserver_request_latencies_microseconds_bucket{resource="bindings",verb="POST",le="2e+06"} 2012
apiserver_request_latencies_microseconds_bucket{resource="bindings",verb="POST",le="4e+06"} 2017
apiserver_request_latencies_microseconds_bucket{resource="bindings",verb="POST",le="8e+06"} 2024
apiserver_request_latencies_microseconds_bucket{resource="bindings",verb="POST",le="+Inf"} 2025
apiserver_request_latencies_microseconds_sum{resource="bindings",verb="POST"} 1.02726334e+08
apiserver_request_latencies_microseconds_count{resource="bindings",verb="POST"} 2025
# EOF

View file

@ -0,0 +1,4 @@
[[inputs.test]]
files = ["input.txt"]
data_format = "openmetrics"

View file

@ -0,0 +1 @@
cadvisor_version,_type=untyped,dockerVersion=1.8.2,kernelVersion=3.10.0-229.20.1.el7.x86_64,osVersion=CentOS\ Linux\ 7\ (Core) info=1u

View file

@ -0,0 +1 @@
openmetric,_type=untyped,dockerVersion=1.8.2,kernelVersion=3.10.0-229.20.1.el7.x86_64,osVersion=CentOS\ Linux\ 7\ (Core) cadvisor_version_info=1u

View file

@ -0,0 +1,4 @@
# HELP cadvisor_version A metric with a constant '1' value labeled by kernel version, OS version, docker version, cadvisor version & cadvisor revision.
# TYPE cadvisor_version info
cadvisor_version{cadvisorRevision="",cadvisorVersion="",dockerVersion="1.8.2",kernelVersion="3.10.0-229.20.1.el7.x86_64",osVersion="CentOS Linux 7 (Core)"} 1
# EOF

View file

@ -0,0 +1,3 @@
[[inputs.test]]
files = ["input.txt"]
data_format = "openmetrics"

View file

@ -0,0 +1,2 @@
alarm_system_state,_type=untyped,entity=ground\ floor door_ok=true,window_1_ok=true,window_2_ok=false
alarm_system_state,_type=untyped,entity=basement window_1_ok=true,window_2_ok=true,window_3_ok=true

View file

@ -0,0 +1,6 @@
openmetric,_type=untyped,entity=ground\ floor alarm_system_state_door_ok=true
openmetric,_type=untyped,entity=ground\ floor alarm_system_state_window_1_ok=true
openmetric,_type=untyped,entity=ground\ floor alarm_system_state_window_2_ok=false
openmetric,_type=untyped,entity=basement alarm_system_state_window_1_ok=true
openmetric,_type=untyped,entity=basement alarm_system_state_window_2_ok=true
openmetric,_type=untyped,entity=basement alarm_system_state_window_3_ok=true

View file

@ -0,0 +1,8 @@
# TYPE alarm_system_state stateset
alarm_system_state{entity="ground floor",alarm_system_state="door ok"} 1.0
alarm_system_state{entity="ground floor",alarm_system_state="window 1 ok"} 1.0
alarm_system_state{entity="ground floor",alarm_system_state="window 2 ok"} 0.0
alarm_system_state{entity="basement",alarm_system_state="window 1 ok"} 1.0
alarm_system_state{entity="basement",alarm_system_state="window 2 ok"} 1.0
alarm_system_state{entity="basement",alarm_system_state="window 3 ok"} 1.0
# EOF

View file

@ -0,0 +1,3 @@
[[inputs.test]]
files = ["input.txt"]
data_format = "openmetrics"

View file

@ -0,0 +1 @@
http_request_duration_microseconds,_type=summary,unit=microseconds,handler=prometheus 0.5=552048.506,0.9=5876804.288,0.99=5876804.288,count=9,sum=18909097.205,created=1705509488.3

View file

@ -0,0 +1,4 @@
openmetric,_type=summary,unit=microseconds,handler=prometheus http_request_duration_microseconds_count=9,http_request_duration_microseconds_sum=18909097.205,http_request_duration_microseconds_created=2005509488
openmetric,_type=summary,unit=microseconds,handler=prometheus,quantile=0.5 http_request_duration_microseconds=552048.506
openmetric,_type=summary,unit=microseconds,handler=prometheus,quantile=0.9 http_request_duration_microseconds=5876804.288
openmetric,_type=summary,unit=microseconds,handler=prometheus,quantile=0.99 http_request_duration_microseconds=5876804.288

View file

@ -0,0 +1,10 @@
# TYPE http_request_duration_microseconds summary
# UNIT http_request_duration_microseconds microseconds
# HELP http_request_duration_microseconds The HTTP request latencies in microseconds.
http_request_duration_microseconds{handler="prometheus",quantile="0.5"} 552048.506
http_request_duration_microseconds{handler="prometheus",quantile="0.9"} 5.876804288e+06
http_request_duration_microseconds{handler="prometheus",quantile="0.99"} 5.876804288e+06
http_request_duration_microseconds_created{handler="prometheus"} 1705509488.3
http_request_duration_microseconds_sum{handler="prometheus"} 1.8909097205e+07
http_request_duration_microseconds_count{handler="prometheus"} 9
# EOF

View file

@ -0,0 +1,3 @@
[[inputs.test]]
files = ["input.txt"]
data_format = "openmetrics"

View file

@ -0,0 +1,2 @@
redis_connected_clients,_type=untyped,instance=rough-snowflake-web,port=6380 value=10.0
redis_connected_clients,_type=untyped,instance=rough-snowflake-web,port=6381 value=12.0

View file

@ -0,0 +1,2 @@
openmetric,_type=untyped,instance=rough-snowflake-web,port=6380 redis_connected_clients=10.0
openmetric,_type=untyped,instance=rough-snowflake-web,port=6381 redis_connected_clients=12.0

View file

@ -0,0 +1,5 @@
# HELP redis_connected_clients Redis connected clients
# TYPE redis_connected_clients unknown
redis_connected_clients{instance="rough-snowflake-web",port="6380"} 10.0
redis_connected_clients{instance="rough-snowflake-web",port="6381"} 12.0
# EOF

View file

@ -0,0 +1,4 @@
[[inputs.test]]
files = ["input.txt"]
data_format = "openmetrics"

View file

@ -0,0 +1,394 @@
package openmetrics
import (
"bytes"
"errors"
"fmt"
"hash/maphash"
"io"
"math"
"slices"
"strconv"
"strings"
"time"
"github.com/prometheus/common/model"
"github.com/prometheus/prometheus/model/labels"
"github.com/prometheus/prometheus/model/textparse"
"google.golang.org/protobuf/types/known/timestamppb"
)
func TextToMetricFamilies(data []byte) ([]*MetricFamily, error) {
var metrics []*MetricFamily
parser := textparse.NewOpenMetricsParser(data, nil)
seed := maphash.MakeSeed()
mf := &MetricFamily{}
mfMetric := &Metric{}
mfMetricKey := uint64(0)
mfMetricPoint := &MetricPoint{}
for {
entry, err := parser.Next()
if err != nil {
if errors.Is(err, io.EOF) {
if mf.Name != "" {
if mfMetricPoint.Value != nil {
mfMetric.MetricPoints = append(mfMetric.MetricPoints, mfMetricPoint)
}
if len(mfMetric.MetricPoints) > 0 {
mf.Metrics = append(mf.Metrics, mfMetric)
}
metrics = append(metrics, mf)
}
break
}
return nil, fmt.Errorf("parsing failed: %w", err)
}
switch entry {
case textparse.EntryInvalid:
continue
case textparse.EntryType:
name, mtype := parser.Type()
if len(name) == 0 {
return nil, errors.New("empty metric-family name")
}
if mf.Name == "" {
mf.Name = string(name)
} else if mf.Name != string(name) {
if mfMetricPoint.Value != nil {
mfMetric.MetricPoints = append(mfMetric.MetricPoints, mfMetricPoint)
}
if len(mfMetric.MetricPoints) > 0 {
mf.Metrics = append(mf.Metrics, mfMetric)
}
metrics = append(metrics, mf)
mf = &MetricFamily{Name: string(name)}
mfMetric = &Metric{}
mfMetricKey = 0
mfMetricPoint = &MetricPoint{}
}
switch mtype {
case model.MetricTypeCounter:
mf.Type = MetricType_COUNTER
case model.MetricTypeGauge:
mf.Type = MetricType_GAUGE
case model.MetricTypeHistogram:
mf.Type = MetricType_HISTOGRAM
case model.MetricTypeGaugeHistogram:
mf.Type = MetricType_GAUGE_HISTOGRAM
case model.MetricTypeSummary:
mf.Type = MetricType_SUMMARY
case model.MetricTypeInfo:
mf.Type = MetricType_INFO
case model.MetricTypeStateset:
mf.Type = MetricType_STATE_SET
case model.MetricTypeUnknown:
mf.Type = MetricType_UNKNOWN
}
case textparse.EntryHelp:
name, mhelp := parser.Help()
if len(name) == 0 {
return nil, errors.New("empty metric-family name")
}
if mf.Name == "" {
mf.Name = string(name)
} else if mf.Name != string(name) {
if mfMetricPoint.Value != nil {
mfMetric.MetricPoints = append(mfMetric.MetricPoints, mfMetricPoint)
}
if len(mfMetric.MetricPoints) > 0 {
mf.Metrics = append(mf.Metrics, mfMetric)
}
metrics = append(metrics, mf)
mf = &MetricFamily{Name: string(name)}
mfMetric = &Metric{}
mfMetricKey = 0
mfMetricPoint = &MetricPoint{}
}
mf.Help = string(mhelp)
case textparse.EntrySeries:
series, ts, value := parser.Series()
// Extract the metric name and labels
dn, _, _ := bytes.Cut(series, []byte("{"))
if len(dn) == 0 {
return nil, errors.New("empty metric name")
}
sampleName := string(dn)
var metricLabels labels.Labels
parser.Metric(&metricLabels)
// There might be metrics without meta-information, however in this
// case the metric is of type UNKNOWN according to the spec and do
// only contain a single metric. Therefore, we can use the metric
// name as metric-family name
if mf.Name == "" {
mf.Name = sampleName
}
// The name contained in the sample is constructed using the metric
// name and an optional sample-type suffix used for more complex
// types (e.g. histograms).
sampleType, seriesLabels := extractSampleType(sampleName, mf.Name, mf.Type, &metricLabels)
// Check if we are still in the same metric, if not, add the
// previous one to the metric family and create a new one...
key := getSeriesKey(seriesLabels, seed)
if mfMetricKey != key {
if mfMetricPoint.Value != nil {
mfMetric.MetricPoints = append(mfMetric.MetricPoints, mfMetricPoint)
}
if len(mfMetric.MetricPoints) > 0 {
mf.Metrics = append(mf.Metrics, mfMetric)
}
mfMetric = &Metric{}
mfMetricKey = key
mfMetricPoint = &MetricPoint{}
mfMetric.Labels = make([]*Label, 0, len(*seriesLabels))
for _, l := range *seriesLabels {
mfMetric.Labels = append(mfMetric.Labels, &Label{
Name: l.Name,
Value: l.Value,
})
}
}
// Check if we are still in the same metric-point
var mpTimestamp int64
if mfMetricPoint.Timestamp != nil {
mpTimestamp = mfMetricPoint.Timestamp.Seconds * int64(time.Second)
mpTimestamp += int64(mfMetricPoint.Timestamp.Nanos)
}
var timestamp int64
if ts != nil {
timestamp = *ts * int64(time.Millisecond)
}
if mpTimestamp != timestamp {
if mfMetricPoint.Value != nil {
mfMetric.MetricPoints = append(mfMetric.MetricPoints, mfMetricPoint)
}
mfMetricPoint = &MetricPoint{}
if ts != nil {
mfMetricPoint.Timestamp = timestamppb.New(time.Unix(0, timestamp))
}
}
// Fill in the metric-point
mfMetricPoint.set(mf.Name, mf.Type, sampleType, value, &metricLabels)
case textparse.EntryComment:
// ignore comments
case textparse.EntryUnit:
name, munit := parser.Unit()
if len(name) == 0 {
return nil, errors.New("empty metric-family name")
}
if mf.Name == "" {
mf.Name = string(name)
} else if mf.Name != string(name) {
if mfMetricPoint.Value != nil {
mfMetric.MetricPoints = append(mfMetric.MetricPoints, mfMetricPoint)
}
if len(mfMetric.MetricPoints) > 0 {
mf.Metrics = append(mf.Metrics, mfMetric)
}
metrics = append(metrics, mf)
mf = &MetricFamily{Name: string(name)}
mfMetric = &Metric{}
mfMetricKey = 0
mfMetricPoint = &MetricPoint{}
}
mf.Unit = string(munit)
case textparse.EntryHistogram:
// not supported yet
default:
return nil, fmt.Errorf("unknown entry type %v", entry)
}
}
return metrics, nil
}
func getSeriesKey(seriesLabels *labels.Labels, seed maphash.Seed) uint64 {
sorted := make([]string, 0, len(*seriesLabels))
for _, l := range *seriesLabels {
sorted = append(sorted, l.Name+"="+l.Value)
}
slices.Sort(sorted)
var h maphash.Hash
h.SetSeed(seed)
for _, p := range sorted {
h.WriteString(p)
h.WriteByte(0)
}
return h.Sum64()
}
func extractSampleType(raw, name string, mtype MetricType, metricLabels *labels.Labels) (string, *labels.Labels) {
suffix := strings.TrimLeft(strings.TrimPrefix(raw, name), "_")
var seriesLabels labels.Labels
for _, l := range *metricLabels {
// filter out special labels
switch {
case l.Name == "__name__":
case mtype == MetricType_STATE_SET && l.Name == name:
case mtype == MetricType_HISTOGRAM && l.Name == "le":
case mtype == MetricType_GAUGE_HISTOGRAM && l.Name == "le":
case mtype == MetricType_SUMMARY && l.Name == "quantile":
default:
seriesLabels = append(seriesLabels, labels.Label{Name: l.Name, Value: l.Value})
}
}
return suffix, &seriesLabels
}
func (mp *MetricPoint) set(mname string, mtype MetricType, stype string, value float64, mlabels *labels.Labels) {
switch mtype {
case MetricType_UNKNOWN:
mp.Value = &MetricPoint_UnknownValue{
UnknownValue: &UnknownValue{
Value: &UnknownValue_DoubleValue{DoubleValue: value},
},
}
case MetricType_GAUGE:
mp.Value = &MetricPoint_GaugeValue{
GaugeValue: &GaugeValue{
Value: &GaugeValue_DoubleValue{DoubleValue: value},
},
}
case MetricType_COUNTER:
var v *MetricPoint_CounterValue
if mp.Value != nil {
v = mp.Value.(*MetricPoint_CounterValue)
} else {
v = &MetricPoint_CounterValue{
CounterValue: &CounterValue{},
}
}
switch stype {
case "total":
v.CounterValue.Total = &CounterValue_DoubleValue{DoubleValue: value}
case "created":
t := time.Unix(0, int64(value*float64(time.Second)))
v.CounterValue.Created = timestamppb.New(t)
}
mp.Value = v
case MetricType_STATE_SET:
var v *MetricPoint_StateSetValue
if mp.Value != nil {
v = mp.Value.(*MetricPoint_StateSetValue)
} else {
v = &MetricPoint_StateSetValue{
StateSetValue: &StateSetValue{},
}
}
var name string
for _, l := range *mlabels {
if l.Name == mname {
name = l.Value
break
}
}
v.StateSetValue.States = append(v.StateSetValue.States, &StateSetValue_State{
Enabled: value > 0,
Name: name,
})
mp.Value = v
case MetricType_INFO:
mp.Value = &MetricPoint_InfoValue{
InfoValue: &InfoValue{},
}
case MetricType_HISTOGRAM, MetricType_GAUGE_HISTOGRAM:
var v *MetricPoint_HistogramValue
if mp.Value != nil {
v = mp.Value.(*MetricPoint_HistogramValue)
} else {
v = &MetricPoint_HistogramValue{
HistogramValue: &HistogramValue{},
}
}
switch stype {
case "sum", "gsum":
v.HistogramValue.Sum = &HistogramValue_DoubleValue{DoubleValue: value}
case "count", "gcount":
v.HistogramValue.Count = uint64(value)
case "created":
t := time.Unix(0, int64(value*float64(time.Second)))
v.HistogramValue.Created = timestamppb.New(t)
case "bucket":
var boundLabel string
for _, l := range *mlabels {
if l.Name == "le" {
boundLabel = l.Value
break
}
}
var bound float64
if boundLabel == "+Inf" {
bound = math.Inf(1)
} else {
var err error
if bound, err = strconv.ParseFloat(boundLabel, 64); err != nil {
bound = math.NaN()
}
}
v.HistogramValue.Buckets = append(v.HistogramValue.Buckets, &HistogramValue_Bucket{
Count: uint64(value),
UpperBound: bound,
})
}
mp.Value = v
case MetricType_SUMMARY:
var v *MetricPoint_SummaryValue
if mp.Value != nil {
v = mp.Value.(*MetricPoint_SummaryValue)
} else {
v = &MetricPoint_SummaryValue{
SummaryValue: &SummaryValue{},
}
}
switch stype {
case "sum":
v.SummaryValue.Sum = &SummaryValue_DoubleValue{DoubleValue: value}
case "count":
v.SummaryValue.Count = uint64(value)
case "created":
t := time.Unix(0, int64(value*float64(time.Second)))
v.SummaryValue.Created = timestamppb.New(t)
default:
var quantileLabel string
for _, l := range *mlabels {
if l.Name == "quantile" {
quantileLabel = l.Value
break
}
}
var quantile float64
if quantileLabel == "+Inf" {
quantile = math.MaxFloat64
} else {
var err error
if quantile, err = strconv.ParseFloat(quantileLabel, 64); err != nil {
quantile = math.NaN()
}
}
v.SummaryValue.Quantile = append(v.SummaryValue.Quantile, &SummaryValue_Quantile{
Quantile: quantile,
Value: value,
})
}
mp.Value = v
}
}