in exporter/collector/metrics.go [967:1008]
func (m *metricMapper) exemplar(ex pmetric.Exemplar, projectID string) *distribution.Distribution_Exemplar {
ctx := context.TODO()
attachments := []*anypb.Any{}
// TODO: Look into still sending exemplars with no span.
if traceID, spanID := ex.TraceID(), ex.SpanID(); !traceID.IsEmpty() && !spanID.IsEmpty() {
sctx, err := anypb.New(&monitoringpb.SpanContext{
// TODO - make sure project id is correct.
SpanName: fmt.Sprintf("projects/%s/traces/%s/spans/%s", projectID, hex.EncodeToString(traceID[:]), hex.EncodeToString(spanID[:])),
})
if err == nil {
attachments = append(attachments, sctx)
} else {
// This happens in the event of logic error (e.g. missing required fields).
// As such we complaining loudly to fail our unit tests.
m.exemplarAttachmentDropCount.Add(ctx, 1)
}
}
if ex.FilteredAttributes().Len() > 0 {
attr, err := anypb.New(&monitoringpb.DroppedLabels{
Label: attributesToLabels(ex.FilteredAttributes()),
})
if err == nil {
attachments = append(attachments, attr)
} else {
// This happens in the event of logic error (e.g. missing required fields).
// As such we complaining loudly to fail our unit tests.
m.exemplarAttachmentDropCount.Add(ctx, 1)
}
}
var val float64
switch ex.ValueType() {
case pmetric.ExemplarValueTypeDouble:
val = ex.DoubleValue()
case pmetric.ExemplarValueTypeInt:
val = float64(ex.IntValue())
}
return &distribution.Distribution_Exemplar{
Value: val,
Timestamp: timestamppb.New(ex.Timestamp().AsTime()),
Attachments: attachments,
}
}