diff --git a/docs/DATA_FORMATS_INPUT.md b/docs/DATA_FORMATS_INPUT.md index f4fd0a628..3947ffab9 100644 --- a/docs/DATA_FORMATS_INPUT.md +++ b/docs/DATA_FORMATS_INPUT.md @@ -18,6 +18,7 @@ Protocol, JSON format, or Apache Avro format. - [JSON v2](/plugins/parsers/json_v2) - [Logfmt](/plugins/parsers/logfmt) - [Nagios](/plugins/parsers/nagios) +- [OpenMetrics](/plugins/parsers/openmetrics) - [OpenTSDB](/plugins/parsers/opentsdb) - [Parquet](/plugins/parsers/parquet) - [Prometheus](/plugins/parsers/prometheus) diff --git a/plugins/inputs/prometheus/README.md b/plugins/inputs/prometheus/README.md index 7786154be..c2fd5ecec 100644 --- a/plugins/inputs/prometheus/README.md +++ b/plugins/inputs/prometheus/README.md @@ -32,6 +32,14 @@ See the [CONFIGURATION.md][CONFIGURATION.md] for more details. ## If set to true, the gather time will be used. # ignore_timestamp = false + ## Override content-type of the returned message + ## Available options are for prometheus: + ## text, protobuf-delimiter, protobuf-compact, protobuf-text, + ## and for openmetrics: + ## openmetrics-text, openmetrics-protobuf + ## By default the content-type of the response is used. + # content_type_override = "" + ## An array of Kubernetes services to scrape metrics from. # kubernetes_services = ["http://my-service-dns.my-namespace:9100/metrics"] diff --git a/plugins/inputs/prometheus/prometheus.go b/plugins/inputs/prometheus/prometheus.go index 57f806655..347092aa0 100644 --- a/plugins/inputs/prometheus/prometheus.go +++ b/plugins/inputs/prometheus/prometheus.go @@ -15,6 +15,7 @@ import ( "sync" "time" + "github.com/prometheus/common/expfmt" "k8s.io/apimachinery/pkg/fields" "k8s.io/apimachinery/pkg/labels" "k8s.io/client-go/tools/cache" @@ -26,6 +27,7 @@ import ( "github.com/influxdata/telegraf/models" httpconfig "github.com/influxdata/telegraf/plugins/common/http" "github.com/influxdata/telegraf/plugins/inputs" + "github.com/influxdata/telegraf/plugins/parsers/openmetrics" parser "github.com/influxdata/telegraf/plugins/parsers/prometheus" ) @@ -46,94 +48,71 @@ const ( type PodID string type Prometheus struct { - // An array of urls to scrape metrics from. - URLs []string `toml:"urls"` + URLs []string `toml:"urls"` + BearerToken string `toml:"bearer_token"` + BearerTokenString string `toml:"bearer_token_string"` + Username string `toml:"username"` + Password string `toml:"password"` + HTTPHeaders map[string]string `toml:"http_headers"` + ContentLengthLimit config.Size `toml:"content_length_limit"` + ContentTypeOverride string `toml:"content_type_override"` + EnableRequestMetrics bool `toml:"enable_request_metrics"` + MetricVersion int `toml:"metric_version"` + URLTag string `toml:"url_tag"` + IgnoreTimestamp bool `toml:"ignore_timestamp"` - // An array of Kubernetes services to scrape metrics from. - KubernetesServices []string + // Kubernetes service discovery + MonitorPods bool `toml:"monitor_kubernetes_pods"` + PodScrapeScope string `toml:"pod_scrape_scope"` + NodeIP string `toml:"node_ip"` + PodScrapeInterval int `toml:"pod_scrape_interval"` + PodNamespace string `toml:"monitor_kubernetes_pods_namespace"` + PodNamespaceLabelName string `toml:"pod_namespace_label_name"` + KubernetesServices []string `toml:"kubernetes_services"` + KubeConfig string `toml:"kube_config"` + KubernetesLabelSelector string `toml:"kubernetes_label_selector"` + KubernetesFieldSelector string `toml:"kubernetes_field_selector"` + MonitorKubernetesPodsMethod MonitorMethod `toml:"monitor_kubernetes_pods_method"` + MonitorKubernetesPodsScheme string `toml:"monitor_kubernetes_pods_scheme"` + MonitorKubernetesPodsPath string `toml:"monitor_kubernetes_pods_path"` + MonitorKubernetesPodsPort int `toml:"monitor_kubernetes_pods_port"` + NamespaceAnnotationPass map[string][]string `toml:"namespace_annotation_pass"` + NamespaceAnnotationDrop map[string][]string `toml:"namespace_annotation_drop"` + PodAnnotationInclude []string `toml:"pod_annotation_include"` + PodAnnotationExclude []string `toml:"pod_annotation_exclude"` + PodLabelInclude []string `toml:"pod_label_include"` + PodLabelExclude []string `toml:"pod_label_exclude"` + CacheRefreshInterval int `toml:"cache_refresh_interval"` - // Location of kubernetes config file - KubeConfig string - - // Label Selector/s for Kubernetes - KubernetesLabelSelector string `toml:"kubernetes_label_selector"` - - // Field Selector/s for Kubernetes - KubernetesFieldSelector string `toml:"kubernetes_field_selector"` - - // Consul SD configuration + // Consul discovery ConsulConfig ConsulConfig `toml:"consul"` - // Bearer Token authorization file path - BearerToken string `toml:"bearer_token"` - BearerTokenString string `toml:"bearer_token_string"` - - // Basic authentication credentials - Username string `toml:"username"` - Password string `toml:"password"` - - HTTPHeaders map[string]string `toml:"http_headers"` - - ContentLengthLimit config.Size `toml:"content_length_limit"` - EnableRequestMetrics bool `toml:"enable_request_metrics"` - - MetricVersion int `toml:"metric_version"` - - URLTag string `toml:"url_tag"` - - IgnoreTimestamp bool `toml:"ignore_timestamp"` - - Log telegraf.Logger - + Log telegraf.Logger `toml:"-"` httpconfig.HTTPClientConfig - client *http.Client - headers map[string]string - - nsStore cache.Store + client *http.Client + headers map[string]string + contentType string + nsStore cache.Store nsAnnotationPass []models.TagFilter nsAnnotationDrop []models.TagFilter // Should we scrape Kubernetes services for prometheus annotations - MonitorPods bool `toml:"monitor_kubernetes_pods"` - PodScrapeScope string `toml:"pod_scrape_scope"` - NodeIP string `toml:"node_ip"` - PodScrapeInterval int `toml:"pod_scrape_interval"` - PodNamespace string `toml:"monitor_kubernetes_pods_namespace"` - PodNamespaceLabelName string `toml:"pod_namespace_label_name"` - lock sync.Mutex - kubernetesPods map[PodID]URLAndAddress - cancel context.CancelFunc - wg sync.WaitGroup + lock sync.Mutex + kubernetesPods map[PodID]URLAndAddress + cancel context.CancelFunc + wg sync.WaitGroup // Only for monitor_kubernetes_pods=true and pod_scrape_scope="node" - podLabelSelector labels.Selector - podFieldSelector fields.Selector - isNodeScrapeScope bool - - MonitorKubernetesPodsMethod MonitorMethod `toml:"monitor_kubernetes_pods_method"` - MonitorKubernetesPodsScheme string `toml:"monitor_kubernetes_pods_scheme"` - MonitorKubernetesPodsPath string `toml:"monitor_kubernetes_pods_path"` - MonitorKubernetesPodsPort int `toml:"monitor_kubernetes_pods_port"` - - NamespaceAnnotationPass map[string][]string `toml:"namespace_annotation_pass"` - NamespaceAnnotationDrop map[string][]string `toml:"namespace_annotation_drop"` - - PodAnnotationInclude []string `toml:"pod_annotation_include"` - PodAnnotationExclude []string `toml:"pod_annotation_exclude"` - - PodLabelInclude []string `toml:"pod_label_include"` - PodLabelExclude []string `toml:"pod_label_exclude"` - + podLabelSelector labels.Selector + podFieldSelector fields.Selector + isNodeScrapeScope bool podAnnotationIncludeFilter filter.Filter podAnnotationExcludeFilter filter.Filter podLabelIncludeFilter filter.Filter podLabelExcludeFilter filter.Filter - // Only for monitor_kubernetes_pods=true - CacheRefreshInterval int `toml:"cache_refresh_interval"` - // List of consul services to scrape consulServices map[string]URLAndAddress } @@ -143,6 +122,29 @@ func (*Prometheus) SampleConfig() string { } func (p *Prometheus) Init() error { + // Setup content-type override if requested + switch p.ContentTypeOverride { + case "": // No override + case "text": + p.contentType = string(expfmt.NewFormat(expfmt.TypeTextPlain)) + case "protobuf-delimiter": + p.contentType = string(expfmt.NewFormat(expfmt.TypeProtoDelim)) + case "protobuf-compact": + p.contentType = string(expfmt.NewFormat(expfmt.TypeProtoCompact)) + case "protobuf-text": + p.contentType = string(expfmt.NewFormat(expfmt.TypeProtoText)) + case "openmetrics-text": + f, err := expfmt.NewOpenMetricsFormat(expfmt.OpenMetricsVersion_1_0_0) + if err != nil { + return err + } + p.contentType = string(f) + case "openmetrics-protobuf": + p.contentType = "application/openmetrics-protobuf;version=1.0.0" + default: + return fmt.Errorf("invalid 'content_type_override' setting %q", p.ContentTypeOverride) + } + // Config processing for node scrape scope for monitor_kubernetes_pods p.isNodeScrapeScope = strings.EqualFold(p.PodScrapeScope, "node") if p.isNodeScrapeScope { @@ -491,14 +493,29 @@ func (p *Prometheus) gatherURL(u URLAndAddress, acc telegraf.Accumulator) (map[s return requestFields, tags, fmt.Errorf("error reading body: %w", err) } } - requestFields["content_length"] = len(body) + + // Override the response format if the user requested it + if p.contentType != "" { + resp.Header.Set("Content-Type", p.contentType) + } + // Parse the metrics - metricParser := parser.Parser{ - Header: resp.Header, - MetricVersion: p.MetricVersion, - IgnoreTimestamp: p.IgnoreTimestamp, - Log: p.Log, + var metricParser telegraf.Parser + if openmetrics.AcceptsContent(resp.Header) { + metricParser = &openmetrics.Parser{ + Header: resp.Header, + MetricVersion: p.MetricVersion, + IgnoreTimestamp: p.IgnoreTimestamp, + Log: p.Log, + } + } else { + metricParser = &parser.Parser{ + Header: resp.Header, + MetricVersion: p.MetricVersion, + IgnoreTimestamp: p.IgnoreTimestamp, + Log: p.Log, + } } metrics, err := metricParser.Parse(body) if err != nil { diff --git a/plugins/inputs/prometheus/prometheus_test.go b/plugins/inputs/prometheus/prometheus_test.go index d56a1cd5f..28f3f3dcc 100644 --- a/plugins/inputs/prometheus/prometheus_test.go +++ b/plugins/inputs/prometheus/prometheus_test.go @@ -7,6 +7,8 @@ import ( "net/http" "net/http/httptest" "net/url" + "os" + "path/filepath" "testing" "time" @@ -706,3 +708,167 @@ func TestPrometheusInternalNoWeb(t *testing.T) { require.Error(t, acc.GatherError(p.Gather)) testutil.RequireMetricsSubset(t, expected, acc.GetTelegrafMetrics(), testutil.IgnoreFields("content_length", "response_time"), testutil.IgnoreTime()) } + +func TestOpenmetricsText(t *testing.T) { + const data = ` +# 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 +` + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { + w.Header().Add("Content-Type", "application/openmetrics-text;version=1.0.0") + _, _ = w.Write([]byte(data)) + })) + defer ts.Close() + + p := &Prometheus{ + Log: &testutil.Logger{}, + URLs: []string{ts.URL}, + URLTag: "", + MetricVersion: 2, + } + require.NoError(t, p.Init()) + + var acc testutil.Accumulator + require.NoError(t, p.Gather(&acc)) + + expected := []telegraf.Metric{ + testutil.MustMetric( + "openmetric", + map[string]string{}, + map[string]interface{}{"go_memstats_gc_cpu_fraction": float64(-0.00014404354379774563)}, + time.Unix(0, 0), + telegraf.Gauge, + ), + testutil.MustMetric( + "openmetric", + map[string]string{}, + map[string]interface{}{"go_memstats_gc_sys_bytes": 6.0936192e+07}, + time.Unix(0, 0), + telegraf.Gauge, + ), + testutil.MustMetric( + "openmetric", + map[string]string{}, + map[string]interface{}{"go_memstats_heap_alloc_bytes": 1.581062048e+09}, + time.Unix(0, 0), + telegraf.Gauge, + ), + } + + testutil.RequireMetricsEqual(t, expected, acc.GetTelegrafMetrics(), testutil.IgnoreTime(), testutil.SortMetrics()) +} + +func TestOpenmetricsProtobuf(t *testing.T) { + data, err := os.ReadFile(filepath.Join("testdata", "openmetric-proto.bin")) + require.NoError(t, err) + + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { + w.Header().Add("Content-Type", "application/openmetrics-protobuf;version=1.0.0") + _, _ = w.Write(data) + })) + defer ts.Close() + + p := &Prometheus{ + Log: &testutil.Logger{}, + URLs: []string{ts.URL}, + URLTag: "", + MetricVersion: 2, + } + require.NoError(t, p.Init()) + + var acc testutil.Accumulator + require.NoError(t, p.Gather(&acc)) + + expected := []telegraf.Metric{ + testutil.MustMetric( + "openmetric", + map[string]string{}, + map[string]interface{}{"go_memstats_gc_cpu_fraction": float64(-0.00014404354379774563)}, + time.Unix(0, 0), + telegraf.Gauge, + ), + testutil.MustMetric( + "openmetric", + map[string]string{}, + map[string]interface{}{"go_memstats_gc_sys_bytes": 6.0936192e+07}, + time.Unix(0, 0), + telegraf.Gauge, + ), + testutil.MustMetric( + "openmetric", + map[string]string{}, + map[string]interface{}{"go_memstats_heap_alloc_bytes": 1.581062048e+09}, + time.Unix(0, 0), + telegraf.Gauge, + ), + } + + testutil.RequireMetricsEqual(t, expected, acc.GetTelegrafMetrics(), testutil.IgnoreTime(), testutil.SortMetrics()) +} + +func TestContentTypeOverride(t *testing.T) { + const data = ` +# 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 +` + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { + // Provide a wrong version + w.Header().Add("Content-Type", "application/vnd.google.protobuf; proto=io.prometheus.client.MetricFamily; encoding=delimited") + _, _ = w.Write([]byte(data)) + })) + defer ts.Close() + + p := &Prometheus{ + Log: &testutil.Logger{}, + URLs: []string{ts.URL}, + URLTag: "", + MetricVersion: 2, + ContentTypeOverride: "openmetrics-text", + } + require.NoError(t, p.Init()) + + var acc testutil.Accumulator + require.NoError(t, p.Gather(&acc)) + + expected := []telegraf.Metric{ + testutil.MustMetric( + "openmetric", + map[string]string{}, + map[string]interface{}{"go_memstats_gc_cpu_fraction": float64(-0.00014404354379774563)}, + time.Unix(0, 0), + telegraf.Gauge, + ), + testutil.MustMetric( + "openmetric", + map[string]string{}, + map[string]interface{}{"go_memstats_gc_sys_bytes": 6.0936192e+07}, + time.Unix(0, 0), + telegraf.Gauge, + ), + testutil.MustMetric( + "openmetric", + map[string]string{}, + map[string]interface{}{"go_memstats_heap_alloc_bytes": 1.581062048e+09}, + time.Unix(0, 0), + telegraf.Gauge, + ), + } + + testutil.RequireMetricsEqual(t, expected, acc.GetTelegrafMetrics(), testutil.IgnoreTime(), testutil.SortMetrics()) +} diff --git a/plugins/inputs/prometheus/sample.conf b/plugins/inputs/prometheus/sample.conf index 30fa7b7ce..425eba379 100644 --- a/plugins/inputs/prometheus/sample.conf +++ b/plugins/inputs/prometheus/sample.conf @@ -15,6 +15,14 @@ ## If set to true, the gather time will be used. # ignore_timestamp = false + ## Override content-type of the returned message + ## Available options are for prometheus: + ## text, protobuf-delimiter, protobuf-compact, protobuf-text, + ## and for openmetrics: + ## openmetrics-text, openmetrics-protobuf + ## By default the content-type of the response is used. + # content_type_override = "" + ## An array of Kubernetes services to scrape metrics from. # kubernetes_services = ["http://my-service-dns.my-namespace:9100/metrics"] diff --git a/plugins/inputs/prometheus/testdata/openmetric-proto.bin b/plugins/inputs/prometheus/testdata/openmetric-proto.bin new file mode 100644 index 000000000..de892459e Binary files /dev/null and b/plugins/inputs/prometheus/testdata/openmetric-proto.bin differ diff --git a/plugins/parsers/all/openmetrics.go b/plugins/parsers/all/openmetrics.go new file mode 100644 index 000000000..516d2987f --- /dev/null +++ b/plugins/parsers/all/openmetrics.go @@ -0,0 +1,5 @@ +//go:build !custom || parsers || parsers.openmetrics + +package all + +import _ "github.com/influxdata/telegraf/plugins/parsers/openmetrics" // register plugin diff --git a/plugins/parsers/openmetrics/README.md b/plugins/parsers/openmetrics/README.md new file mode 100644 index 000000000..a9328a8d9 --- /dev/null +++ b/plugins/parsers/openmetrics/README.md @@ -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/OpenObservability/OpenMetrics/blob/main/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 +``` diff --git a/plugins/parsers/openmetrics/metric_v1.go b/plugins/parsers/openmetrics/metric_v1.go new file mode 100644 index 000000000..6b9c4f68a --- /dev/null +++ b/plugins/parsers/openmetrics/metric_v1.go @@ -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 +} diff --git a/plugins/parsers/openmetrics/metric_v2.go b/plugins/parsers/openmetrics/metric_v2.go new file mode 100644 index 000000000..46478d506 --- /dev/null +++ b/plugins/parsers/openmetrics/metric_v2.go @@ -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 +} diff --git a/plugins/parsers/openmetrics/openmetrics_data_model.pb.go b/plugins/parsers/openmetrics/openmetrics_data_model.pb.go new file mode 100644 index 000000000..096df5969 --- /dev/null +++ b/plugins/parsers/openmetrics/openmetrics_data_model.pb.go @@ -0,0 +1,1833 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.31.0 +// protoc v4.25.1 +// source: openmetrics_data_model.proto + +// 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 ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + timestamppb "google.golang.org/protobuf/types/known/timestamppb" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +// The type of a Metric. +type MetricType int32 + +const ( + // Unknown must use unknown MetricPoint values. + MetricType_UNKNOWN MetricType = 0 + // Gauge must use gauge MetricPoint values. + MetricType_GAUGE MetricType = 1 + // Counter must use counter MetricPoint values. + MetricType_COUNTER MetricType = 2 + // State set must use state set MetricPoint values. + MetricType_STATE_SET MetricType = 3 + // Info must use info MetricPoint values. + MetricType_INFO MetricType = 4 + // Histogram must use histogram value MetricPoint values. + MetricType_HISTOGRAM MetricType = 5 + // Gauge histogram must use histogram value MetricPoint values. + MetricType_GAUGE_HISTOGRAM MetricType = 6 + // Summary quantiles must use summary value MetricPoint values. + MetricType_SUMMARY MetricType = 7 +) + +// Enum value maps for MetricType. +var ( + MetricType_name = map[int32]string{ + 0: "UNKNOWN", + 1: "GAUGE", + 2: "COUNTER", + 3: "STATE_SET", + 4: "INFO", + 5: "HISTOGRAM", + 6: "GAUGE_HISTOGRAM", + 7: "SUMMARY", + } + MetricType_value = map[string]int32{ + "UNKNOWN": 0, + "GAUGE": 1, + "COUNTER": 2, + "STATE_SET": 3, + "INFO": 4, + "HISTOGRAM": 5, + "GAUGE_HISTOGRAM": 6, + "SUMMARY": 7, + } +) + +func (x MetricType) Enum() *MetricType { + p := new(MetricType) + *p = x + return p +} + +func (x MetricType) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (MetricType) Descriptor() protoreflect.EnumDescriptor { + return file_openmetrics_data_model_proto_enumTypes[0].Descriptor() +} + +func (MetricType) Type() protoreflect.EnumType { + return &file_openmetrics_data_model_proto_enumTypes[0] +} + +func (x MetricType) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use MetricType.Descriptor instead. +func (MetricType) EnumDescriptor() ([]byte, []int) { + return file_openmetrics_data_model_proto_rawDescGZIP(), []int{0} +} + +// The top-level container type that is encoded and sent over the wire. +type MetricSet struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Each MetricFamily has one or more MetricPoints for a single Metric. + MetricFamilies []*MetricFamily `protobuf:"bytes,1,rep,name=metric_families,json=metricFamilies,proto3" json:"metric_families,omitempty"` +} + +func (x *MetricSet) Reset() { + *x = MetricSet{} + if protoimpl.UnsafeEnabled { + mi := &file_openmetrics_data_model_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *MetricSet) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*MetricSet) ProtoMessage() {} + +func (x *MetricSet) ProtoReflect() protoreflect.Message { + mi := &file_openmetrics_data_model_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use MetricSet.ProtoReflect.Descriptor instead. +func (*MetricSet) Descriptor() ([]byte, []int) { + return file_openmetrics_data_model_proto_rawDescGZIP(), []int{0} +} + +func (x *MetricSet) GetMetricFamilies() []*MetricFamily { + if x != nil { + return x.MetricFamilies + } + return nil +} + +// One or more Metrics for a single MetricFamily, where each Metric +// has one or more MetricPoints. +type MetricFamily struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Required. + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + // Optional. + Type MetricType `protobuf:"varint,2,opt,name=type,proto3,enum=openmetrics.MetricType" json:"type,omitempty"` + // Optional. + Unit string `protobuf:"bytes,3,opt,name=unit,proto3" json:"unit,omitempty"` + // Optional. + Help string `protobuf:"bytes,4,opt,name=help,proto3" json:"help,omitempty"` + // Optional. + Metrics []*Metric `protobuf:"bytes,5,rep,name=metrics,proto3" json:"metrics,omitempty"` +} + +func (x *MetricFamily) Reset() { + *x = MetricFamily{} + if protoimpl.UnsafeEnabled { + mi := &file_openmetrics_data_model_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *MetricFamily) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*MetricFamily) ProtoMessage() {} + +func (x *MetricFamily) ProtoReflect() protoreflect.Message { + mi := &file_openmetrics_data_model_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use MetricFamily.ProtoReflect.Descriptor instead. +func (*MetricFamily) Descriptor() ([]byte, []int) { + return file_openmetrics_data_model_proto_rawDescGZIP(), []int{1} +} + +func (x *MetricFamily) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *MetricFamily) GetType() MetricType { + if x != nil { + return x.Type + } + return MetricType_UNKNOWN +} + +func (x *MetricFamily) GetUnit() string { + if x != nil { + return x.Unit + } + return "" +} + +func (x *MetricFamily) GetHelp() string { + if x != nil { + return x.Help + } + return "" +} + +func (x *MetricFamily) GetMetrics() []*Metric { + if x != nil { + return x.Metrics + } + return nil +} + +// A single metric with a unique set of labels within a metric family. +type Metric struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Optional. + Labels []*Label `protobuf:"bytes,1,rep,name=labels,proto3" json:"labels,omitempty"` + // Optional. + MetricPoints []*MetricPoint `protobuf:"bytes,2,rep,name=metric_points,json=metricPoints,proto3" json:"metric_points,omitempty"` +} + +func (x *Metric) Reset() { + *x = Metric{} + if protoimpl.UnsafeEnabled { + mi := &file_openmetrics_data_model_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Metric) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Metric) ProtoMessage() {} + +func (x *Metric) ProtoReflect() protoreflect.Message { + mi := &file_openmetrics_data_model_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Metric.ProtoReflect.Descriptor instead. +func (*Metric) Descriptor() ([]byte, []int) { + return file_openmetrics_data_model_proto_rawDescGZIP(), []int{2} +} + +func (x *Metric) GetLabels() []*Label { + if x != nil { + return x.Labels + } + return nil +} + +func (x *Metric) GetMetricPoints() []*MetricPoint { + if x != nil { + return x.MetricPoints + } + return nil +} + +// A name-value pair. These are used in multiple places: identifying +// timeseries, value of INFO metrics, and exemplars in Histograms. +type Label struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Required. + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + // Required. + Value string `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"` +} + +func (x *Label) Reset() { + *x = Label{} + if protoimpl.UnsafeEnabled { + mi := &file_openmetrics_data_model_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Label) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Label) ProtoMessage() {} + +func (x *Label) ProtoReflect() protoreflect.Message { + mi := &file_openmetrics_data_model_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Label.ProtoReflect.Descriptor instead. +func (*Label) Descriptor() ([]byte, []int) { + return file_openmetrics_data_model_proto_rawDescGZIP(), []int{3} +} + +func (x *Label) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *Label) GetValue() string { + if x != nil { + return x.Value + } + return "" +} + +// A MetricPoint in a Metric. +type MetricPoint struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Required. + // + // Types that are assignable to Value: + // + // *MetricPoint_UnknownValue + // *MetricPoint_GaugeValue + // *MetricPoint_CounterValue + // *MetricPoint_HistogramValue + // *MetricPoint_StateSetValue + // *MetricPoint_InfoValue + // *MetricPoint_SummaryValue + Value isMetricPoint_Value `protobuf_oneof:"value"` + // Optional. + Timestamp *timestamppb.Timestamp `protobuf:"bytes,8,opt,name=timestamp,proto3" json:"timestamp,omitempty"` +} + +func (x *MetricPoint) Reset() { + *x = MetricPoint{} + if protoimpl.UnsafeEnabled { + mi := &file_openmetrics_data_model_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *MetricPoint) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*MetricPoint) ProtoMessage() {} + +func (x *MetricPoint) ProtoReflect() protoreflect.Message { + mi := &file_openmetrics_data_model_proto_msgTypes[4] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use MetricPoint.ProtoReflect.Descriptor instead. +func (*MetricPoint) Descriptor() ([]byte, []int) { + return file_openmetrics_data_model_proto_rawDescGZIP(), []int{4} +} + +func (m *MetricPoint) GetValue() isMetricPoint_Value { + if m != nil { + return m.Value + } + return nil +} + +func (x *MetricPoint) GetUnknownValue() *UnknownValue { + if x, ok := x.GetValue().(*MetricPoint_UnknownValue); ok { + return x.UnknownValue + } + return nil +} + +func (x *MetricPoint) GetGaugeValue() *GaugeValue { + if x, ok := x.GetValue().(*MetricPoint_GaugeValue); ok { + return x.GaugeValue + } + return nil +} + +func (x *MetricPoint) GetCounterValue() *CounterValue { + if x, ok := x.GetValue().(*MetricPoint_CounterValue); ok { + return x.CounterValue + } + return nil +} + +func (x *MetricPoint) GetHistogramValue() *HistogramValue { + if x, ok := x.GetValue().(*MetricPoint_HistogramValue); ok { + return x.HistogramValue + } + return nil +} + +func (x *MetricPoint) GetStateSetValue() *StateSetValue { + if x, ok := x.GetValue().(*MetricPoint_StateSetValue); ok { + return x.StateSetValue + } + return nil +} + +func (x *MetricPoint) GetInfoValue() *InfoValue { + if x, ok := x.GetValue().(*MetricPoint_InfoValue); ok { + return x.InfoValue + } + return nil +} + +func (x *MetricPoint) GetSummaryValue() *SummaryValue { + if x, ok := x.GetValue().(*MetricPoint_SummaryValue); ok { + return x.SummaryValue + } + return nil +} + +func (x *MetricPoint) GetTimestamp() *timestamppb.Timestamp { + if x != nil { + return x.Timestamp + } + return nil +} + +type isMetricPoint_Value interface { + isMetricPoint_Value() +} + +type MetricPoint_UnknownValue struct { + UnknownValue *UnknownValue `protobuf:"bytes,1,opt,name=unknown_value,json=unknownValue,proto3,oneof"` +} + +type MetricPoint_GaugeValue struct { + GaugeValue *GaugeValue `protobuf:"bytes,2,opt,name=gauge_value,json=gaugeValue,proto3,oneof"` +} + +type MetricPoint_CounterValue struct { + CounterValue *CounterValue `protobuf:"bytes,3,opt,name=counter_value,json=counterValue,proto3,oneof"` +} + +type MetricPoint_HistogramValue struct { + HistogramValue *HistogramValue `protobuf:"bytes,4,opt,name=histogram_value,json=histogramValue,proto3,oneof"` +} + +type MetricPoint_StateSetValue struct { + StateSetValue *StateSetValue `protobuf:"bytes,5,opt,name=state_set_value,json=stateSetValue,proto3,oneof"` +} + +type MetricPoint_InfoValue struct { + InfoValue *InfoValue `protobuf:"bytes,6,opt,name=info_value,json=infoValue,proto3,oneof"` +} + +type MetricPoint_SummaryValue struct { + SummaryValue *SummaryValue `protobuf:"bytes,7,opt,name=summary_value,json=summaryValue,proto3,oneof"` +} + +func (*MetricPoint_UnknownValue) isMetricPoint_Value() {} + +func (*MetricPoint_GaugeValue) isMetricPoint_Value() {} + +func (*MetricPoint_CounterValue) isMetricPoint_Value() {} + +func (*MetricPoint_HistogramValue) isMetricPoint_Value() {} + +func (*MetricPoint_StateSetValue) isMetricPoint_Value() {} + +func (*MetricPoint_InfoValue) isMetricPoint_Value() {} + +func (*MetricPoint_SummaryValue) isMetricPoint_Value() {} + +// Value for UNKNOWN MetricPoint. +type UnknownValue struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Required. + // + // Types that are assignable to Value: + // + // *UnknownValue_DoubleValue + // *UnknownValue_IntValue + Value isUnknownValue_Value `protobuf_oneof:"value"` +} + +func (x *UnknownValue) Reset() { + *x = UnknownValue{} + if protoimpl.UnsafeEnabled { + mi := &file_openmetrics_data_model_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *UnknownValue) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UnknownValue) ProtoMessage() {} + +func (x *UnknownValue) ProtoReflect() protoreflect.Message { + mi := &file_openmetrics_data_model_proto_msgTypes[5] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use UnknownValue.ProtoReflect.Descriptor instead. +func (*UnknownValue) Descriptor() ([]byte, []int) { + return file_openmetrics_data_model_proto_rawDescGZIP(), []int{5} +} + +func (m *UnknownValue) GetValue() isUnknownValue_Value { + if m != nil { + return m.Value + } + return nil +} + +func (x *UnknownValue) GetDoubleValue() float64 { + if x, ok := x.GetValue().(*UnknownValue_DoubleValue); ok { + return x.DoubleValue + } + return 0 +} + +func (x *UnknownValue) GetIntValue() int64 { + if x, ok := x.GetValue().(*UnknownValue_IntValue); ok { + return x.IntValue + } + return 0 +} + +type isUnknownValue_Value interface { + isUnknownValue_Value() +} + +type UnknownValue_DoubleValue struct { + DoubleValue float64 `protobuf:"fixed64,1,opt,name=double_value,json=doubleValue,proto3,oneof"` +} + +type UnknownValue_IntValue struct { + IntValue int64 `protobuf:"varint,2,opt,name=int_value,json=intValue,proto3,oneof"` +} + +func (*UnknownValue_DoubleValue) isUnknownValue_Value() {} + +func (*UnknownValue_IntValue) isUnknownValue_Value() {} + +// Value for GAUGE MetricPoint. +type GaugeValue struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Required. + // + // Types that are assignable to Value: + // + // *GaugeValue_DoubleValue + // *GaugeValue_IntValue + Value isGaugeValue_Value `protobuf_oneof:"value"` +} + +func (x *GaugeValue) Reset() { + *x = GaugeValue{} + if protoimpl.UnsafeEnabled { + mi := &file_openmetrics_data_model_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GaugeValue) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GaugeValue) ProtoMessage() {} + +func (x *GaugeValue) ProtoReflect() protoreflect.Message { + mi := &file_openmetrics_data_model_proto_msgTypes[6] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GaugeValue.ProtoReflect.Descriptor instead. +func (*GaugeValue) Descriptor() ([]byte, []int) { + return file_openmetrics_data_model_proto_rawDescGZIP(), []int{6} +} + +func (m *GaugeValue) GetValue() isGaugeValue_Value { + if m != nil { + return m.Value + } + return nil +} + +func (x *GaugeValue) GetDoubleValue() float64 { + if x, ok := x.GetValue().(*GaugeValue_DoubleValue); ok { + return x.DoubleValue + } + return 0 +} + +func (x *GaugeValue) GetIntValue() int64 { + if x, ok := x.GetValue().(*GaugeValue_IntValue); ok { + return x.IntValue + } + return 0 +} + +type isGaugeValue_Value interface { + isGaugeValue_Value() +} + +type GaugeValue_DoubleValue struct { + DoubleValue float64 `protobuf:"fixed64,1,opt,name=double_value,json=doubleValue,proto3,oneof"` +} + +type GaugeValue_IntValue struct { + IntValue int64 `protobuf:"varint,2,opt,name=int_value,json=intValue,proto3,oneof"` +} + +func (*GaugeValue_DoubleValue) isGaugeValue_Value() {} + +func (*GaugeValue_IntValue) isGaugeValue_Value() {} + +// Value for COUNTER MetricPoint. +type CounterValue struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Required. + // + // Types that are assignable to Total: + // + // *CounterValue_DoubleValue + // *CounterValue_IntValue + Total isCounterValue_Total `protobuf_oneof:"total"` + // The time values began being collected for this counter. + // Optional. + Created *timestamppb.Timestamp `protobuf:"bytes,3,opt,name=created,proto3" json:"created,omitempty"` + // Optional. + Exemplar *Exemplar `protobuf:"bytes,4,opt,name=exemplar,proto3" json:"exemplar,omitempty"` +} + +func (x *CounterValue) Reset() { + *x = CounterValue{} + if protoimpl.UnsafeEnabled { + mi := &file_openmetrics_data_model_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *CounterValue) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CounterValue) ProtoMessage() {} + +func (x *CounterValue) ProtoReflect() protoreflect.Message { + mi := &file_openmetrics_data_model_proto_msgTypes[7] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CounterValue.ProtoReflect.Descriptor instead. +func (*CounterValue) Descriptor() ([]byte, []int) { + return file_openmetrics_data_model_proto_rawDescGZIP(), []int{7} +} + +func (m *CounterValue) GetTotal() isCounterValue_Total { + if m != nil { + return m.Total + } + return nil +} + +func (x *CounterValue) GetDoubleValue() float64 { + if x, ok := x.GetTotal().(*CounterValue_DoubleValue); ok { + return x.DoubleValue + } + return 0 +} + +func (x *CounterValue) GetIntValue() uint64 { + if x, ok := x.GetTotal().(*CounterValue_IntValue); ok { + return x.IntValue + } + return 0 +} + +func (x *CounterValue) GetCreated() *timestamppb.Timestamp { + if x != nil { + return x.Created + } + return nil +} + +func (x *CounterValue) GetExemplar() *Exemplar { + if x != nil { + return x.Exemplar + } + return nil +} + +type isCounterValue_Total interface { + isCounterValue_Total() +} + +type CounterValue_DoubleValue struct { + DoubleValue float64 `protobuf:"fixed64,1,opt,name=double_value,json=doubleValue,proto3,oneof"` +} + +type CounterValue_IntValue struct { + IntValue uint64 `protobuf:"varint,2,opt,name=int_value,json=intValue,proto3,oneof"` +} + +func (*CounterValue_DoubleValue) isCounterValue_Total() {} + +func (*CounterValue_IntValue) isCounterValue_Total() {} + +// Value for HISTOGRAM or GAUGE_HISTOGRAM MetricPoint. +type HistogramValue struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Optional. + // + // Types that are assignable to Sum: + // + // *HistogramValue_DoubleValue + // *HistogramValue_IntValue + Sum isHistogramValue_Sum `protobuf_oneof:"sum"` + // Optional. + Count uint64 `protobuf:"varint,3,opt,name=count,proto3" json:"count,omitempty"` + // The time values began being collected for this histogram. + // Optional. + Created *timestamppb.Timestamp `protobuf:"bytes,4,opt,name=created,proto3" json:"created,omitempty"` + // Optional. + Buckets []*HistogramValue_Bucket `protobuf:"bytes,5,rep,name=buckets,proto3" json:"buckets,omitempty"` +} + +func (x *HistogramValue) Reset() { + *x = HistogramValue{} + if protoimpl.UnsafeEnabled { + mi := &file_openmetrics_data_model_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *HistogramValue) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*HistogramValue) ProtoMessage() {} + +func (x *HistogramValue) ProtoReflect() protoreflect.Message { + mi := &file_openmetrics_data_model_proto_msgTypes[8] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use HistogramValue.ProtoReflect.Descriptor instead. +func (*HistogramValue) Descriptor() ([]byte, []int) { + return file_openmetrics_data_model_proto_rawDescGZIP(), []int{8} +} + +func (m *HistogramValue) GetSum() isHistogramValue_Sum { + if m != nil { + return m.Sum + } + return nil +} + +func (x *HistogramValue) GetDoubleValue() float64 { + if x, ok := x.GetSum().(*HistogramValue_DoubleValue); ok { + return x.DoubleValue + } + return 0 +} + +func (x *HistogramValue) GetIntValue() int64 { + if x, ok := x.GetSum().(*HistogramValue_IntValue); ok { + return x.IntValue + } + return 0 +} + +func (x *HistogramValue) GetCount() uint64 { + if x != nil { + return x.Count + } + return 0 +} + +func (x *HistogramValue) GetCreated() *timestamppb.Timestamp { + if x != nil { + return x.Created + } + return nil +} + +func (x *HistogramValue) GetBuckets() []*HistogramValue_Bucket { + if x != nil { + return x.Buckets + } + return nil +} + +type isHistogramValue_Sum interface { + isHistogramValue_Sum() +} + +type HistogramValue_DoubleValue struct { + DoubleValue float64 `protobuf:"fixed64,1,opt,name=double_value,json=doubleValue,proto3,oneof"` +} + +type HistogramValue_IntValue struct { + IntValue int64 `protobuf:"varint,2,opt,name=int_value,json=intValue,proto3,oneof"` +} + +func (*HistogramValue_DoubleValue) isHistogramValue_Sum() {} + +func (*HistogramValue_IntValue) isHistogramValue_Sum() {} + +type Exemplar struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Required. + Value float64 `protobuf:"fixed64,1,opt,name=value,proto3" json:"value,omitempty"` + // Optional. + Timestamp *timestamppb.Timestamp `protobuf:"bytes,2,opt,name=timestamp,proto3" json:"timestamp,omitempty"` + // Labels are additional information about the exemplar value (e.g. trace id). + // Optional. + Label []*Label `protobuf:"bytes,3,rep,name=label,proto3" json:"label,omitempty"` +} + +func (x *Exemplar) Reset() { + *x = Exemplar{} + if protoimpl.UnsafeEnabled { + mi := &file_openmetrics_data_model_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Exemplar) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Exemplar) ProtoMessage() {} + +func (x *Exemplar) ProtoReflect() protoreflect.Message { + mi := &file_openmetrics_data_model_proto_msgTypes[9] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Exemplar.ProtoReflect.Descriptor instead. +func (*Exemplar) Descriptor() ([]byte, []int) { + return file_openmetrics_data_model_proto_rawDescGZIP(), []int{9} +} + +func (x *Exemplar) GetValue() float64 { + if x != nil { + return x.Value + } + return 0 +} + +func (x *Exemplar) GetTimestamp() *timestamppb.Timestamp { + if x != nil { + return x.Timestamp + } + return nil +} + +func (x *Exemplar) GetLabel() []*Label { + if x != nil { + return x.Label + } + return nil +} + +// Value for STATE_SET MetricPoint. +type StateSetValue struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Optional. + States []*StateSetValue_State `protobuf:"bytes,1,rep,name=states,proto3" json:"states,omitempty"` +} + +func (x *StateSetValue) Reset() { + *x = StateSetValue{} + if protoimpl.UnsafeEnabled { + mi := &file_openmetrics_data_model_proto_msgTypes[10] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *StateSetValue) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*StateSetValue) ProtoMessage() {} + +func (x *StateSetValue) ProtoReflect() protoreflect.Message { + mi := &file_openmetrics_data_model_proto_msgTypes[10] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use StateSetValue.ProtoReflect.Descriptor instead. +func (*StateSetValue) Descriptor() ([]byte, []int) { + return file_openmetrics_data_model_proto_rawDescGZIP(), []int{10} +} + +func (x *StateSetValue) GetStates() []*StateSetValue_State { + if x != nil { + return x.States + } + return nil +} + +// Value for INFO MetricPoint. +type InfoValue struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Optional. + Info []*Label `protobuf:"bytes,1,rep,name=info,proto3" json:"info,omitempty"` +} + +func (x *InfoValue) Reset() { + *x = InfoValue{} + if protoimpl.UnsafeEnabled { + mi := &file_openmetrics_data_model_proto_msgTypes[11] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *InfoValue) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*InfoValue) ProtoMessage() {} + +func (x *InfoValue) ProtoReflect() protoreflect.Message { + mi := &file_openmetrics_data_model_proto_msgTypes[11] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use InfoValue.ProtoReflect.Descriptor instead. +func (*InfoValue) Descriptor() ([]byte, []int) { + return file_openmetrics_data_model_proto_rawDescGZIP(), []int{11} +} + +func (x *InfoValue) GetInfo() []*Label { + if x != nil { + return x.Info + } + return nil +} + +// Value for SUMMARY MetricPoint. +type SummaryValue struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Optional. + // + // Types that are assignable to Sum: + // + // *SummaryValue_DoubleValue + // *SummaryValue_IntValue + Sum isSummaryValue_Sum `protobuf_oneof:"sum"` + // Optional. + Count uint64 `protobuf:"varint,3,opt,name=count,proto3" json:"count,omitempty"` + // The time sum and count values began being collected for this summary. + // Optional. + Created *timestamppb.Timestamp `protobuf:"bytes,4,opt,name=created,proto3" json:"created,omitempty"` + // Optional. + Quantile []*SummaryValue_Quantile `protobuf:"bytes,5,rep,name=quantile,proto3" json:"quantile,omitempty"` +} + +func (x *SummaryValue) Reset() { + *x = SummaryValue{} + if protoimpl.UnsafeEnabled { + mi := &file_openmetrics_data_model_proto_msgTypes[12] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SummaryValue) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SummaryValue) ProtoMessage() {} + +func (x *SummaryValue) ProtoReflect() protoreflect.Message { + mi := &file_openmetrics_data_model_proto_msgTypes[12] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SummaryValue.ProtoReflect.Descriptor instead. +func (*SummaryValue) Descriptor() ([]byte, []int) { + return file_openmetrics_data_model_proto_rawDescGZIP(), []int{12} +} + +func (m *SummaryValue) GetSum() isSummaryValue_Sum { + if m != nil { + return m.Sum + } + return nil +} + +func (x *SummaryValue) GetDoubleValue() float64 { + if x, ok := x.GetSum().(*SummaryValue_DoubleValue); ok { + return x.DoubleValue + } + return 0 +} + +func (x *SummaryValue) GetIntValue() int64 { + if x, ok := x.GetSum().(*SummaryValue_IntValue); ok { + return x.IntValue + } + return 0 +} + +func (x *SummaryValue) GetCount() uint64 { + if x != nil { + return x.Count + } + return 0 +} + +func (x *SummaryValue) GetCreated() *timestamppb.Timestamp { + if x != nil { + return x.Created + } + return nil +} + +func (x *SummaryValue) GetQuantile() []*SummaryValue_Quantile { + if x != nil { + return x.Quantile + } + return nil +} + +type isSummaryValue_Sum interface { + isSummaryValue_Sum() +} + +type SummaryValue_DoubleValue struct { + DoubleValue float64 `protobuf:"fixed64,1,opt,name=double_value,json=doubleValue,proto3,oneof"` +} + +type SummaryValue_IntValue struct { + IntValue int64 `protobuf:"varint,2,opt,name=int_value,json=intValue,proto3,oneof"` +} + +func (*SummaryValue_DoubleValue) isSummaryValue_Sum() {} + +func (*SummaryValue_IntValue) isSummaryValue_Sum() {} + +// Bucket is the number of values for a bucket in the histogram +// with an optional exemplar. +type HistogramValue_Bucket struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Required. + Count uint64 `protobuf:"varint,1,opt,name=count,proto3" json:"count,omitempty"` + // Optional. + UpperBound float64 `protobuf:"fixed64,2,opt,name=upper_bound,json=upperBound,proto3" json:"upper_bound,omitempty"` + // Optional. + Exemplar *Exemplar `protobuf:"bytes,3,opt,name=exemplar,proto3" json:"exemplar,omitempty"` +} + +func (x *HistogramValue_Bucket) Reset() { + *x = HistogramValue_Bucket{} + if protoimpl.UnsafeEnabled { + mi := &file_openmetrics_data_model_proto_msgTypes[13] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *HistogramValue_Bucket) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*HistogramValue_Bucket) ProtoMessage() {} + +func (x *HistogramValue_Bucket) ProtoReflect() protoreflect.Message { + mi := &file_openmetrics_data_model_proto_msgTypes[13] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use HistogramValue_Bucket.ProtoReflect.Descriptor instead. +func (*HistogramValue_Bucket) Descriptor() ([]byte, []int) { + return file_openmetrics_data_model_proto_rawDescGZIP(), []int{8, 0} +} + +func (x *HistogramValue_Bucket) GetCount() uint64 { + if x != nil { + return x.Count + } + return 0 +} + +func (x *HistogramValue_Bucket) GetUpperBound() float64 { + if x != nil { + return x.UpperBound + } + return 0 +} + +func (x *HistogramValue_Bucket) GetExemplar() *Exemplar { + if x != nil { + return x.Exemplar + } + return nil +} + +type StateSetValue_State struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Required. + Enabled bool `protobuf:"varint,1,opt,name=enabled,proto3" json:"enabled,omitempty"` + // Required. + Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` +} + +func (x *StateSetValue_State) Reset() { + *x = StateSetValue_State{} + if protoimpl.UnsafeEnabled { + mi := &file_openmetrics_data_model_proto_msgTypes[14] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *StateSetValue_State) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*StateSetValue_State) ProtoMessage() {} + +func (x *StateSetValue_State) ProtoReflect() protoreflect.Message { + mi := &file_openmetrics_data_model_proto_msgTypes[14] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use StateSetValue_State.ProtoReflect.Descriptor instead. +func (*StateSetValue_State) Descriptor() ([]byte, []int) { + return file_openmetrics_data_model_proto_rawDescGZIP(), []int{10, 0} +} + +func (x *StateSetValue_State) GetEnabled() bool { + if x != nil { + return x.Enabled + } + return false +} + +func (x *StateSetValue_State) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +type SummaryValue_Quantile struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Required. + Quantile float64 `protobuf:"fixed64,1,opt,name=quantile,proto3" json:"quantile,omitempty"` + // Required. + Value float64 `protobuf:"fixed64,2,opt,name=value,proto3" json:"value,omitempty"` +} + +func (x *SummaryValue_Quantile) Reset() { + *x = SummaryValue_Quantile{} + if protoimpl.UnsafeEnabled { + mi := &file_openmetrics_data_model_proto_msgTypes[15] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SummaryValue_Quantile) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SummaryValue_Quantile) ProtoMessage() {} + +func (x *SummaryValue_Quantile) ProtoReflect() protoreflect.Message { + mi := &file_openmetrics_data_model_proto_msgTypes[15] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SummaryValue_Quantile.ProtoReflect.Descriptor instead. +func (*SummaryValue_Quantile) Descriptor() ([]byte, []int) { + return file_openmetrics_data_model_proto_rawDescGZIP(), []int{12, 0} +} + +func (x *SummaryValue_Quantile) GetQuantile() float64 { + if x != nil { + return x.Quantile + } + return 0 +} + +func (x *SummaryValue_Quantile) GetValue() float64 { + if x != nil { + return x.Value + } + return 0 +} + +var File_openmetrics_data_model_proto protoreflect.FileDescriptor + +var file_openmetrics_data_model_proto_rawDesc = []byte{ + 0x0a, 0x1c, 0x6f, 0x70, 0x65, 0x6e, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x5f, 0x64, 0x61, + 0x74, 0x61, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0b, + 0x6f, 0x70, 0x65, 0x6e, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, + 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x4f, 0x0a, 0x09, + 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x53, 0x65, 0x74, 0x12, 0x42, 0x0a, 0x0f, 0x6d, 0x65, 0x74, + 0x72, 0x69, 0x63, 0x5f, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x69, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, + 0x2e, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x46, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x52, 0x0e, 0x6d, + 0x65, 0x74, 0x72, 0x69, 0x63, 0x46, 0x61, 0x6d, 0x69, 0x6c, 0x69, 0x65, 0x73, 0x22, 0xa6, 0x01, + 0x0a, 0x0c, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x46, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x12, 0x12, + 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, + 0x6d, 0x65, 0x12, 0x2b, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, + 0x32, 0x17, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x4d, + 0x65, 0x74, 0x72, 0x69, 0x63, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, + 0x12, 0x0a, 0x04, 0x75, 0x6e, 0x69, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x75, + 0x6e, 0x69, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x65, 0x6c, 0x70, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x04, 0x68, 0x65, 0x6c, 0x70, 0x12, 0x2d, 0x0a, 0x07, 0x6d, 0x65, 0x74, 0x72, 0x69, + 0x63, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x6d, + 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x52, 0x07, 0x6d, + 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x22, 0x73, 0x0a, 0x06, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, + 0x12, 0x2a, 0x0a, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x12, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x4c, + 0x61, 0x62, 0x65, 0x6c, 0x52, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x12, 0x3d, 0x0a, 0x0d, + 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x5f, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x18, 0x02, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, + 0x73, 0x2e, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x0c, 0x6d, + 0x65, 0x74, 0x72, 0x69, 0x63, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x22, 0x31, 0x0a, 0x05, 0x4c, + 0x61, 0x62, 0x65, 0x6c, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x99, + 0x04, 0x0a, 0x0b, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x40, + 0x0a, 0x0d, 0x75, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x6d, 0x65, 0x74, 0x72, + 0x69, 0x63, 0x73, 0x2e, 0x55, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x56, 0x61, 0x6c, 0x75, 0x65, + 0x48, 0x00, 0x52, 0x0c, 0x75, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x56, 0x61, 0x6c, 0x75, 0x65, + 0x12, 0x3a, 0x0a, 0x0b, 0x67, 0x61, 0x75, 0x67, 0x65, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x6d, 0x65, 0x74, 0x72, + 0x69, 0x63, 0x73, 0x2e, 0x47, 0x61, 0x75, 0x67, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x48, 0x00, + 0x52, 0x0a, 0x67, 0x61, 0x75, 0x67, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x40, 0x0a, 0x0d, + 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, + 0x73, 0x2e, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x48, 0x00, + 0x52, 0x0c, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x46, + 0x0a, 0x0f, 0x68, 0x69, 0x73, 0x74, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x5f, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x6d, 0x65, + 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x56, + 0x61, 0x6c, 0x75, 0x65, 0x48, 0x00, 0x52, 0x0e, 0x68, 0x69, 0x73, 0x74, 0x6f, 0x67, 0x72, 0x61, + 0x6d, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x44, 0x0a, 0x0f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, + 0x73, 0x65, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x1a, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x53, 0x74, + 0x61, 0x74, 0x65, 0x53, 0x65, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x48, 0x00, 0x52, 0x0d, 0x73, + 0x74, 0x61, 0x74, 0x65, 0x53, 0x65, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x37, 0x0a, 0x0a, + 0x69, 0x6e, 0x66, 0x6f, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x16, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x49, + 0x6e, 0x66, 0x6f, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x48, 0x00, 0x52, 0x09, 0x69, 0x6e, 0x66, 0x6f, + 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x40, 0x0a, 0x0d, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, + 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x6f, + 0x70, 0x65, 0x6e, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x53, 0x75, 0x6d, 0x6d, 0x61, + 0x72, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x48, 0x00, 0x52, 0x0c, 0x73, 0x75, 0x6d, 0x6d, 0x61, + 0x72, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x38, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, + 0x74, 0x61, 0x6d, 0x70, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, + 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, + 0x70, 0x42, 0x07, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x5b, 0x0a, 0x0c, 0x55, 0x6e, + 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x23, 0x0a, 0x0c, 0x64, 0x6f, + 0x75, 0x62, 0x6c, 0x65, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x01, + 0x48, 0x00, 0x52, 0x0b, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, + 0x1d, 0x0a, 0x09, 0x69, 0x6e, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x03, 0x48, 0x00, 0x52, 0x08, 0x69, 0x6e, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x07, + 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x59, 0x0a, 0x0a, 0x47, 0x61, 0x75, 0x67, 0x65, + 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x23, 0x0a, 0x0c, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x5f, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x01, 0x48, 0x00, 0x52, 0x0b, 0x64, + 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x1d, 0x0a, 0x09, 0x69, 0x6e, + 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x48, 0x00, 0x52, + 0x08, 0x69, 0x6e, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x07, 0x0a, 0x05, 0x76, 0x61, 0x6c, + 0x75, 0x65, 0x22, 0xc4, 0x01, 0x0a, 0x0c, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x56, 0x61, + 0x6c, 0x75, 0x65, 0x12, 0x23, 0x0a, 0x0c, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x5f, 0x76, 0x61, + 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x01, 0x48, 0x00, 0x52, 0x0b, 0x64, 0x6f, 0x75, + 0x62, 0x6c, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x1d, 0x0a, 0x09, 0x69, 0x6e, 0x74, 0x5f, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x48, 0x00, 0x52, 0x08, 0x69, + 0x6e, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x34, 0x0a, 0x07, 0x63, 0x72, 0x65, 0x61, 0x74, + 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, + 0x74, 0x61, 0x6d, 0x70, 0x52, 0x07, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x12, 0x31, 0x0a, + 0x08, 0x65, 0x78, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x15, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x45, 0x78, + 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x72, 0x52, 0x08, 0x65, 0x78, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x72, + 0x42, 0x07, 0x0a, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x22, 0xd9, 0x02, 0x0a, 0x0e, 0x48, 0x69, + 0x73, 0x74, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x23, 0x0a, 0x0c, + 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x01, 0x48, 0x00, 0x52, 0x0b, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x56, 0x61, 0x6c, 0x75, + 0x65, 0x12, 0x1d, 0x0a, 0x09, 0x69, 0x6e, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x03, 0x48, 0x00, 0x52, 0x08, 0x69, 0x6e, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, + 0x12, 0x14, 0x0a, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, + 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x34, 0x0a, 0x07, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, + 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, + 0x61, 0x6d, 0x70, 0x52, 0x07, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x12, 0x3c, 0x0a, 0x07, + 0x62, 0x75, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, + 0x6f, 0x70, 0x65, 0x6e, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x48, 0x69, 0x73, 0x74, + 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x2e, 0x42, 0x75, 0x63, 0x6b, 0x65, + 0x74, 0x52, 0x07, 0x62, 0x75, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x1a, 0x72, 0x0a, 0x06, 0x42, 0x75, + 0x63, 0x6b, 0x65, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x04, 0x52, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x75, 0x70, + 0x70, 0x65, 0x72, 0x5f, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x01, 0x52, + 0x0a, 0x75, 0x70, 0x70, 0x65, 0x72, 0x42, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x31, 0x0a, 0x08, 0x65, + 0x78, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, + 0x6f, 0x70, 0x65, 0x6e, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x45, 0x78, 0x65, 0x6d, + 0x70, 0x6c, 0x61, 0x72, 0x52, 0x08, 0x65, 0x78, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x72, 0x42, 0x05, + 0x0a, 0x03, 0x73, 0x75, 0x6d, 0x22, 0x84, 0x01, 0x0a, 0x08, 0x45, 0x78, 0x65, 0x6d, 0x70, 0x6c, + 0x61, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x01, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x38, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, + 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, + 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, + 0x6d, 0x70, 0x12, 0x28, 0x0a, 0x05, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x18, 0x03, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x12, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, + 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x52, 0x05, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x22, 0x80, 0x01, 0x0a, + 0x0d, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x65, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x38, + 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x20, + 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x53, 0x74, 0x61, + 0x74, 0x65, 0x53, 0x65, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, + 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x65, 0x73, 0x1a, 0x35, 0x0a, 0x05, 0x53, 0x74, 0x61, 0x74, + 0x65, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, + 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, + 0x33, 0x0a, 0x09, 0x49, 0x6e, 0x66, 0x6f, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x26, 0x0a, 0x04, + 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x6f, 0x70, 0x65, + 0x6e, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x52, 0x04, + 0x69, 0x6e, 0x66, 0x6f, 0x22, 0xa3, 0x02, 0x0a, 0x0c, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, + 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x23, 0x0a, 0x0c, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x5f, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x01, 0x48, 0x00, 0x52, 0x0b, 0x64, + 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x1d, 0x0a, 0x09, 0x69, 0x6e, + 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x48, 0x00, 0x52, + 0x08, 0x69, 0x6e, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x6f, 0x75, + 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12, + 0x34, 0x0a, 0x07, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, + 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x07, 0x63, 0x72, + 0x65, 0x61, 0x74, 0x65, 0x64, 0x12, 0x3e, 0x0a, 0x08, 0x71, 0x75, 0x61, 0x6e, 0x74, 0x69, 0x6c, + 0x65, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x6d, 0x65, + 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x56, 0x61, 0x6c, + 0x75, 0x65, 0x2e, 0x51, 0x75, 0x61, 0x6e, 0x74, 0x69, 0x6c, 0x65, 0x52, 0x08, 0x71, 0x75, 0x61, + 0x6e, 0x74, 0x69, 0x6c, 0x65, 0x1a, 0x3c, 0x0a, 0x08, 0x51, 0x75, 0x61, 0x6e, 0x74, 0x69, 0x6c, + 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x71, 0x75, 0x61, 0x6e, 0x74, 0x69, 0x6c, 0x65, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x01, 0x52, 0x08, 0x71, 0x75, 0x61, 0x6e, 0x74, 0x69, 0x6c, 0x65, 0x12, 0x14, 0x0a, + 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x01, 0x52, 0x05, 0x76, 0x61, + 0x6c, 0x75, 0x65, 0x42, 0x05, 0x0a, 0x03, 0x73, 0x75, 0x6d, 0x2a, 0x7b, 0x0a, 0x0a, 0x4d, 0x65, + 0x74, 0x72, 0x69, 0x63, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, + 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x47, 0x41, 0x55, 0x47, 0x45, 0x10, 0x01, + 0x12, 0x0b, 0x0a, 0x07, 0x43, 0x4f, 0x55, 0x4e, 0x54, 0x45, 0x52, 0x10, 0x02, 0x12, 0x0d, 0x0a, + 0x09, 0x53, 0x54, 0x41, 0x54, 0x45, 0x5f, 0x53, 0x45, 0x54, 0x10, 0x03, 0x12, 0x08, 0x0a, 0x04, + 0x49, 0x4e, 0x46, 0x4f, 0x10, 0x04, 0x12, 0x0d, 0x0a, 0x09, 0x48, 0x49, 0x53, 0x54, 0x4f, 0x47, + 0x52, 0x41, 0x4d, 0x10, 0x05, 0x12, 0x13, 0x0a, 0x0f, 0x47, 0x41, 0x55, 0x47, 0x45, 0x5f, 0x48, + 0x49, 0x53, 0x54, 0x4f, 0x47, 0x52, 0x41, 0x4d, 0x10, 0x06, 0x12, 0x0b, 0x0a, 0x07, 0x53, 0x55, + 0x4d, 0x4d, 0x41, 0x52, 0x59, 0x10, 0x07, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_openmetrics_data_model_proto_rawDescOnce sync.Once + file_openmetrics_data_model_proto_rawDescData = file_openmetrics_data_model_proto_rawDesc +) + +func file_openmetrics_data_model_proto_rawDescGZIP() []byte { + file_openmetrics_data_model_proto_rawDescOnce.Do(func() { + file_openmetrics_data_model_proto_rawDescData = protoimpl.X.CompressGZIP(file_openmetrics_data_model_proto_rawDescData) + }) + return file_openmetrics_data_model_proto_rawDescData +} + +var file_openmetrics_data_model_proto_enumTypes = make([]protoimpl.EnumInfo, 1) +var file_openmetrics_data_model_proto_msgTypes = make([]protoimpl.MessageInfo, 16) +var file_openmetrics_data_model_proto_goTypes = []interface{}{ + (MetricType)(0), // 0: openmetrics.MetricType + (*MetricSet)(nil), // 1: openmetrics.MetricSet + (*MetricFamily)(nil), // 2: openmetrics.MetricFamily + (*Metric)(nil), // 3: openmetrics.Metric + (*Label)(nil), // 4: openmetrics.Label + (*MetricPoint)(nil), // 5: openmetrics.MetricPoint + (*UnknownValue)(nil), // 6: openmetrics.UnknownValue + (*GaugeValue)(nil), // 7: openmetrics.GaugeValue + (*CounterValue)(nil), // 8: openmetrics.CounterValue + (*HistogramValue)(nil), // 9: openmetrics.HistogramValue + (*Exemplar)(nil), // 10: openmetrics.Exemplar + (*StateSetValue)(nil), // 11: openmetrics.StateSetValue + (*InfoValue)(nil), // 12: openmetrics.InfoValue + (*SummaryValue)(nil), // 13: openmetrics.SummaryValue + (*HistogramValue_Bucket)(nil), // 14: openmetrics.HistogramValue.Bucket + (*StateSetValue_State)(nil), // 15: openmetrics.StateSetValue.State + (*SummaryValue_Quantile)(nil), // 16: openmetrics.SummaryValue.Quantile + (*timestamppb.Timestamp)(nil), // 17: google.protobuf.Timestamp +} +var file_openmetrics_data_model_proto_depIdxs = []int32{ + 2, // 0: openmetrics.MetricSet.metric_families:type_name -> openmetrics.MetricFamily + 0, // 1: openmetrics.MetricFamily.type:type_name -> openmetrics.MetricType + 3, // 2: openmetrics.MetricFamily.metrics:type_name -> openmetrics.Metric + 4, // 3: openmetrics.Metric.labels:type_name -> openmetrics.Label + 5, // 4: openmetrics.Metric.metric_points:type_name -> openmetrics.MetricPoint + 6, // 5: openmetrics.MetricPoint.unknown_value:type_name -> openmetrics.UnknownValue + 7, // 6: openmetrics.MetricPoint.gauge_value:type_name -> openmetrics.GaugeValue + 8, // 7: openmetrics.MetricPoint.counter_value:type_name -> openmetrics.CounterValue + 9, // 8: openmetrics.MetricPoint.histogram_value:type_name -> openmetrics.HistogramValue + 11, // 9: openmetrics.MetricPoint.state_set_value:type_name -> openmetrics.StateSetValue + 12, // 10: openmetrics.MetricPoint.info_value:type_name -> openmetrics.InfoValue + 13, // 11: openmetrics.MetricPoint.summary_value:type_name -> openmetrics.SummaryValue + 17, // 12: openmetrics.MetricPoint.timestamp:type_name -> google.protobuf.Timestamp + 17, // 13: openmetrics.CounterValue.created:type_name -> google.protobuf.Timestamp + 10, // 14: openmetrics.CounterValue.exemplar:type_name -> openmetrics.Exemplar + 17, // 15: openmetrics.HistogramValue.created:type_name -> google.protobuf.Timestamp + 14, // 16: openmetrics.HistogramValue.buckets:type_name -> openmetrics.HistogramValue.Bucket + 17, // 17: openmetrics.Exemplar.timestamp:type_name -> google.protobuf.Timestamp + 4, // 18: openmetrics.Exemplar.label:type_name -> openmetrics.Label + 15, // 19: openmetrics.StateSetValue.states:type_name -> openmetrics.StateSetValue.State + 4, // 20: openmetrics.InfoValue.info:type_name -> openmetrics.Label + 17, // 21: openmetrics.SummaryValue.created:type_name -> google.protobuf.Timestamp + 16, // 22: openmetrics.SummaryValue.quantile:type_name -> openmetrics.SummaryValue.Quantile + 10, // 23: openmetrics.HistogramValue.Bucket.exemplar:type_name -> openmetrics.Exemplar + 24, // [24:24] is the sub-list for method output_type + 24, // [24:24] is the sub-list for method input_type + 24, // [24:24] is the sub-list for extension type_name + 24, // [24:24] is the sub-list for extension extendee + 0, // [0:24] is the sub-list for field type_name +} + +func init() { file_openmetrics_data_model_proto_init() } +func file_openmetrics_data_model_proto_init() { + if File_openmetrics_data_model_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_openmetrics_data_model_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*MetricSet); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_openmetrics_data_model_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*MetricFamily); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_openmetrics_data_model_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Metric); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_openmetrics_data_model_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Label); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_openmetrics_data_model_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*MetricPoint); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_openmetrics_data_model_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*UnknownValue); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_openmetrics_data_model_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GaugeValue); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_openmetrics_data_model_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*CounterValue); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_openmetrics_data_model_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*HistogramValue); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_openmetrics_data_model_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Exemplar); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_openmetrics_data_model_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*StateSetValue); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_openmetrics_data_model_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*InfoValue); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_openmetrics_data_model_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SummaryValue); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_openmetrics_data_model_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*HistogramValue_Bucket); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_openmetrics_data_model_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*StateSetValue_State); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_openmetrics_data_model_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SummaryValue_Quantile); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + file_openmetrics_data_model_proto_msgTypes[4].OneofWrappers = []interface{}{ + (*MetricPoint_UnknownValue)(nil), + (*MetricPoint_GaugeValue)(nil), + (*MetricPoint_CounterValue)(nil), + (*MetricPoint_HistogramValue)(nil), + (*MetricPoint_StateSetValue)(nil), + (*MetricPoint_InfoValue)(nil), + (*MetricPoint_SummaryValue)(nil), + } + file_openmetrics_data_model_proto_msgTypes[5].OneofWrappers = []interface{}{ + (*UnknownValue_DoubleValue)(nil), + (*UnknownValue_IntValue)(nil), + } + file_openmetrics_data_model_proto_msgTypes[6].OneofWrappers = []interface{}{ + (*GaugeValue_DoubleValue)(nil), + (*GaugeValue_IntValue)(nil), + } + file_openmetrics_data_model_proto_msgTypes[7].OneofWrappers = []interface{}{ + (*CounterValue_DoubleValue)(nil), + (*CounterValue_IntValue)(nil), + } + file_openmetrics_data_model_proto_msgTypes[8].OneofWrappers = []interface{}{ + (*HistogramValue_DoubleValue)(nil), + (*HistogramValue_IntValue)(nil), + } + file_openmetrics_data_model_proto_msgTypes[12].OneofWrappers = []interface{}{ + (*SummaryValue_DoubleValue)(nil), + (*SummaryValue_IntValue)(nil), + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_openmetrics_data_model_proto_rawDesc, + NumEnums: 1, + NumMessages: 16, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_openmetrics_data_model_proto_goTypes, + DependencyIndexes: file_openmetrics_data_model_proto_depIdxs, + EnumInfos: file_openmetrics_data_model_proto_enumTypes, + MessageInfos: file_openmetrics_data_model_proto_msgTypes, + }.Build() + File_openmetrics_data_model_proto = out.File + file_openmetrics_data_model_proto_rawDesc = nil + file_openmetrics_data_model_proto_goTypes = nil + file_openmetrics_data_model_proto_depIdxs = nil +} diff --git a/plugins/parsers/openmetrics/openmetrics_data_model.proto b/plugins/parsers/openmetrics/openmetrics_data_model.proto new file mode 100644 index 000000000..a95942d90 --- /dev/null +++ b/plugins/parsers/openmetrics/openmetrics_data_model.proto @@ -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; + } +} diff --git a/plugins/parsers/openmetrics/parser.go b/plugins/parsers/openmetrics/parser.go new file mode 100644 index 000000000..19f9d0dd8 --- /dev/null +++ b/plugins/parsers/openmetrics/parser.go @@ -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{} + }, + ) +} diff --git a/plugins/parsers/openmetrics/parser_test.go b/plugins/parsers/openmetrics/parser_test.go new file mode 100644 index 000000000..d3de8ce37 --- /dev/null +++ b/plugins/parsers/openmetrics/parser_test.go @@ -0,0 +1,176 @@ +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++ { + _, _ = 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++ { + _, _ = plugin.Parse(benchmarkData) + } +} diff --git a/plugins/parsers/openmetrics/testcases/dovecot/expected_v1.out b/plugins/parsers/openmetrics/testcases/dovecot/expected_v1.out new file mode 100644 index 000000000..1d36d9ae5 --- /dev/null +++ b/plugins/parsers/openmetrics/testcases/dovecot/expected_v1.out @@ -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 diff --git a/plugins/parsers/openmetrics/testcases/dovecot/expected_v2.out b/plugins/parsers/openmetrics/testcases/dovecot/expected_v2.out new file mode 100644 index 000000000..2d26b249a --- /dev/null +++ b/plugins/parsers/openmetrics/testcases/dovecot/expected_v2.out @@ -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 diff --git a/plugins/parsers/openmetrics/testcases/dovecot/input.txt b/plugins/parsers/openmetrics/testcases/dovecot/input.txt new file mode 100644 index 000000000..0b845d86d --- /dev/null +++ b/plugins/parsers/openmetrics/testcases/dovecot/input.txt @@ -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 \ No newline at end of file diff --git a/plugins/parsers/openmetrics/testcases/dovecot/telegraf.conf b/plugins/parsers/openmetrics/testcases/dovecot/telegraf.conf new file mode 100644 index 000000000..5f9ebc805 --- /dev/null +++ b/plugins/parsers/openmetrics/testcases/dovecot/telegraf.conf @@ -0,0 +1,4 @@ +[[inputs.test]] + files = ["input.txt"] + data_format = "openmetrics" + diff --git a/plugins/parsers/openmetrics/testcases/multiple/expected_v1.out b/plugins/parsers/openmetrics/testcases/multiple/expected_v1.out new file mode 100644 index 000000000..a86c43c3d --- /dev/null +++ b/plugins/parsers/openmetrics/testcases/multiple/expected_v1.out @@ -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 \ No newline at end of file diff --git a/plugins/parsers/openmetrics/testcases/multiple/expected_v2.out b/plugins/parsers/openmetrics/testcases/multiple/expected_v2.out new file mode 100644 index 000000000..f2846d32b --- /dev/null +++ b/plugins/parsers/openmetrics/testcases/multiple/expected_v2.out @@ -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 \ No newline at end of file diff --git a/plugins/parsers/openmetrics/testcases/multiple/input.txt b/plugins/parsers/openmetrics/testcases/multiple/input.txt new file mode 100644 index 000000000..19ac8ac0b --- /dev/null +++ b/plugins/parsers/openmetrics/testcases/multiple/input.txt @@ -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 \ No newline at end of file diff --git a/plugins/parsers/openmetrics/testcases/multiple/telegraf.conf b/plugins/parsers/openmetrics/testcases/multiple/telegraf.conf new file mode 100644 index 000000000..5f9ebc805 --- /dev/null +++ b/plugins/parsers/openmetrics/testcases/multiple/telegraf.conf @@ -0,0 +1,4 @@ +[[inputs.test]] + files = ["input.txt"] + data_format = "openmetrics" + diff --git a/plugins/parsers/openmetrics/testcases/protobuf/expected_v1.out b/plugins/parsers/openmetrics/testcases/protobuf/expected_v1.out new file mode 100644 index 000000000..1d36d9ae5 --- /dev/null +++ b/plugins/parsers/openmetrics/testcases/protobuf/expected_v1.out @@ -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 diff --git a/plugins/parsers/openmetrics/testcases/protobuf/expected_v2.out b/plugins/parsers/openmetrics/testcases/protobuf/expected_v2.out new file mode 100644 index 000000000..2d26b249a --- /dev/null +++ b/plugins/parsers/openmetrics/testcases/protobuf/expected_v2.out @@ -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 diff --git a/plugins/parsers/openmetrics/testcases/protobuf/input.bin b/plugins/parsers/openmetrics/testcases/protobuf/input.bin new file mode 100644 index 000000000..cd712a91e Binary files /dev/null and b/plugins/parsers/openmetrics/testcases/protobuf/input.bin differ diff --git a/plugins/parsers/openmetrics/testcases/protobuf/telegraf.conf b/plugins/parsers/openmetrics/testcases/protobuf/telegraf.conf new file mode 100644 index 000000000..8ef14acc0 --- /dev/null +++ b/plugins/parsers/openmetrics/testcases/protobuf/telegraf.conf @@ -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"} diff --git a/plugins/parsers/openmetrics/testcases/protobuf_infolabels/expected_v1.out b/plugins/parsers/openmetrics/testcases/protobuf_infolabels/expected_v1.out new file mode 100644 index 000000000..d3edc47d0 --- /dev/null +++ b/plugins/parsers/openmetrics/testcases/protobuf_infolabels/expected_v1.out @@ -0,0 +1 @@ +device_versioning,_type=untyped,location=office,device=machine,version=1.29.2,environment=production,build=42 info=1u diff --git a/plugins/parsers/openmetrics/testcases/protobuf_infolabels/expected_v2.out b/plugins/parsers/openmetrics/testcases/protobuf_infolabels/expected_v2.out new file mode 100644 index 000000000..cb586e9a3 --- /dev/null +++ b/plugins/parsers/openmetrics/testcases/protobuf_infolabels/expected_v2.out @@ -0,0 +1 @@ +openmetric,_type=untyped,location=office,device=machine,version=1.29.2,environment=production,build=42 device_versioning_info=1u diff --git a/plugins/parsers/openmetrics/testcases/protobuf_infolabels/input.bin b/plugins/parsers/openmetrics/testcases/protobuf_infolabels/input.bin new file mode 100644 index 000000000..3fac74219 --- /dev/null +++ b/plugins/parsers/openmetrics/testcases/protobuf_infolabels/input.bin @@ -0,0 +1,14 @@ + +‘ +device_versioning"A test info metric*f + +locationoffice + +devicemachine=2; + +version1.29.2 + + environment +production + +build42 \ No newline at end of file diff --git a/plugins/parsers/openmetrics/testcases/protobuf_infolabels/telegraf.conf b/plugins/parsers/openmetrics/testcases/protobuf_infolabels/telegraf.conf new file mode 100644 index 000000000..8ef14acc0 --- /dev/null +++ b/plugins/parsers/openmetrics/testcases/protobuf_infolabels/telegraf.conf @@ -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"} diff --git a/plugins/parsers/openmetrics/testcases/valid_counter/expected_v1.out b/plugins/parsers/openmetrics/testcases/valid_counter/expected_v1.out new file mode 100644 index 000000000..1f5d596de --- /dev/null +++ b/plugins/parsers/openmetrics/testcases/valid_counter/expected_v1.out @@ -0,0 +1 @@ +get_token_fail_count,_type=counter counter=8 diff --git a/plugins/parsers/openmetrics/testcases/valid_counter/expected_v2.out b/plugins/parsers/openmetrics/testcases/valid_counter/expected_v2.out new file mode 100644 index 000000000..b5e05273e --- /dev/null +++ b/plugins/parsers/openmetrics/testcases/valid_counter/expected_v2.out @@ -0,0 +1 @@ +openmetric,_type=counter get_token_fail_count=8 diff --git a/plugins/parsers/openmetrics/testcases/valid_counter/input.txt b/plugins/parsers/openmetrics/testcases/valid_counter/input.txt new file mode 100644 index 000000000..a99d41119 --- /dev/null +++ b/plugins/parsers/openmetrics/testcases/valid_counter/input.txt @@ -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 \ No newline at end of file diff --git a/plugins/parsers/openmetrics/testcases/valid_counter/telegraf.conf b/plugins/parsers/openmetrics/testcases/valid_counter/telegraf.conf new file mode 100644 index 000000000..5f9ebc805 --- /dev/null +++ b/plugins/parsers/openmetrics/testcases/valid_counter/telegraf.conf @@ -0,0 +1,4 @@ +[[inputs.test]] + files = ["input.txt"] + data_format = "openmetrics" + diff --git a/plugins/parsers/openmetrics/testcases/valid_gauge/expected_v1.out b/plugins/parsers/openmetrics/testcases/valid_gauge/expected_v1.out new file mode 100644 index 000000000..0fb245878 --- /dev/null +++ b/plugins/parsers/openmetrics/testcases/valid_gauge/expected_v1.out @@ -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 diff --git a/plugins/parsers/openmetrics/testcases/valid_gauge/expected_v2.out b/plugins/parsers/openmetrics/testcases/valid_gauge/expected_v2.out new file mode 100644 index 000000000..6782d5d12 --- /dev/null +++ b/plugins/parsers/openmetrics/testcases/valid_gauge/expected_v2.out @@ -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 diff --git a/plugins/parsers/openmetrics/testcases/valid_gauge/input.txt b/plugins/parsers/openmetrics/testcases/valid_gauge/input.txt new file mode 100644 index 000000000..0938d53ea --- /dev/null +++ b/plugins/parsers/openmetrics/testcases/valid_gauge/input.txt @@ -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 \ No newline at end of file diff --git a/plugins/parsers/openmetrics/testcases/valid_gauge/telegraf.conf b/plugins/parsers/openmetrics/testcases/valid_gauge/telegraf.conf new file mode 100644 index 000000000..e49895cce --- /dev/null +++ b/plugins/parsers/openmetrics/testcases/valid_gauge/telegraf.conf @@ -0,0 +1,3 @@ +[[inputs.test]] + files = ["input.txt"] + data_format = "openmetrics" diff --git a/plugins/parsers/openmetrics/testcases/valid_gaugehistogram/expected_v1.out b/plugins/parsers/openmetrics/testcases/valid_gaugehistogram/expected_v1.out new file mode 100644 index 000000000..9714755d4 --- /dev/null +++ b/plugins/parsers/openmetrics/testcases/valid_gaugehistogram/expected_v1.out @@ -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 diff --git a/plugins/parsers/openmetrics/testcases/valid_gaugehistogram/expected_v2.out b/plugins/parsers/openmetrics/testcases/valid_gaugehistogram/expected_v2.out new file mode 100644 index 000000000..37a2f2479 --- /dev/null +++ b/plugins/parsers/openmetrics/testcases/valid_gaugehistogram/expected_v2.out @@ -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 diff --git a/plugins/parsers/openmetrics/testcases/valid_gaugehistogram/input.txt b/plugins/parsers/openmetrics/testcases/valid_gaugehistogram/input.txt new file mode 100644 index 000000000..4ed8bf00e --- /dev/null +++ b/plugins/parsers/openmetrics/testcases/valid_gaugehistogram/input.txt @@ -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 \ No newline at end of file diff --git a/plugins/parsers/openmetrics/testcases/valid_gaugehistogram/telegraf.conf b/plugins/parsers/openmetrics/testcases/valid_gaugehistogram/telegraf.conf new file mode 100644 index 000000000..5f9ebc805 --- /dev/null +++ b/plugins/parsers/openmetrics/testcases/valid_gaugehistogram/telegraf.conf @@ -0,0 +1,4 @@ +[[inputs.test]] + files = ["input.txt"] + data_format = "openmetrics" + diff --git a/plugins/parsers/openmetrics/testcases/valid_histogram/expected_v1.out b/plugins/parsers/openmetrics/testcases/valid_histogram/expected_v1.out new file mode 100644 index 000000000..9714755d4 --- /dev/null +++ b/plugins/parsers/openmetrics/testcases/valid_histogram/expected_v1.out @@ -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 diff --git a/plugins/parsers/openmetrics/testcases/valid_histogram/expected_v2.out b/plugins/parsers/openmetrics/testcases/valid_histogram/expected_v2.out new file mode 100644 index 000000000..37a2f2479 --- /dev/null +++ b/plugins/parsers/openmetrics/testcases/valid_histogram/expected_v2.out @@ -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 diff --git a/plugins/parsers/openmetrics/testcases/valid_histogram/input.txt b/plugins/parsers/openmetrics/testcases/valid_histogram/input.txt new file mode 100644 index 000000000..4ed8bf00e --- /dev/null +++ b/plugins/parsers/openmetrics/testcases/valid_histogram/input.txt @@ -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 \ No newline at end of file diff --git a/plugins/parsers/openmetrics/testcases/valid_histogram/telegraf.conf b/plugins/parsers/openmetrics/testcases/valid_histogram/telegraf.conf new file mode 100644 index 000000000..5f9ebc805 --- /dev/null +++ b/plugins/parsers/openmetrics/testcases/valid_histogram/telegraf.conf @@ -0,0 +1,4 @@ +[[inputs.test]] + files = ["input.txt"] + data_format = "openmetrics" + diff --git a/plugins/parsers/openmetrics/testcases/valid_info/expected_v1.out b/plugins/parsers/openmetrics/testcases/valid_info/expected_v1.out new file mode 100644 index 000000000..b9ded28c2 --- /dev/null +++ b/plugins/parsers/openmetrics/testcases/valid_info/expected_v1.out @@ -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 diff --git a/plugins/parsers/openmetrics/testcases/valid_info/expected_v2.out b/plugins/parsers/openmetrics/testcases/valid_info/expected_v2.out new file mode 100644 index 000000000..2a9ad0487 --- /dev/null +++ b/plugins/parsers/openmetrics/testcases/valid_info/expected_v2.out @@ -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 diff --git a/plugins/parsers/openmetrics/testcases/valid_info/input.txt b/plugins/parsers/openmetrics/testcases/valid_info/input.txt new file mode 100644 index 000000000..e8bb1049f --- /dev/null +++ b/plugins/parsers/openmetrics/testcases/valid_info/input.txt @@ -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 \ No newline at end of file diff --git a/plugins/parsers/openmetrics/testcases/valid_info/telegraf.conf b/plugins/parsers/openmetrics/testcases/valid_info/telegraf.conf new file mode 100644 index 000000000..e49895cce --- /dev/null +++ b/plugins/parsers/openmetrics/testcases/valid_info/telegraf.conf @@ -0,0 +1,3 @@ +[[inputs.test]] + files = ["input.txt"] + data_format = "openmetrics" diff --git a/plugins/parsers/openmetrics/testcases/valid_stateset/expected_v1.out b/plugins/parsers/openmetrics/testcases/valid_stateset/expected_v1.out new file mode 100644 index 000000000..6d8521df1 --- /dev/null +++ b/plugins/parsers/openmetrics/testcases/valid_stateset/expected_v1.out @@ -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 diff --git a/plugins/parsers/openmetrics/testcases/valid_stateset/expected_v2.out b/plugins/parsers/openmetrics/testcases/valid_stateset/expected_v2.out new file mode 100644 index 000000000..861f1b4a5 --- /dev/null +++ b/plugins/parsers/openmetrics/testcases/valid_stateset/expected_v2.out @@ -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 diff --git a/plugins/parsers/openmetrics/testcases/valid_stateset/input.txt b/plugins/parsers/openmetrics/testcases/valid_stateset/input.txt new file mode 100644 index 000000000..6e587ed09 --- /dev/null +++ b/plugins/parsers/openmetrics/testcases/valid_stateset/input.txt @@ -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 \ No newline at end of file diff --git a/plugins/parsers/openmetrics/testcases/valid_stateset/telegraf.conf b/plugins/parsers/openmetrics/testcases/valid_stateset/telegraf.conf new file mode 100644 index 000000000..e49895cce --- /dev/null +++ b/plugins/parsers/openmetrics/testcases/valid_stateset/telegraf.conf @@ -0,0 +1,3 @@ +[[inputs.test]] + files = ["input.txt"] + data_format = "openmetrics" diff --git a/plugins/parsers/openmetrics/testcases/valid_summary/expected_v1.out b/plugins/parsers/openmetrics/testcases/valid_summary/expected_v1.out new file mode 100644 index 000000000..c79c7d71d --- /dev/null +++ b/plugins/parsers/openmetrics/testcases/valid_summary/expected_v1.out @@ -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 diff --git a/plugins/parsers/openmetrics/testcases/valid_summary/expected_v2.out b/plugins/parsers/openmetrics/testcases/valid_summary/expected_v2.out new file mode 100644 index 000000000..f50724df0 --- /dev/null +++ b/plugins/parsers/openmetrics/testcases/valid_summary/expected_v2.out @@ -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 \ No newline at end of file diff --git a/plugins/parsers/openmetrics/testcases/valid_summary/input.txt b/plugins/parsers/openmetrics/testcases/valid_summary/input.txt new file mode 100644 index 000000000..af2987882 --- /dev/null +++ b/plugins/parsers/openmetrics/testcases/valid_summary/input.txt @@ -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 \ No newline at end of file diff --git a/plugins/parsers/openmetrics/testcases/valid_summary/telegraf.conf b/plugins/parsers/openmetrics/testcases/valid_summary/telegraf.conf new file mode 100644 index 000000000..e49895cce --- /dev/null +++ b/plugins/parsers/openmetrics/testcases/valid_summary/telegraf.conf @@ -0,0 +1,3 @@ +[[inputs.test]] + files = ["input.txt"] + data_format = "openmetrics" diff --git a/plugins/parsers/openmetrics/testcases/valid_unknown/expected_v1.out b/plugins/parsers/openmetrics/testcases/valid_unknown/expected_v1.out new file mode 100644 index 000000000..9a9a3a856 --- /dev/null +++ b/plugins/parsers/openmetrics/testcases/valid_unknown/expected_v1.out @@ -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 diff --git a/plugins/parsers/openmetrics/testcases/valid_unknown/expected_v2.out b/plugins/parsers/openmetrics/testcases/valid_unknown/expected_v2.out new file mode 100644 index 000000000..237b610e5 --- /dev/null +++ b/plugins/parsers/openmetrics/testcases/valid_unknown/expected_v2.out @@ -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 diff --git a/plugins/parsers/openmetrics/testcases/valid_unknown/input.txt b/plugins/parsers/openmetrics/testcases/valid_unknown/input.txt new file mode 100644 index 000000000..876bb6e58 --- /dev/null +++ b/plugins/parsers/openmetrics/testcases/valid_unknown/input.txt @@ -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 \ No newline at end of file diff --git a/plugins/parsers/openmetrics/testcases/valid_unknown/telegraf.conf b/plugins/parsers/openmetrics/testcases/valid_unknown/telegraf.conf new file mode 100644 index 000000000..5f9ebc805 --- /dev/null +++ b/plugins/parsers/openmetrics/testcases/valid_unknown/telegraf.conf @@ -0,0 +1,4 @@ +[[inputs.test]] + files = ["input.txt"] + data_format = "openmetrics" + diff --git a/plugins/parsers/openmetrics/textparse.go b/plugins/parsers/openmetrics/textparse.go new file mode 100644 index 000000000..fadc625cb --- /dev/null +++ b/plugins/parsers/openmetrics/textparse.go @@ -0,0 +1,393 @@ +package openmetrics + +import ( + "bytes" + "errors" + "fmt" + "hash/maphash" + "io" + "math" + "slices" + "strconv" + "strings" + "time" + + "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) + + 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 textparse.MetricTypeCounter: + mf.Type = MetricType_COUNTER + case textparse.MetricTypeGauge: + mf.Type = MetricType_GAUGE + case textparse.MetricTypeHistogram: + mf.Type = MetricType_HISTOGRAM + case textparse.MetricTypeGaugeHistogram: + mf.Type = MetricType_GAUGE_HISTOGRAM + case textparse.MetricTypeSummary: + mf.Type = MetricType_SUMMARY + case textparse.MetricTypeInfo: + mf.Type = MetricType_INFO + case textparse.MetricTypeStateset: + mf.Type = MetricType_STATE_SET + case textparse.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 + } +} diff --git a/plugins/parsers/prometheus/parser.go b/plugins/parsers/prometheus/parser.go index 62db36a39..3d78c4f2d 100644 --- a/plugins/parsers/prometheus/parser.go +++ b/plugins/parsers/prometheus/parser.go @@ -14,6 +14,10 @@ import ( "github.com/influxdata/telegraf/plugins/parsers" ) +func AcceptsContent(header http.Header) bool { + return expfmt.ResponseFormat(header).FormatType() != expfmt.TypeUnknown +} + type Parser struct { IgnoreTimestamp bool `toml:"prometheus_ignore_timestamp"` MetricVersion int `toml:"prometheus_metric_version"`