Skip to content

Commit

Permalink
prometheusremotewriteexporter: fix panic on histogram without buckets (
Browse files Browse the repository at this point in the history
  • Loading branch information
dashpole committed Aug 1, 2022
1 parent 9adc808 commit 1fe70b7
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 22 deletions.
9 changes: 9 additions & 0 deletions exporter/prometheusremotewriteexporter/exporter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -369,6 +369,8 @@ func Test_PushMetrics(t *testing.T) {

histogramBatch := getMetricsFromMetricList(validMetrics1[validHistogram], validMetrics2[validHistogram])

emptyDataPointHistogramBatch := getMetricsFromMetricList(validMetrics1[validEmptyHistogram], validMetrics2[validEmptyHistogram])

summaryBatch := getMetricsFromMetricList(validMetrics1[validSummary], validMetrics2[validSummary])

// len(BucketCount) > len(ExplicitBounds)
Expand Down Expand Up @@ -470,6 +472,13 @@ func Test_PushMetrics(t *testing.T) {
expectedTimeSeries: 12,
httpResponseCode: http.StatusAccepted,
},
{
name: "valid_empty_histogram_case",
metrics: &emptyDataPointHistogramBatch,
reqTestFunc: checkFunc,
expectedTimeSeries: 6,
httpResponseCode: http.StatusAccepted,
},
{
name: "summary_case",
metrics: &summaryBatch,
Expand Down
56 changes: 35 additions & 21 deletions exporter/prometheusremotewriteexporter/testutil_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,36 +56,39 @@ var (
quantileValues = []float64{7, 8, 9}
quantiles = getQuantiles(quantileBounds, quantileValues)

validIntGauge = "valid_IntGauge"
validDoubleGauge = "valid_DoubleGauge"
validIntSum = "valid_IntSum"
validSum = "valid_Sum"
validHistogram = "valid_Histogram"
validSummary = "valid_Summary"
suffixedCounter = "valid_IntSum_total"
validIntGauge = "valid_IntGauge"
validDoubleGauge = "valid_DoubleGauge"
validIntSum = "valid_IntSum"
validSum = "valid_Sum"
validHistogram = "valid_Histogram"
validEmptyHistogram = "valid_empty_Histogram"
validSummary = "valid_Summary"
suffixedCounter = "valid_IntSum_total"

validIntGaugeDirty = "*valid_IntGauge$"

unmatchedBoundBucketHist = "unmatchedBoundBucketHist"

// valid metrics as input should not return error
validMetrics1 = map[string]pmetric.Metric{
validIntGauge: getIntGaugeMetric(validIntGauge, lbs1, intVal1, time1),
validDoubleGauge: getDoubleGaugeMetric(validDoubleGauge, lbs1, floatVal1, time1),
validIntSum: getIntSumMetric(validIntSum, lbs1, intVal1, time1),
suffixedCounter: getIntSumMetric(suffixedCounter, lbs1, intVal1, time1),
validSum: getSumMetric(validSum, lbs1, floatVal1, time1),
validHistogram: getHistogramMetric(validHistogram, lbs1, time1, floatVal1, uint64(intVal1), bounds, buckets),
validSummary: getSummaryMetric(validSummary, lbs1, time1, floatVal1, uint64(intVal1), quantiles),
validIntGauge: getIntGaugeMetric(validIntGauge, lbs1, intVal1, time1),
validDoubleGauge: getDoubleGaugeMetric(validDoubleGauge, lbs1, floatVal1, time1),
validIntSum: getIntSumMetric(validIntSum, lbs1, intVal1, time1),
suffixedCounter: getIntSumMetric(suffixedCounter, lbs1, intVal1, time1),
validSum: getSumMetric(validSum, lbs1, floatVal1, time1),
validHistogram: getHistogramMetric(validHistogram, lbs1, time1, floatVal1, uint64(intVal1), bounds, buckets),
validEmptyHistogram: getHistogramMetricEmptyDataPoint(validEmptyHistogram, lbs1, time1),
validSummary: getSummaryMetric(validSummary, lbs1, time1, floatVal1, uint64(intVal1), quantiles),
}
validMetrics2 = map[string]pmetric.Metric{
validIntGauge: getIntGaugeMetric(validIntGauge, lbs2, intVal2, time2),
validDoubleGauge: getDoubleGaugeMetric(validDoubleGauge, lbs2, floatVal2, time2),
validIntSum: getIntSumMetric(validIntSum, lbs2, intVal2, time2),
validSum: getSumMetric(validSum, lbs2, floatVal2, time2),
validHistogram: getHistogramMetric(validHistogram, lbs2, time2, floatVal2, uint64(intVal2), bounds, buckets),
validSummary: getSummaryMetric(validSummary, lbs2, time2, floatVal2, uint64(intVal2), quantiles),
validIntGaugeDirty: getIntGaugeMetric(validIntGaugeDirty, lbs1, intVal1, time1),
validIntGauge: getIntGaugeMetric(validIntGauge, lbs2, intVal2, time2),
validDoubleGauge: getDoubleGaugeMetric(validDoubleGauge, lbs2, floatVal2, time2),
validIntSum: getIntSumMetric(validIntSum, lbs2, intVal2, time2),
validSum: getSumMetric(validSum, lbs2, floatVal2, time2),
validHistogram: getHistogramMetric(validHistogram, lbs2, time2, floatVal2, uint64(intVal2), bounds, buckets),
validEmptyHistogram: getHistogramMetricEmptyDataPoint(validEmptyHistogram, lbs2, time2),
validSummary: getSummaryMetric(validSummary, lbs2, time2, floatVal2, uint64(intVal2), quantiles),
validIntGaugeDirty: getIntGaugeMetric(validIntGaugeDirty, lbs1, intVal1, time1),
unmatchedBoundBucketHist: getHistogramMetric(unmatchedBoundBucketHist, pcommon.NewMap(), 0, 0, 0,
pcommon.NewImmutableFloat64Slice([]float64{0.1, 0.2, 0.3}),
pcommon.NewImmutableUInt64Slice([]uint64{1, 2})),
Expand Down Expand Up @@ -293,6 +296,17 @@ func getEmptyCumulativeHistogramMetric(name string) pmetric.Metric {
return metric
}

func getHistogramMetricEmptyDataPoint(name string, attributes pcommon.Map, ts uint64) pmetric.Metric {
metric := pmetric.NewMetric()
metric.SetName(name)
metric.SetDataType(pmetric.MetricDataTypeHistogram)
metric.Histogram().SetAggregationTemporality(pmetric.MetricAggregationTemporalityCumulative)
dp := metric.Histogram().DataPoints().AppendEmpty()
attributes.CopyTo(dp.Attributes())
dp.SetTimestamp(pcommon.Timestamp(ts))
return metric
}

func getHistogramMetric(name string, attributes pcommon.Map, ts uint64, sum float64, count uint64, bounds pcommon.ImmutableFloat64Slice,
buckets pcommon.ImmutableUInt64Slice) pmetric.Metric {
metric := pmetric.NewMetric()
Expand Down
4 changes: 3 additions & 1 deletion pkg/translator/prometheusremotewrite/helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -343,7 +343,9 @@ func addSingleHistogramDataPoint(pt pmetric.HistogramDataPoint, resource pcommon
if pt.Flags().HasFlag(pmetric.MetricDataPointFlagNoRecordedValue) {
infBucket.Value = math.Float64frombits(value.StaleNaN)
} else {
cumulativeCount += pt.BucketCounts().At(pt.BucketCounts().Len() - 1)
if pt.BucketCounts().Len() > 0 {
cumulativeCount += pt.BucketCounts().At(pt.BucketCounts().Len() - 1)
}
infBucket.Value = float64(cumulativeCount)
}
infLabels := createAttributes(resource, pt.Attributes(), settings.ExternalLabels, nameStr, baseName+bucketStr, leStr, pInfStr)
Expand Down
11 changes: 11 additions & 0 deletions unreleased/prw-no-hist-panic.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix'
change_type: bug_fix

# The name of the component, or a single word describing the area of concern, (e.g. filelogreceiver)
component: exporter/prometheusremotewrite

# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`).
note: "Fix a panic when a histogram does not have any buckets"

# One or more tracking issues related to the change
issues: [12777]

0 comments on commit 1fe70b7

Please sign in to comment.