in exporter/collector/metrics.go [1023:1068]
func (m *metricMapper) histogramPoint(point pmetric.HistogramDataPoint, projectID string) *monitoringpb.TypedValue {
counts := make([]int64, point.BucketCounts().Len())
var mean, deviation, prevBound float64
for i := 0; i < point.BucketCounts().Len(); i++ {
counts[i] = int64(point.BucketCounts().At(i))
}
if !math.IsNaN(point.Sum()) && point.Count() > 0 { // Avoid divide-by-zero
mean = float64(point.Sum() / float64(point.Count()))
}
bounds := point.ExplicitBounds()
if m.cfg.MetricConfig.EnableSumOfSquaredDeviation {
// Calculate the sum of squared deviation.
for i := 0; i < bounds.Len(); i++ {
// Assume all points in the bucket occur at the middle of the bucket range
middleOfBucket := (prevBound + bounds.At(i)) / 2
deviation += float64(counts[i]) * (middleOfBucket - mean) * (middleOfBucket - mean)
prevBound = bounds.At(i)
}
// The infinity bucket is an implicit +Inf bound after the list of explicit bounds.
// Assume points in the infinity bucket are at the top of the previous bucket
middleOfInfBucket := prevBound
deviation += float64(counts[len(counts)-1]) * (middleOfInfBucket - mean) * (middleOfInfBucket - mean)
}
return &monitoringpb.TypedValue{
Value: &monitoringpb.TypedValue_DistributionValue{
DistributionValue: &distribution.Distribution{
Count: int64(point.Count()),
Mean: mean,
BucketCounts: counts,
SumOfSquaredDeviation: deviation,
BucketOptions: &distribution.Distribution_BucketOptions{
Options: &distribution.Distribution_BucketOptions_ExplicitBuckets{
ExplicitBuckets: &distribution.Distribution_BucketOptions_Explicit{
Bounds: bounds.AsRaw(),
},
},
},
Exemplars: m.exemplars(point.Exemplars(), projectID),
},
},
}
}