diff --git a/pkg/translator/signalfx/from_metrics.go b/pkg/translator/signalfx/from_metrics.go index 9d961836e14c..36c40037eaa5 100644 --- a/pkg/translator/signalfx/from_metrics.go +++ b/pkg/translator/signalfx/from_metrics.go @@ -133,7 +133,19 @@ func convertNumberDataPoints(in pmetric.NumberDataPointSlice, name string, mt *s func convertHistogram(in pmetric.HistogramDataPointSlice, name string, mt *sfxpb.MetricType, extraDims []*sfxpb.Dimension) []*sfxpb.DataPoint { var numDPs int for i := 0; i < in.Len(); i++ { - numDPs += 2 + in.At(i).BucketCounts().Len() + histDP := in.At(i) + numDPs += 1 + histDP.BucketCounts().Len() + if histDP.HasSum() { + numDPs++ + } + + if histDP.HasMin() { + numDPs++ + } + + if histDP.HasMax() { + numDPs++ + } } dps := newDpsBuilder(numDPs) @@ -146,10 +158,25 @@ func convertHistogram(in pmetric.HistogramDataPointSlice, name string, mt *sfxpb count := int64(histDP.Count()) countDP.Value.IntValue = &count - sumName := name + "_sum" - sumDP := dps.appendPoint(sumName, mt, ts, dims) - sum := histDP.Sum() - sumDP.Value.DoubleValue = &sum + if histDP.HasSum() { + sumDP := dps.appendPoint(name+"_sum", mt, ts, dims) + sum := histDP.Sum() + sumDP.Value.DoubleValue = &sum + } + + if histDP.HasMin() { + // Min is always a gauge. + minDP := dps.appendPoint(name+"_min", &sfxMetricTypeGauge, ts, dims) + min := histDP.Min() + minDP.Value.DoubleValue = &min + } + + if histDP.HasMax() { + // Max is always a gauge. + maxDP := dps.appendPoint(name+"_max", &sfxMetricTypeGauge, ts, dims) + max := histDP.Max() + maxDP.Value.DoubleValue = &max + } bounds := histDP.ExplicitBounds() counts := histDP.BucketCounts() diff --git a/pkg/translator/signalfx/from_metrics_test.go b/pkg/translator/signalfx/from_metrics_test.go index 6915f3e98d57..57ac229a82f9 100644 --- a/pkg/translator/signalfx/from_metrics_test.go +++ b/pkg/translator/signalfx/from_metrics_test.go @@ -67,15 +67,21 @@ func Test_FromMetrics(t *testing.T) { attrMap.CopyTo(dp.Attributes()) } - initHistDP := func(dp pmetric.HistogramDataPoint) { + initHistDPNoOptional := func(dp pmetric.HistogramDataPoint) { dp.SetTimestamp(ts) dp.SetCount(16) - dp.SetSum(100.0) dp.SetExplicitBounds(pcommon.NewImmutableFloat64Slice([]float64{1, 2, 4})) dp.SetBucketCounts(pcommon.NewImmutableUInt64Slice([]uint64{4, 2, 3, 7})) attrMap.CopyTo(dp.Attributes()) } + initHistDP := func(dp pmetric.HistogramDataPoint) { + initHistDPNoOptional(dp) + dp.SetSum(100.0) + dp.SetMin(0.1) + dp.SetMax(11.11) + } + tests := []struct { name string metricsFn func() pmetric.Metrics @@ -268,6 +274,32 @@ func Test_FromMetrics(t *testing.T) { wantSfxDataPoints: []*sfxpb.DataPoint{ int64SFxDataPoint("histogram_count", &sfxMetricTypeCumulativeCounter, labelMap, 16), doubleSFxDataPoint("histogram_sum", &sfxMetricTypeCumulativeCounter, labelMap, 100.0), + doubleSFxDataPoint("histogram_min", &sfxMetricTypeGauge, labelMap, 0.1), + doubleSFxDataPoint("histogram_max", &sfxMetricTypeGauge, labelMap, 11.11), + int64SFxDataPoint("histogram_bucket", &sfxMetricTypeCumulativeCounter, + maps.MergeStringMaps(map[string]string{bucketDimensionKey: "1"}, labelMap), 4), + int64SFxDataPoint("histogram_bucket", &sfxMetricTypeCumulativeCounter, + maps.MergeStringMaps(map[string]string{bucketDimensionKey: "2"}, labelMap), 6), + int64SFxDataPoint("histogram_bucket", &sfxMetricTypeCumulativeCounter, + maps.MergeStringMaps(map[string]string{bucketDimensionKey: "4"}, labelMap), 9), + int64SFxDataPoint("histogram_bucket", &sfxMetricTypeCumulativeCounter, + maps.MergeStringMaps(map[string]string{bucketDimensionKey: "+Inf"}, labelMap), 16), + }, + }, + { + name: "histogram_no_optional", + metricsFn: func() pmetric.Metrics { + out := pmetric.NewMetrics() + ilm := out.ResourceMetrics().AppendEmpty().ScopeMetrics().AppendEmpty() + m := ilm.Metrics().AppendEmpty() + m.SetName("histogram") + m.SetDataType(pmetric.MetricDataTypeHistogram) + m.Histogram().SetAggregationTemporality(pmetric.MetricAggregationTemporalityCumulative) + initHistDPNoOptional(m.Histogram().DataPoints().AppendEmpty()) + return out + }, + wantSfxDataPoints: []*sfxpb.DataPoint{ + int64SFxDataPoint("histogram_count", &sfxMetricTypeCumulativeCounter, labelMap, 16), int64SFxDataPoint("histogram_bucket", &sfxMetricTypeCumulativeCounter, maps.MergeStringMaps(map[string]string{bucketDimensionKey: "1"}, labelMap), 4), int64SFxDataPoint("histogram_bucket", &sfxMetricTypeCumulativeCounter, @@ -293,6 +325,8 @@ func Test_FromMetrics(t *testing.T) { wantSfxDataPoints: []*sfxpb.DataPoint{ int64SFxDataPoint("delta_histogram_count", &sfxMetricTypeCounter, labelMap, 16), doubleSFxDataPoint("delta_histogram_sum", &sfxMetricTypeCounter, labelMap, 100.0), + doubleSFxDataPoint("delta_histogram_min", &sfxMetricTypeGauge, labelMap, 0.1), + doubleSFxDataPoint("delta_histogram_max", &sfxMetricTypeGauge, labelMap, 11.11), int64SFxDataPoint("delta_histogram_bucket", &sfxMetricTypeCounter, maps.MergeStringMaps(map[string]string{bucketDimensionKey: "1"}, labelMap), 4), int64SFxDataPoint("delta_histogram_bucket", &sfxMetricTypeCounter, diff --git a/unreleased/signalfx_export_min_max.yaml b/unreleased/signalfx_export_min_max.yaml new file mode 100755 index 000000000000..2f57e35cd470 --- /dev/null +++ b/unreleased/signalfx_export_min_max.yaml @@ -0,0 +1,11 @@ +# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix' +change_type: enhancement + +# The name of the component, or a single word describing the area of concern, (e.g. filelogreceiver) +component: pkg/translator/signalfx + +# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`). +note: report Histogram min/max when present, do not report sum when not present + +# One or more tracking issues related to the change +issues: [13153]