From 0472b0d59732be7f93b5e79875c0a61fcd4a35e6 Mon Sep 17 00:00:00 2001 From: Igor Morozov Date: Mon, 17 Jun 2024 20:27:26 +0300 Subject: [PATCH] feat(otel): add NewMetricsHook, use api interface instead of SDK type (#530) Signed-off-by: Igor Morozov --- hooks/open-telemetry/README.md | 35 +++++++++++++++++++++-------- hooks/open-telemetry/go.sum | 22 ++---------------- hooks/open-telemetry/pkg/metrics.go | 11 +++++++-- 3 files changed, 37 insertions(+), 31 deletions(-) diff --git a/hooks/open-telemetry/README.md b/hooks/open-telemetry/README.md index cc39c45d0..248f2a6be 100644 --- a/hooks/open-telemetry/README.md +++ b/hooks/open-telemetry/README.md @@ -15,14 +15,31 @@ This hook performs metric collection by tapping into various hook stages. Given - `feature_flag.evaluation_error_total` - `feature_flag.evaluation_active_count` -Consider example below for usage, +There are two ways to create hooks: + +### Using Global MeterProvider + +Global provider should be set somewhere using `otel.SetMeterProvider` before calling this constructor. + +```go +// Derive metric hook from reader +metricsHook, err := hooks.NewMetricsHook() +if err != nil { + return err +} + +// Register OpenFeature API level hooks +openfeature.AddHooks(metricsHook) +``` + +### Passing MeterProvider to Constructor ```go // provider must be configured and provided to constructor based on application configurations var provider *metric.MeterProvider - + // Derive metric hook from reader -metricsHook, _ := hooks.NewMetricsHookForProvider(provider) +metricsHook, err := hooks.NewMetricsHookForProvider(provider) if err != nil { return err } @@ -44,15 +61,15 @@ NewMetricsHookForProvider(provider, WithMetricsAttributeSetter( func(metadata openfeature.FlagMetadata) []attribute.KeyValue { // custom attribute extraction logic - + return attributes })) ``` -#### WithFlagMetadataDimensions +#### WithFlagMetadataDimensions -This constructor option allows to configure dimension descriptions to be extracted from `openfeature.FlagMetadata`. -If present, these dimension will be added to the `feature_flag.evaluation_success_total` metric. +This constructor option allows to configure dimension descriptions to be extracted from `openfeature.FlagMetadata`. +If present, these dimension will be added to the `feature_flag.evaluation_success_total` metric. Missing metadata keys will be ignored by the implementation. ```go @@ -100,7 +117,7 @@ These attributes are added at the `After` stage of the hook. NewTracesHook(WithMetricsAttributeSetter( func(metadata openfeature.FlagMetadata) []attribute.KeyValue { // custom attribute extraction logic - + return attributes })) -``` \ No newline at end of file +``` diff --git a/hooks/open-telemetry/go.sum b/hooks/open-telemetry/go.sum index 30067f01c..a06c0b90c 100644 --- a/hooks/open-telemetry/go.sum +++ b/hooks/open-telemetry/go.sum @@ -9,42 +9,24 @@ github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/open-feature/go-sdk v1.9.0 h1:1Nyj+XNHfL0rRGZgGCbZ29CHDD57PQJL7Q/2ZbW/E8c= -github.com/open-feature/go-sdk v1.9.0/go.mod h1:n5BM4DfvIiKaWWquZnL/yVihcGM5aLsz7rNYE3BkXAM= -github.com/open-feature/go-sdk v1.10.0 h1:druQtYOrN+gyz3rMsXp0F2jW1oBXJb0V26PVQnUGLbM= -github.com/open-feature/go-sdk v1.10.0/go.mod h1:+rkJhLBtYsJ5PZNddAgFILhRAAxwrJ32aU7UEUm4zQI= github.com/open-feature/go-sdk v1.11.0 h1:4cp9rXl16ZvlMCef7O+I3vQSXae8DzAF0SfV9mvYInw= github.com/open-feature/go-sdk v1.11.0/go.mod h1:+rkJhLBtYsJ5PZNddAgFILhRAAxwrJ32aU7UEUm4zQI= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= -github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -go.opentelemetry.io/otel v1.22.0 h1:xS7Ku+7yTFvDfDraDIJVpw7XPyuHlB9MCiqqX5mcJ6Y= -go.opentelemetry.io/otel v1.22.0/go.mod h1:eoV4iAi3Ea8LkAEI9+GFT44O6T/D0GWAVFyZVCC6pMI= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= go.opentelemetry.io/otel v1.25.0 h1:gldB5FfhRl7OJQbUHt/8s0a7cE8fbsPAtdpRaApKy4k= go.opentelemetry.io/otel v1.25.0/go.mod h1:Wa2ds5NOXEMkCmUou1WA7ZBfLTHWIsp034OVD7AO+Vg= -go.opentelemetry.io/otel/metric v1.22.0 h1:lypMQnGyJYeuYPhOM/bgjbFM6WE44W1/T45er4d8Hhg= -go.opentelemetry.io/otel/metric v1.22.0/go.mod h1:evJGjVpZv0mQ5QBRJoBF64yMuOf4xCWdXjK8pzFvliY= go.opentelemetry.io/otel/metric v1.25.0 h1:LUKbS7ArpFL/I2jJHdJcqMGxkRdxpPHE0VU/D4NuEwA= go.opentelemetry.io/otel/metric v1.25.0/go.mod h1:rkDLUSd2lC5lq2dFNrX9LGAbINP5B7WBkC78RXCpH5s= -go.opentelemetry.io/otel/sdk v1.22.0 h1:6coWHw9xw7EfClIC/+O31R8IY3/+EiRFHevmHafB2Gw= -go.opentelemetry.io/otel/sdk v1.22.0/go.mod h1:iu7luyVGYovrRpe2fmj3CVKouQNdTOkxtLzPvPz1DOc= go.opentelemetry.io/otel/sdk v1.25.0 h1:PDryEJPC8YJZQSyLY5eqLeafHtG+X7FWnf3aXMtxbqo= go.opentelemetry.io/otel/sdk v1.25.0/go.mod h1:oFgzCM2zdsxKzz6zwpTZYLLQsFwc+K0daArPdIhuxkw= -go.opentelemetry.io/otel/sdk/metric v1.22.0 h1:ARrRetm1HCVxq0cbnaZQlfwODYJHo3gFL8Z3tSmHBcI= -go.opentelemetry.io/otel/sdk/metric v1.22.0/go.mod h1:KjQGeMIDlBNEOo6HvjhxIec1p/69/kULDcp4gr0oLQQ= go.opentelemetry.io/otel/sdk/metric v1.25.0 h1:7CiHOy08LbrxMAp4vWpbiPcklunUshVpAvGBrdDRlGw= go.opentelemetry.io/otel/sdk/metric v1.25.0/go.mod h1:LzwoKptdbBBdYfvtGCzGwk6GWMA3aUzBOwtQpR6Nz7o= -go.opentelemetry.io/otel/trace v1.22.0 h1:Hg6pPujv0XG9QaVbGOBVHunyuLcCC3jN7WEhPx83XD0= -go.opentelemetry.io/otel/trace v1.22.0/go.mod h1:RbbHXVqKES9QhzZq/fE5UnOSILqRt40a21sPw2He1xo= go.opentelemetry.io/otel/trace v1.25.0 h1:tqukZGLwQYRIFtSQM2u2+yfMVTgGVeqRLPUYx1Dq6RM= go.opentelemetry.io/otel/trace v1.25.0/go.mod h1:hCCs70XM/ljO+BeQkyFnbK28SBIJ/Emuha+ccrCRT7I= -golang.org/x/exp v0.0.0-20230811145659-89c5cff77bcb h1:mIKbk8weKhSeLH2GmUTrvx8CjkyJmnU1wFmg59CUjFA= -golang.org/x/exp v0.0.0-20230811145659-89c5cff77bcb/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc= golang.org/x/exp v0.0.0-20240205201215-2c58cdc269a3 h1:/RIbNt/Zr7rVhIkQhooTxCxFcdWLGIKnZA4IXNFSrvo= golang.org/x/exp v0.0.0-20240205201215-2c58cdc269a3/go.mod h1:idGWGoKP1toJGkd5/ig9ZLuPcZBC3ewk7SzmH0uou08= -golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= -golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= diff --git a/hooks/open-telemetry/pkg/metrics.go b/hooks/open-telemetry/pkg/metrics.go index 8b2d8666f..83bf8db13 100644 --- a/hooks/open-telemetry/pkg/metrics.go +++ b/hooks/open-telemetry/pkg/metrics.go @@ -2,10 +2,11 @@ package otel import ( "context" + "github.com/open-feature/go-sdk/openfeature" + "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/attribute" api "go.opentelemetry.io/otel/metric" - "go.opentelemetry.io/otel/sdk/metric" semconv "go.opentelemetry.io/otel/semconv/v1.18.0" ) @@ -30,8 +31,14 @@ type MetricsHook struct { var _ openfeature.Hook = &MetricsHook{} +// NewMetricsHook builds a metric hook backed by a globally set metric.MeterProvider. +// Use otel.SetMeterProvider to set the global provider or use NewMetricsHookForProvider. +func NewMetricsHook(opts ...MetricOptions) (*MetricsHook, error) { + return NewMetricsHookForProvider(otel.GetMeterProvider(), opts...) +} + // NewMetricsHookForProvider builds a metric hook backed by metric.MeterProvider. -func NewMetricsHookForProvider(provider *metric.MeterProvider, opts ...MetricOptions) (*MetricsHook, error) { +func NewMetricsHookForProvider(provider api.MeterProvider, opts ...MetricOptions) (*MetricsHook, error) { meter := provider.Meter(meterName) activeCounter, err := meter.Int64UpDownCounter(evaluationActive, api.WithDescription("active flag evaluations counter"))