exporter/sumologicexporter/otlp.go (119 lines of code) (raw):

// Copyright The OpenTelemetry Authors // SPDX-License-Identifier: Apache-2.0 package sumologicexporter // import "github.com/open-telemetry/opentelemetry-collector-contrib/exporter/sumologicexporter" import ( "math" "go.opentelemetry.io/collector/pdata/pmetric" ) // decomposeHistograms decomposes any histograms present in the metric data into individual Sums and Gauges // This is a noop if no Histograms are present, but otherwise makes a copy of the whole structure // This exists because Sumo doesn't support OTLP histograms yet, and has the same semantics as the conversion to Prometheus format in prometheus_formatter.go func decomposeHistograms(md pmetric.Metrics) pmetric.Metrics { // short circuit and do nothing if no Histograms are present foundHistogram := false outer: for i := 0; i < md.ResourceMetrics().Len(); i++ { resourceMetric := md.ResourceMetrics().At(i) for j := 0; j < resourceMetric.ScopeMetrics().Len(); j++ { scopeMetric := resourceMetric.ScopeMetrics().At(j) for k := 0; k < scopeMetric.Metrics().Len(); k++ { foundHistogram = scopeMetric.Metrics().At(k).Type() == pmetric.MetricTypeHistogram if foundHistogram { break outer } } } } if !foundHistogram { return md } decomposed := pmetric.NewMetrics() md.CopyTo(decomposed) for i := 0; i < decomposed.ResourceMetrics().Len(); i++ { resourceMetric := decomposed.ResourceMetrics().At(i) for j := 0; j < resourceMetric.ScopeMetrics().Len(); j++ { metrics := resourceMetric.ScopeMetrics().At(j).Metrics() for k := 0; k < metrics.Len(); k++ { metric := metrics.At(k) if metric.Type() == pmetric.MetricTypeHistogram { decomposedHistogram := decomposeHistogram(metric) decomposedHistogram.MoveAndAppendTo(metrics) } } metrics.RemoveIf(func(m pmetric.Metric) bool { return m.Type() == pmetric.MetricTypeHistogram }) } } return decomposed } // decomposeHistogram decomposes a single Histogram metric into individual metrics for count, bucket and sum // non-Histograms give an empty slice as output func decomposeHistogram(metric pmetric.Metric) pmetric.MetricSlice { output := pmetric.NewMetricSlice() if metric.Type() != pmetric.MetricTypeHistogram { return output } getHistogramSumMetric(metric).MoveTo(output.AppendEmpty()) getHistogramCountMetric(metric).MoveTo(output.AppendEmpty()) getHistogramBucketsMetric(metric).MoveTo(output.AppendEmpty()) return output } func getHistogramBucketsMetric(metric pmetric.Metric) pmetric.Metric { histogram := metric.Histogram() bucketsMetric := pmetric.NewMetric() bucketsMetric.SetName(metric.Name() + "_bucket") bucketsMetric.SetDescription(metric.Description()) bucketsMetric.SetUnit(metric.Unit()) bucketsMetric.SetEmptyGauge() bucketsDatapoints := bucketsMetric.Gauge().DataPoints() for i := 0; i < histogram.DataPoints().Len(); i++ { histogramDataPoint := histogram.DataPoints().At(i) histogramBounds := histogramDataPoint.ExplicitBounds() var cumulative uint64 for j := 0; j < histogramBounds.Len(); j++ { bucketDataPoint := bucketsDatapoints.AppendEmpty() bound := histogramBounds.At(j) histogramDataPoint.Attributes().CopyTo(bucketDataPoint.Attributes()) bucketDataPoint.Attributes().PutDouble(prometheusLeTag, bound) bucketDataPoint.SetStartTimestamp(histogramDataPoint.StartTimestamp()) bucketDataPoint.SetTimestamp(histogramDataPoint.Timestamp()) cumulative += histogramDataPoint.BucketCounts().At(j) bucketDataPoint.SetIntValue(int64(cumulative)) } // need to add one more bucket at +Inf bucketDataPoint := bucketsDatapoints.AppendEmpty() histogramDataPoint.Attributes().CopyTo(bucketDataPoint.Attributes()) bucketDataPoint.Attributes().PutDouble(prometheusLeTag, math.Inf(1)) bucketDataPoint.SetStartTimestamp(histogramDataPoint.StartTimestamp()) bucketDataPoint.SetTimestamp(histogramDataPoint.Timestamp()) cumulative += histogramDataPoint.BucketCounts().At(histogramDataPoint.ExplicitBounds().Len()) bucketDataPoint.SetIntValue(int64(cumulative)) } return bucketsMetric } func getHistogramSumMetric(metric pmetric.Metric) pmetric.Metric { histogram := metric.Histogram() sumMetric := pmetric.NewMetric() sumMetric.SetName(metric.Name() + "_sum") sumMetric.SetDescription(metric.Description()) sumMetric.SetUnit(metric.Unit()) sumMetric.SetEmptyGauge() sumDataPoints := sumMetric.Gauge().DataPoints() for i := 0; i < histogram.DataPoints().Len(); i++ { histogramDataPoint := histogram.DataPoints().At(i) sumDataPoint := sumDataPoints.AppendEmpty() histogramDataPoint.Attributes().CopyTo(sumDataPoint.Attributes()) sumDataPoint.SetStartTimestamp(histogramDataPoint.StartTimestamp()) sumDataPoint.SetTimestamp(histogramDataPoint.Timestamp()) sumDataPoint.SetDoubleValue(histogramDataPoint.Sum()) } return sumMetric } func getHistogramCountMetric(metric pmetric.Metric) pmetric.Metric { histogram := metric.Histogram() countMetric := pmetric.NewMetric() countMetric.SetName(metric.Name() + "_count") countMetric.SetDescription(metric.Description()) countMetric.SetUnit(metric.Unit()) countMetric.SetEmptyGauge() countDataPoints := countMetric.Gauge().DataPoints() for i := 0; i < histogram.DataPoints().Len(); i++ { histogramDataPoint := histogram.DataPoints().At(i) countDataPoint := countDataPoints.AppendEmpty() histogramDataPoint.Attributes().CopyTo(countDataPoint.Attributes()) countDataPoint.SetStartTimestamp(histogramDataPoint.StartTimestamp()) countDataPoint.SetTimestamp(histogramDataPoint.Timestamp()) countDataPoint.SetIntValue(int64(histogramDataPoint.Count())) } return countMetric }