in collector/export/metric_otlp.go [179:263]
func (c *PromToOtlpExporter) promToOtlpRequest(wr *prompb.WriteRequest) ([]byte, int64, error) {
scopeMetrics := &metricsv1.ScopeMetrics{
// TODO - assume we filter most or keep most?
Metrics: make([]*metricsv1.Metric, 0, len(wr.Timeseries)),
}
exportRequest := &v1.ExportMetricsServiceRequest{
ResourceMetrics: []*metricsv1.ResourceMetrics{
{
Resource: &resourcev1.Resource{
Attributes: c.resourceAttributes,
},
ScopeMetrics: []*metricsv1.ScopeMetrics{
scopeMetrics,
},
},
},
}
count := int64(0)
for _, ts := range wr.Timeseries {
nameBytes := prompb.MetricName(ts)
if c.transformer.ShouldDropMetric(ts, nameBytes) {
continue
}
count++
gauge := &metricsv1.Gauge{
DataPoints: make([]*metricsv1.NumberDataPoint, 0, len(ts.Samples)),
}
metric := &metricsv1.Metric{
Data: &metricsv1.Metric_Gauge{
Gauge: gauge,
},
}
attributes := make([]*commonv1.KeyValue, 0, len(ts.Labels))
c.transformer.WalkLabels(ts, func(k, v []byte) {
// skip adding the name label and any adxmon_ prefixed labels
if bytes.Equal(k, nameLabel) || bytes.HasPrefix(k, []byte("adxmon_")) {
return
}
attribute := c.stringKVPool.Get(0).(*commonv1.KeyValue)
// Explicitly set all fields to reset, but also to avoid allocations for the value
attribute.Key = string(k)
// only accept stringval here to avoid allocations
stringval := attribute.Value.Value.(*commonv1.AnyValue_StringValue)
stringval.StringValue = string(v)
attributes = append(attributes, attribute)
})
metric.Name = string(nameBytes)
for _, sample := range ts.Samples {
datapoint := c.datapointPool.Get(0).(*metricsv1.NumberDataPoint)
// Explicitly set all fields to reset, but also to avoid allocations for the value
datapoint.Attributes = attributes
datapoint.TimeUnixNano = uint64(sample.Timestamp * 1000000) // milliseconds to nanoseconds
datapoint.StartTimeUnixNano = 0
datapoint.Exemplars = nil
datapoint.Flags = 0
// only accept doubleval here to avoid allocations
doubleVal := datapoint.Value.(*metricsv1.NumberDataPoint_AsDouble)
doubleVal.AsDouble = sample.Value
gauge.DataPoints = append(gauge.DataPoints, datapoint)
}
scopeMetrics.Metrics = append(scopeMetrics.Metrics, metric)
}
serialized, err := proto.Marshal(exportRequest)
for _, scopeMetric := range scopeMetrics.Metrics {
for idx, datapoint := range scopeMetric.GetGauge().GetDataPoints() {
if idx == 0 {
// shared attribute with all datapoints under metric
for _, attribute := range datapoint.Attributes {
c.stringKVPool.Put(attribute)
}
}
c.datapointPool.Put(datapoint)
}
}
return serialized, count, err
}