Skip to content

Commit 1133977

Browse files
authored
refactor prometheus exporter to slightly improve performance (open-telemetry#3351)
1 parent 587437b commit 1133977

File tree

1 file changed

+35
-94
lines changed

1 file changed

+35
-94
lines changed

exporters/prometheus/exporter.go

Lines changed: 35 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ type collector struct {
5252

5353
disableTargetInfo bool
5454
withoutUnits bool
55-
targetInfo *metricData
55+
targetInfo prometheus.Metric
5656
createTargetInfoOnce sync.Once
5757
}
5858

@@ -105,74 +105,39 @@ func (c *collector) Collect(ch chan<- prometheus.Metric) {
105105
}
106106
}
107107

108-
for _, metricData := range c.getMetricData(metrics) {
109-
if metricData.valueType == prometheus.UntypedValue {
110-
m, err := prometheus.NewConstHistogram(metricData.description, metricData.histogramCount, metricData.histogramSum, metricData.histogramBuckets, metricData.attributeValues...)
111-
if err != nil {
112-
otel.Handle(err)
113-
continue
114-
}
115-
ch <- m
116-
} else {
117-
m, err := prometheus.NewConstMetric(metricData.description, metricData.valueType, metricData.value, metricData.attributeValues...)
118-
if err != nil {
119-
otel.Handle(err)
120-
continue
121-
}
122-
ch <- m
123-
}
124-
}
125-
}
126-
127-
// metricData holds the metadata as well as values for individual data points.
128-
type metricData struct {
129-
// name should include the unit as a suffix (before _total on counters)
130-
// see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/data-model.md#metric-metadata-1
131-
name string
132-
description *prometheus.Desc
133-
attributeValues []string
134-
valueType prometheus.ValueType
135-
value float64
136-
histogramCount uint64
137-
histogramSum float64
138-
histogramBuckets map[float64]uint64
139-
}
140-
141-
func (c *collector) getMetricData(metrics metricdata.ResourceMetrics) []*metricData {
142-
allMetrics := make([]*metricData, 0)
143-
144108
c.createTargetInfoOnce.Do(func() {
145109
// Resource should be immutable, we don't need to compute again
146-
c.targetInfo = c.createInfoMetricData(targetInfoMetricName, targetInfoDescription, metrics.Resource)
110+
targetInfo, err := c.createInfoMetric(targetInfoMetricName, targetInfoDescription, metrics.Resource)
111+
if err != nil {
112+
// If the target info metric is invalid, disable sending it.
113+
otel.Handle(err)
114+
c.disableTargetInfo = true
115+
}
116+
c.targetInfo = targetInfo
147117
})
148-
149-
if c.targetInfo != nil {
150-
allMetrics = append(allMetrics, c.targetInfo)
118+
if !c.disableTargetInfo {
119+
ch <- c.targetInfo
151120
}
152-
153121
for _, scopeMetrics := range metrics.ScopeMetrics {
154122
for _, m := range scopeMetrics.Metrics {
155123
switch v := m.Data.(type) {
156124
case metricdata.Histogram:
157-
allMetrics = append(allMetrics, getHistogramMetricData(v, m, c.getName(m))...)
125+
addHistogramMetric(ch, v, m, c.getName(m))
158126
case metricdata.Sum[int64]:
159-
allMetrics = append(allMetrics, getSumMetricData(v, m, c.getName(m))...)
127+
addSumMetric(ch, v, m, c.getName(m))
160128
case metricdata.Sum[float64]:
161-
allMetrics = append(allMetrics, getSumMetricData(v, m, c.getName(m))...)
129+
addSumMetric(ch, v, m, c.getName(m))
162130
case metricdata.Gauge[int64]:
163-
allMetrics = append(allMetrics, getGaugeMetricData(v, m, c.getName(m))...)
131+
addGaugeMetric(ch, v, m, c.getName(m))
164132
case metricdata.Gauge[float64]:
165-
allMetrics = append(allMetrics, getGaugeMetricData(v, m, c.getName(m))...)
133+
addGaugeMetric(ch, v, m, c.getName(m))
166134
}
167135
}
168136
}
169-
170-
return allMetrics
171137
}
172138

173-
func getHistogramMetricData(histogram metricdata.Histogram, m metricdata.Metrics, name string) []*metricData {
139+
func addHistogramMetric(ch chan<- prometheus.Metric, histogram metricdata.Histogram, m metricdata.Metrics, name string) {
174140
// TODO(https://github.com/open-telemetry/opentelemetry-go/issues/3163): support exemplars
175-
dataPoints := make([]*metricData, 0, len(histogram.DataPoints))
176141
for _, dp := range histogram.DataPoints {
177142
keys, values := getAttrs(dp.Attributes)
178143
desc := prometheus.NewDesc(name, m.Description, keys, nil)
@@ -183,60 +148,47 @@ func getHistogramMetricData(histogram metricdata.Histogram, m metricdata.Metrics
183148
cumulativeCount += dp.BucketCounts[i]
184149
buckets[bound] = cumulativeCount
185150
}
186-
md := &metricData{
187-
name: m.Name,
188-
description: desc,
189-
attributeValues: values,
190-
valueType: prometheus.UntypedValue,
191-
histogramCount: dp.Count,
192-
histogramSum: dp.Sum,
193-
histogramBuckets: buckets,
151+
m, err := prometheus.NewConstHistogram(desc, dp.Count, dp.Sum, buckets, values...)
152+
if err != nil {
153+
otel.Handle(err)
154+
continue
194155
}
195-
dataPoints = append(dataPoints, md)
156+
ch <- m
196157
}
197-
return dataPoints
198158
}
199159

200-
func getSumMetricData[N int64 | float64](sum metricdata.Sum[N], m metricdata.Metrics, name string) []*metricData {
160+
func addSumMetric[N int64 | float64](ch chan<- prometheus.Metric, sum metricdata.Sum[N], m metricdata.Metrics, name string) {
201161
valueType := prometheus.CounterValue
202162
if !sum.IsMonotonic {
203163
valueType = prometheus.GaugeValue
204164
}
205-
dataPoints := make([]*metricData, 0, len(sum.DataPoints))
206165
for _, dp := range sum.DataPoints {
207166
if sum.IsMonotonic {
208167
// Add _total suffix for counters
209168
name += counterSuffix
210169
}
211170
keys, values := getAttrs(dp.Attributes)
212171
desc := prometheus.NewDesc(name, m.Description, keys, nil)
213-
md := &metricData{
214-
name: m.Name,
215-
description: desc,
216-
attributeValues: values,
217-
valueType: valueType,
218-
value: float64(dp.Value),
172+
m, err := prometheus.NewConstMetric(desc, valueType, float64(dp.Value), values...)
173+
if err != nil {
174+
otel.Handle(err)
175+
continue
219176
}
220-
dataPoints = append(dataPoints, md)
177+
ch <- m
221178
}
222-
return dataPoints
223179
}
224180

225-
func getGaugeMetricData[N int64 | float64](gauge metricdata.Gauge[N], m metricdata.Metrics, name string) []*metricData {
226-
dataPoints := make([]*metricData, 0, len(gauge.DataPoints))
181+
func addGaugeMetric[N int64 | float64](ch chan<- prometheus.Metric, gauge metricdata.Gauge[N], m metricdata.Metrics, name string) {
227182
for _, dp := range gauge.DataPoints {
228183
keys, values := getAttrs(dp.Attributes)
229184
desc := prometheus.NewDesc(name, m.Description, keys, nil)
230-
md := &metricData{
231-
name: m.Name,
232-
description: desc,
233-
attributeValues: values,
234-
valueType: prometheus.GaugeValue,
235-
value: float64(dp.Value),
185+
m, err := prometheus.NewConstMetric(desc, prometheus.GaugeValue, float64(dp.Value), values...)
186+
if err != nil {
187+
otel.Handle(err)
188+
continue
236189
}
237-
dataPoints = append(dataPoints, md)
190+
ch <- m
238191
}
239-
return dataPoints
240192
}
241193

242194
// getAttrs parses the attribute.Set to two lists of matching Prometheus-style
@@ -268,21 +220,10 @@ func getAttrs(attrs attribute.Set) ([]string, []string) {
268220
return keys, values
269221
}
270222

271-
func (c *collector) createInfoMetricData(name, description string, res *resource.Resource) *metricData {
272-
if c.disableTargetInfo {
273-
return nil
274-
}
275-
223+
func (c *collector) createInfoMetric(name, description string, res *resource.Resource) (prometheus.Metric, error) {
276224
keys, values := getAttrs(*res.Set())
277-
278225
desc := prometheus.NewDesc(name, description, keys, nil)
279-
return &metricData{
280-
name: name,
281-
description: desc,
282-
attributeValues: values,
283-
valueType: prometheus.GaugeValue,
284-
value: float64(1),
285-
}
226+
return prometheus.NewConstMetric(desc, prometheus.GaugeValue, float64(1), values...)
286227
}
287228

288229
func sanitizeRune(r rune) rune {

0 commit comments

Comments
 (0)