diff --git a/extra/redisotel/metrics.go b/extra/redisotel/metrics.go index 915838f34..ab4cea690 100644 --- a/extra/redisotel/metrics.go +++ b/extra/redisotel/metrics.go @@ -82,10 +82,15 @@ func InstrumentMetrics(rdb redis.UniversalClient, opts ...MetricsOption) error { } } +func poolStatsAttrs(conf *config) (poolAttrs, idleAttrs, usedAttrs attribute.Set) { + poolAttrs = attribute.NewSet(conf.attrs...) + idleAttrs = attribute.NewSet(append(poolAttrs.ToSlice(), attribute.String("state", "idle"))...) + usedAttrs = attribute.NewSet(append(poolAttrs.ToSlice(), attribute.String("state", "used"))...) + return +} + func reportPoolStats(rdb *redis.Client, conf *config) error { - labels := conf.attrs - idleAttrs := append(labels, attribute.String("state", "idle")) - usedAttrs := append(labels, attribute.String("state", "used")) + poolAttrs, idleAttrs, usedAttrs := poolStatsAttrs(conf) idleMax, err := conf.meter.Int64ObservableUpDownCounter( "db.client.connections.idle.max", @@ -132,14 +137,14 @@ func reportPoolStats(rdb *redis.Client, conf *config) error { func(ctx context.Context, o metric.Observer) error { stats := rdb.PoolStats() - o.ObserveInt64(idleMax, int64(redisConf.MaxIdleConns), metric.WithAttributes(labels...)) - o.ObserveInt64(idleMin, int64(redisConf.MinIdleConns), metric.WithAttributes(labels...)) - o.ObserveInt64(connsMax, int64(redisConf.PoolSize), metric.WithAttributes(labels...)) + o.ObserveInt64(idleMax, int64(redisConf.MaxIdleConns), metric.WithAttributeSet(poolAttrs)) + o.ObserveInt64(idleMin, int64(redisConf.MinIdleConns), metric.WithAttributeSet(poolAttrs)) + o.ObserveInt64(connsMax, int64(redisConf.PoolSize), metric.WithAttributeSet(poolAttrs)) - o.ObserveInt64(usage, int64(stats.IdleConns), metric.WithAttributes(idleAttrs...)) - o.ObserveInt64(usage, int64(stats.TotalConns-stats.IdleConns), metric.WithAttributes(usedAttrs...)) + o.ObserveInt64(usage, int64(stats.IdleConns), metric.WithAttributeSet(idleAttrs)) + o.ObserveInt64(usage, int64(stats.TotalConns-stats.IdleConns), metric.WithAttributeSet(usedAttrs)) - o.ObserveInt64(timeouts, int64(stats.Timeouts), metric.WithAttributes(labels...)) + o.ObserveInt64(timeouts, int64(stats.Timeouts), metric.WithAttributeSet(poolAttrs)) return nil }, idleMax, diff --git a/extra/redisotel/metrics_test.go b/extra/redisotel/metrics_test.go new file mode 100644 index 000000000..71a3606c2 --- /dev/null +++ b/extra/redisotel/metrics_test.go @@ -0,0 +1,54 @@ +package redisotel + +import ( + "reflect" + "testing" + + "go.opentelemetry.io/otel/attribute" +) + +func Test_poolStatsAttrs(t *testing.T) { + t.Parallel() + type args struct { + conf *config + } + tests := []struct { + name string + args args + wantPoolAttrs attribute.Set + wantIdleAttrs attribute.Set + wantUsedAttrs attribute.Set + }{ + { + name: "#3122", + args: func() args { + conf := &config{ + attrs: make([]attribute.KeyValue, 0, 4), + } + conf.attrs = append(conf.attrs, attribute.String("foo1", "bar1"), attribute.String("foo2", "bar2")) + conf.attrs = append(conf.attrs, attribute.String("pool.name", "pool1")) + return args{conf: conf} + }(), + wantPoolAttrs: attribute.NewSet(attribute.String("foo1", "bar1"), attribute.String("foo2", "bar2"), + attribute.String("pool.name", "pool1")), + wantIdleAttrs: attribute.NewSet(attribute.String("foo1", "bar1"), attribute.String("foo2", "bar2"), + attribute.String("pool.name", "pool1"), attribute.String("state", "idle")), + wantUsedAttrs: attribute.NewSet(attribute.String("foo1", "bar1"), attribute.String("foo2", "bar2"), + attribute.String("pool.name", "pool1"), attribute.String("state", "used")), + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + gotPoolAttrs, gotIdleAttrs, gotUsedAttrs := poolStatsAttrs(tt.args.conf) + if !reflect.DeepEqual(gotPoolAttrs, tt.wantPoolAttrs) { + t.Errorf("poolStatsAttrs() gotPoolAttrs = %v, want %v", gotPoolAttrs, tt.wantPoolAttrs) + } + if !reflect.DeepEqual(gotIdleAttrs, tt.wantIdleAttrs) { + t.Errorf("poolStatsAttrs() gotIdleAttrs = %v, want %v", gotIdleAttrs, tt.wantIdleAttrs) + } + if !reflect.DeepEqual(gotUsedAttrs, tt.wantUsedAttrs) { + t.Errorf("poolStatsAttrs() gotUsedAttrs = %v, want %v", gotUsedAttrs, tt.wantUsedAttrs) + } + }) + } +}