in components/google-built-opentelemetry-collector/exporter/googleservicecontrolexporter/exporter.go [458:516]
func translateDistributionValue(value pmetric.HistogramDataPoint) *scpb.Distribution {
result := &scpb.Distribution{
Count: int64(value.Count()),
BucketOption: &scpb.Distribution_ExplicitBuckets_{
&scpb.Distribution_ExplicitBuckets{
Bounds: value.ExplicitBounds().AsRaw(),
},
},
BucketCounts: toInt64Slice(value.BucketCounts().AsRaw()),
}
exemplars := value.Exemplars()
// We compute `sum` from `exemplars`, instead of getting it from `value.Sum()`.
// Sum is optional in pmetric.HistogramDataPoint.
// Note that Exemplars are optional as well.
var sum float64
for i := 0; i < exemplars.Len(); i++ {
ex := exemplars.At(i)
// Service Control only has double value type:
// https://github.com/googleapis/googleapis/blob/40bad3ea0d48ecf250296ea7438035b8e45227dd/google/api/distribution.proto#L147,
// so we convert everything to float64.
var value float64
switch ex.ValueType() {
case pmetric.ExemplarValueTypeDouble:
value = ex.DoubleValue()
case pmetric.ExemplarValueTypeInt:
value = float64(ex.IntValue())
}
sum += value
result.Exemplars = append(result.Exemplars, &distribution.Distribution_Exemplar{
Value: value,
Timestamp: timestamppb.New(ex.Timestamp().AsTime()),
})
}
// Service Control API does not like if we set non-zero mean and deviation when count=0:
// https://github.com/googleapis/google-api-go-client/blob/8a616df18563c9fedaead92873d200cd8c2d0503/servicecontrol/v1/servicecontrol-gen.go#L853
if value.Count() > 0 {
if exemplars.Len() > 0 {
// We can calculate everything ourselves.
mean := sum / float64(value.Count())
result.Mean = mean
// SumOfSquaredDeviation calculation:
// https://github.com/googleapis/google-api-go-client/blob/8a616df18563c9fedaead92873d200cd8c2d0503/servicecontrol/v1/servicecontrol-gen.go#L860
var sumDev float64
for _, exemplar := range result.Exemplars {
dev := exemplar.Value - mean
sumDev += dev * dev
}
result.SumOfSquaredDeviation = sumDev
} else {
// We can only hope that `value.Sum()` is populated, and calculate `result.Mean` from that.
// There is no way to calculate `result.SumOfSquaredDeviation`.
result.Mean = value.Sum() / float64(value.Count())
}
}
return result
}