diff --git a/example/prometheus/go.mod b/example/prometheus/go.mod index 9f570847704..8d1647c6e60 100644 --- a/example/prometheus/go.mod +++ b/example/prometheus/go.mod @@ -20,6 +20,7 @@ require ( github.com/prometheus/client_model v0.3.0 // indirect github.com/prometheus/common v0.37.0 // indirect github.com/prometheus/procfs v0.8.0 // indirect + github.com/puzpuzpuz/xsync v1.5.2 // indirect go.opentelemetry.io/otel/sdk v1.15.0-rc.1 // indirect go.opentelemetry.io/otel/trace v1.15.0-rc.1 // indirect golang.org/x/sys v0.6.0 // indirect diff --git a/example/prometheus/go.sum b/example/prometheus/go.sum index 291846e4d7d..7f7f9167900 100644 --- a/example/prometheus/go.sum +++ b/example/prometheus/go.sum @@ -188,6 +188,8 @@ github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1 github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/procfs v0.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5mo= github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4= +github.com/puzpuzpuz/xsync v1.5.2 h1:yRAP4wqSOZG+/4pxJ08fPTwrfL0IzE/LKQ/cw509qGY= +github.com/puzpuzpuz/xsync v1.5.2/go.mod h1:K98BYhX3k1dQ2M63t1YNVDanbwUPmBCAhNmVrrxfiGg= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= diff --git a/example/view/go.mod b/example/view/go.mod index 4dd01b52e9b..97e4c6b5f62 100644 --- a/example/view/go.mod +++ b/example/view/go.mod @@ -21,6 +21,7 @@ require ( github.com/prometheus/client_model v0.3.0 // indirect github.com/prometheus/common v0.37.0 // indirect github.com/prometheus/procfs v0.8.0 // indirect + github.com/puzpuzpuz/xsync v1.5.2 // indirect go.opentelemetry.io/otel/trace v1.15.0-rc.1 // indirect golang.org/x/sys v0.6.0 // indirect google.golang.org/protobuf v1.29.1 // indirect diff --git a/example/view/go.sum b/example/view/go.sum index 291846e4d7d..7f7f9167900 100644 --- a/example/view/go.sum +++ b/example/view/go.sum @@ -188,6 +188,8 @@ github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1 github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/procfs v0.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5mo= github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4= +github.com/puzpuzpuz/xsync v1.5.2 h1:yRAP4wqSOZG+/4pxJ08fPTwrfL0IzE/LKQ/cw509qGY= +github.com/puzpuzpuz/xsync v1.5.2/go.mod h1:K98BYhX3k1dQ2M63t1YNVDanbwUPmBCAhNmVrrxfiGg= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= diff --git a/exporters/prometheus/exporter.go b/exporters/prometheus/exporter.go index 21b5c41de62..2dbcdd33343 100644 --- a/exporters/prometheus/exporter.go +++ b/exporters/prometheus/exporter.go @@ -26,6 +26,7 @@ import ( "github.com/prometheus/client_golang/prometheus" dto "github.com/prometheus/client_model/go" + "github.com/puzpuzpuz/xsync" "google.golang.org/protobuf/proto" "go.opentelemetry.io/otel" @@ -65,9 +66,11 @@ type collector struct { disableScopeInfo bool createTargetInfoOnce sync.Once scopeInfos map[instrumentation.Scope]prometheus.Metric - metricFamilies map[string]*dto.MetricFamily + metricFamilies mfMap } +type mfMap = *xsync.MapOf[string, *dto.MetricFamily] + // prometheus counters MUST have a _total suffix: // https://github.com/open-telemetry/opentelemetry-specification/blob/v1.14.0/specification/metrics/data-model.md#sums-1 const counterSuffix = "_total" @@ -87,7 +90,7 @@ func New(opts ...Option) (*Exporter, error) { withoutUnits: cfg.withoutUnits, disableScopeInfo: cfg.disableScopeInfo, scopeInfos: make(map[instrumentation.Scope]prometheus.Metric), - metricFamilies: make(map[string]*dto.MetricFamily), + metricFamilies: xsync.NewMapOf[*dto.MetricFamily](), } if err := cfg.registerer.Register(collector); err != nil { @@ -172,7 +175,7 @@ func (c *collector) Collect(ch chan<- prometheus.Metric) { } } -func addHistogramMetric[N int64 | float64](ch chan<- prometheus.Metric, histogram metricdata.Histogram[N], m metricdata.Metrics, ks, vs [2]string, name string, mfs map[string]*dto.MetricFamily) { +func addHistogramMetric[N int64 | float64](ch chan<- prometheus.Metric, histogram metricdata.Histogram[N], m metricdata.Metrics, ks, vs [2]string, name string, mfs mfMap) { // TODO(https://github.com/open-telemetry/opentelemetry-go/issues/3163): support exemplars drop, help := validateMetrics(name, m.Description, dto.MetricType_HISTOGRAM.Enum(), mfs) if drop { @@ -202,7 +205,7 @@ func addHistogramMetric[N int64 | float64](ch chan<- prometheus.Metric, histogra } } -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) { +func addSumMetric[N int64 | float64](ch chan<- prometheus.Metric, sum metricdata.Sum[N], m metricdata.Metrics, ks, vs [2]string, name string, mfs mfMap) { valueType := prometheus.CounterValue metricType := dto.MetricType_COUNTER if !sum.IsMonotonic { @@ -235,7 +238,7 @@ func addSumMetric[N int64 | float64](ch chan<- prometheus.Metric, sum metricdata } } -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) { +func addGaugeMetric[N int64 | float64](ch chan<- prometheus.Metric, gauge metricdata.Gauge[N], m metricdata.Metrics, ks, vs [2]string, name string, mfs mfMap) { drop, help := validateMetrics(name, m.Description, dto.MetricType_GAUGE.Enum(), mfs) if drop { return @@ -381,14 +384,14 @@ func sanitizeName(n string) string { return b.String() } -func validateMetrics(name, description string, metricType *dto.MetricType, mfs map[string]*dto.MetricFamily) (drop bool, help string) { - emf, exist := mfs[name] - if !exist { - mfs[name] = &dto.MetricFamily{ - Name: proto.String(name), - Help: proto.String(description), - Type: metricType, - } +func validateMetrics(name, description string, metricType *dto.MetricType, mfs mfMap) (drop bool, help string) { + emf, loaded := mfs.LoadOrStore(name, &dto.MetricFamily{ + Name: proto.String(name), + Help: proto.String(description), + Type: metricType, + }) + + if !loaded { return false, "" } if emf.GetType() != *metricType { diff --git a/exporters/prometheus/go.mod b/exporters/prometheus/go.mod index ec6b2ef3351..e01bca27735 100644 --- a/exporters/prometheus/go.mod +++ b/exporters/prometheus/go.mod @@ -5,6 +5,7 @@ go 1.19 require ( github.com/prometheus/client_golang v1.14.0 github.com/prometheus/client_model v0.3.0 + github.com/puzpuzpuz/xsync v1.5.2 github.com/stretchr/testify v1.8.2 go.opentelemetry.io/otel v1.15.0-rc.1 go.opentelemetry.io/otel/metric v1.15.0-rc.1 diff --git a/exporters/prometheus/go.sum b/exporters/prometheus/go.sum index 2ceb6fdd9c7..ae2a58346f2 100644 --- a/exporters/prometheus/go.sum +++ b/exporters/prometheus/go.sum @@ -190,6 +190,8 @@ github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1 github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/procfs v0.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5mo= github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4= +github.com/puzpuzpuz/xsync v1.5.2 h1:yRAP4wqSOZG+/4pxJ08fPTwrfL0IzE/LKQ/cw509qGY= +github.com/puzpuzpuz/xsync v1.5.2/go.mod h1:K98BYhX3k1dQ2M63t1YNVDanbwUPmBCAhNmVrrxfiGg= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=