@@ -16,6 +16,7 @@ package prometheus // import "go.opentelemetry.io/otel/exporters/prometheus"
16
16
17
17
import (
18
18
"context"
19
+ "errors"
19
20
"fmt"
20
21
"sort"
21
22
"strings"
@@ -24,9 +25,12 @@ import (
24
25
"unicode/utf8"
25
26
26
27
"github.com/prometheus/client_golang/prometheus"
28
+ dto "github.com/prometheus/client_model/go"
29
+ "google.golang.org/protobuf/proto"
27
30
28
31
"go.opentelemetry.io/otel"
29
32
"go.opentelemetry.io/otel/attribute"
33
+ "go.opentelemetry.io/otel/internal/global"
30
34
"go.opentelemetry.io/otel/metric/unit"
31
35
"go.opentelemetry.io/otel/sdk/instrumentation"
32
36
"go.opentelemetry.io/otel/sdk/metric"
@@ -62,6 +66,7 @@ type collector struct {
62
66
disableScopeInfo bool
63
67
createTargetInfoOnce sync.Once
64
68
scopeInfos map [instrumentation.Scope ]prometheus.Metric
69
+ metricFamilies map [string ]* dto.MetricFamily
65
70
}
66
71
67
72
// prometheus counters MUST have a _total suffix:
@@ -83,6 +88,7 @@ func New(opts ...Option) (*Exporter, error) {
83
88
withoutUnits : cfg .withoutUnits ,
84
89
disableScopeInfo : cfg .disableScopeInfo ,
85
90
scopeInfos : make (map [instrumentation.Scope ]prometheus.Metric ),
91
+ metricFamilies : make (map [string ]* dto.MetricFamily ),
86
92
}
87
93
88
94
if err := cfg .registerer .Register (collector ); err != nil {
@@ -149,22 +155,30 @@ func (c *collector) Collect(ch chan<- prometheus.Metric) {
149
155
for _ , m := range scopeMetrics .Metrics {
150
156
switch v := m .Data .(type ) {
151
157
case metricdata.Histogram :
152
- addHistogramMetric (ch , v , m , keys , values , c .getName (m ))
158
+ addHistogramMetric (ch , v , m , keys , values , c .getName (m ), c . metricFamilies )
153
159
case metricdata.Sum [int64 ]:
154
- addSumMetric (ch , v , m , keys , values , c .getName (m ))
160
+ addSumMetric (ch , v , m , keys , values , c .getName (m ), c . metricFamilies )
155
161
case metricdata.Sum [float64 ]:
156
- addSumMetric (ch , v , m , keys , values , c .getName (m ))
162
+ addSumMetric (ch , v , m , keys , values , c .getName (m ), c . metricFamilies )
157
163
case metricdata.Gauge [int64 ]:
158
- addGaugeMetric (ch , v , m , keys , values , c .getName (m ))
164
+ addGaugeMetric (ch , v , m , keys , values , c .getName (m ), c . metricFamilies )
159
165
case metricdata.Gauge [float64 ]:
160
- addGaugeMetric (ch , v , m , keys , values , c .getName (m ))
166
+ addGaugeMetric (ch , v , m , keys , values , c .getName (m ), c . metricFamilies )
161
167
}
162
168
}
163
169
}
164
170
}
165
171
166
- func addHistogramMetric (ch chan <- prometheus.Metric , histogram metricdata.Histogram , m metricdata.Metrics , ks , vs [2 ]string , name string ) {
172
+ func addHistogramMetric (ch chan <- prometheus.Metric , histogram metricdata.Histogram , m metricdata.Metrics , ks , vs [2 ]string , name string , mfs map [ string ] * dto. MetricFamily ) {
167
173
// TODO(https://github.com/open-telemetry/opentelemetry-go/issues/3163): support exemplars
174
+ drop , help := validateMetrics (name , m .Description , dto .MetricType_HISTOGRAM .Enum (), mfs )
175
+ if drop {
176
+ return
177
+ }
178
+ if help != "" {
179
+ m .Description = help
180
+ }
181
+
168
182
for _ , dp := range histogram .DataPoints {
169
183
keys , values := getAttrs (dp .Attributes , ks , vs )
170
184
@@ -185,15 +199,26 @@ func addHistogramMetric(ch chan<- prometheus.Metric, histogram metricdata.Histog
185
199
}
186
200
}
187
201
188
- func addSumMetric [N int64 | float64 ](ch chan <- prometheus.Metric , sum metricdata.Sum [N ], m metricdata.Metrics , ks , vs [2 ]string , name string ) {
202
+ func addSumMetric [N int64 | float64 ](ch chan <- prometheus.Metric , sum metricdata.Sum [N ], m metricdata.Metrics , ks , vs [2 ]string , name string , mfs map [ string ] * dto. MetricFamily ) {
189
203
valueType := prometheus .CounterValue
204
+ metricType := dto .MetricType_COUNTER
190
205
if ! sum .IsMonotonic {
191
206
valueType = prometheus .GaugeValue
207
+ metricType = dto .MetricType_GAUGE
192
208
}
193
209
if sum .IsMonotonic {
194
210
// Add _total suffix for counters
195
211
name += counterSuffix
196
212
}
213
+
214
+ drop , help := validateMetrics (name , m .Description , metricType .Enum (), mfs )
215
+ if drop {
216
+ return
217
+ }
218
+ if help != "" {
219
+ m .Description = help
220
+ }
221
+
197
222
for _ , dp := range sum .DataPoints {
198
223
keys , values := getAttrs (dp .Attributes , ks , vs )
199
224
@@ -207,7 +232,15 @@ func addSumMetric[N int64 | float64](ch chan<- prometheus.Metric, sum metricdata
207
232
}
208
233
}
209
234
210
- func addGaugeMetric [N int64 | float64 ](ch chan <- prometheus.Metric , gauge metricdata.Gauge [N ], m metricdata.Metrics , ks , vs [2 ]string , name string ) {
235
+ func addGaugeMetric [N int64 | float64 ](ch chan <- prometheus.Metric , gauge metricdata.Gauge [N ], m metricdata.Metrics , ks , vs [2 ]string , name string , mfs map [string ]* dto.MetricFamily ) {
236
+ drop , help := validateMetrics (name , m .Description , dto .MetricType_GAUGE .Enum (), mfs )
237
+ if drop {
238
+ return
239
+ }
240
+ if help != "" {
241
+ m .Description = help
242
+ }
243
+
211
244
for _ , dp := range gauge .DataPoints {
212
245
keys , values := getAttrs (dp .Attributes , ks , vs )
213
246
@@ -344,3 +377,36 @@ func sanitizeName(n string) string {
344
377
345
378
return b .String ()
346
379
}
380
+
381
+ func validateMetrics (name , description string , metricType * dto.MetricType , mfs map [string ]* dto.MetricFamily ) (drop bool , help string ) {
382
+ emf , exist := mfs [name ]
383
+ if ! exist {
384
+ mfs [name ] = & dto.MetricFamily {
385
+ Name : proto .String (name ),
386
+ Help : proto .String (description ),
387
+ Type : metricType ,
388
+ }
389
+ return false , ""
390
+ }
391
+ if emf .GetType () != * metricType {
392
+ global .Error (
393
+ errors .New ("instrument type conflict" ),
394
+ "Using existing type definition." ,
395
+ "instrument" , name ,
396
+ "existing" , emf .GetType (),
397
+ "dropped" , * metricType ,
398
+ )
399
+ return true , ""
400
+ }
401
+ if emf .GetHelp () != description {
402
+ global .Info (
403
+ "Instrument description conflict, using existing" ,
404
+ "instrument" , name ,
405
+ "existing" , emf .GetHelp (),
406
+ "dropped" , description ,
407
+ )
408
+ return false , emf .GetHelp ()
409
+ }
410
+
411
+ return false , ""
412
+ }
0 commit comments