in collector/receiver/prometheusreceiver/internal/metricfamily.go [100:158]
func (mg *metricGroup) toDistributionPoint(dest pmetric.HistogramDataPointSlice) {
if !mg.hasCount || len(mg.complexValue) == 0 {
return
}
mg.sortPoints()
// for OTLP the bounds won't include +inf
bounds := make([]float64, len(mg.complexValue)-1)
bucketCounts := make([]uint64, len(mg.complexValue))
pointIsStale := value.IsStaleNaN(mg.sum) || value.IsStaleNaN(mg.count)
for i := 0; i < len(mg.complexValue); i++ {
if i != len(mg.complexValue)-1 {
// not need to add +inf as OTLP assumes it
bounds[i] = mg.complexValue[i].boundary
} else if mg.complexValue[i].boundary != math.Inf(1) {
// This histogram is missing the +Inf bucket, and isn't a complete prometheus histogram.
return
}
adjustedCount := mg.complexValue[i].value
// Buckets still need to be sent to know to set them as stale,
// but a staleness NaN converted to uint64 would be an extremely large number.
// Setting to 0 instead.
if pointIsStale {
adjustedCount = 0
} else if i != 0 {
adjustedCount -= mg.complexValue[i-1].value
}
bucketCounts[i] = uint64(adjustedCount)
}
point := dest.AppendEmpty()
if pointIsStale {
point.SetFlags(pmetric.DefaultDataPointFlags.WithNoRecordedValue(true))
} else {
point.SetCount(uint64(mg.count))
if mg.hasSum {
point.SetSum(mg.sum)
}
}
point.ExplicitBounds().FromRaw(bounds)
point.BucketCounts().FromRaw(bucketCounts)
// The timestamp MUST be in retrieved from milliseconds and converted to nanoseconds.
tsNanos := timestampFromMs(mg.ts)
if mg.created != 0 {
point.SetStartTimestamp(timestampFromFloat64(mg.created))
} else {
// metrics_adjuster adjusts the startTimestamp to the initial scrape timestamp
point.SetStartTimestamp(tsNanos)
}
point.SetTimestamp(tsNanos)
populateAttributes(pmetric.MetricTypeHistogram, mg.ls, point.Attributes())
mg.setExemplars(point.Exemplars())
}