From 2e9464f07ffbff25737fa0df413b4ee35eb45bf5 Mon Sep 17 00:00:00 2001 From: Francesco Casula Date: Wed, 25 Sep 2024 09:54:51 +0200 Subject: [PATCH 1/2] chore: gauges optimization --- stats/otel.go | 68 +++++++++++++++++++++++++-------------- stats/otel_measurement.go | 3 +- 2 files changed, 45 insertions(+), 26 deletions(-) diff --git a/stats/otel.go b/stats/otel.go index 6a762f3e..9f192645 100644 --- a/stats/otel.go +++ b/stats/otel.go @@ -40,16 +40,18 @@ type otelStats struct { tracerMap map[string]Tracer tracerMapMu sync.Mutex - meter metric.Meter - noopMeter metric.Meter - counters map[string]metric.Int64Counter - countersMu sync.Mutex - gauges map[string]*otelGauge - gaugesMu sync.Mutex - timers map[string]metric.Float64Histogram - timersMu sync.Mutex - histograms map[string]metric.Float64Histogram - histogramsMu sync.Mutex + meter metric.Meter + noopMeter metric.Meter + counters map[string]metric.Int64Counter + countersMu sync.Mutex + gauges map[string]*otelGauge + gaugesOtel map[string]metric.Float64ObservableGauge + gaugesMu sync.RWMutex + gaugesRegisterOnce sync.Once + timers map[string]metric.Float64Histogram + timersMu sync.Mutex + histograms map[string]metric.Float64Histogram + histogramsMu sync.Mutex otelManager otel.Manager collectorAggregator *aggregatedCollector @@ -385,29 +387,45 @@ func (s *otelStats) getGauge( } if !ok { + g, exists := s.gaugesOtel[name] + if !exists { + var err error + g, err = s.meter.Float64ObservableGauge(name) + if err != nil { + s.logger.Warnf("failed to create observable gauge %s: %v", name, err) + g, _ = s.noopMeter.Float64ObservableGauge(name) + } + } + og = &otelGauge{otelMeasurement: &otelMeasurement{ genericMeasurement: genericMeasurement{statType: GaugeType}, attributes: attributes, - }} + }, observableGauge: g} - g, err := s.meter.Float64ObservableGauge(name) - if err != nil { - s.logger.Warnf("failed to create gauge %s: %v", name, err) - g, _ = s.noopMeter.Float64ObservableGauge(name) - } else { - _, err = s.meter.RegisterCallback(func(ctx context.Context, o metric.Observer) error { + s.gauges[mapKey] = og + s.gaugesOtel[name] = g + } + + s.gaugesRegisterOnce.Do(func() { + _, err := s.meter.RegisterCallback(func(ctx context.Context, o metric.Observer) error { + s.gaugesMu.RLock() + defer s.gaugesMu.RUnlock() + + for _, og := range s.gauges { + if og.disabled { + continue + } if value := og.getValue(); value != nil { - o.ObserveFloat64(g, cast.ToFloat64(value), metric.WithAttributes(attributes...)) + o.ObserveFloat64(og.observableGauge, cast.ToFloat64(value), metric.WithAttributes(og.attributes...)) } - return nil - }, g) - if err != nil { - panic(fmt.Errorf("failed to register callback for gauge %s: %w", name, err)) } - } - s.gauges[mapKey] = og - } + return nil + }) + if err != nil { + panic(fmt.Errorf("failed to register callback for gauge %s: %w", name, err)) + } + }) return og } diff --git a/stats/otel_measurement.go b/stats/otel_measurement.go index b941db53..05909a3e 100644 --- a/stats/otel_measurement.go +++ b/stats/otel_measurement.go @@ -38,7 +38,8 @@ func (c *otelCounter) Increment() { // otelGauge represents a gauge stat type otelGauge struct { *otelMeasurement - value atomic.Value + value atomic.Value + observableGauge metric.Float64ObservableGauge } // Gauge records an absolute value for this stat. Only applies to GaugeType stats From 2d51ad1d2f4363c6f3a6c642c1379a3365d24fef Mon Sep 17 00:00:00 2001 From: Francesco Casula Date: Wed, 25 Sep 2024 09:59:21 +0200 Subject: [PATCH 2/2] fix: nil map --- stats/otel.go | 1 + 1 file changed, 1 insertion(+) diff --git a/stats/otel.go b/stats/otel.go index 9f192645..6661943b 100644 --- a/stats/otel.go +++ b/stats/otel.go @@ -382,6 +382,7 @@ func (s *otelStats) getGauge( if s.gauges == nil { s.gauges = make(map[string]*otelGauge) + s.gaugesOtel = make(map[string]metric.Float64ObservableGauge) } else { og, ok = s.gauges[mapKey] }