From 01c6bd49fe2b9f583efb8ba1fe2a6a4871175d2d Mon Sep 17 00:00:00 2001 From: Dave Henderson Date: Wed, 9 Oct 2024 11:34:39 -0400 Subject: [PATCH] feat(tracing): Misc. OTel tracing improvements Signed-off-by: Dave Henderson --- cmd/relayproxy/api/opentelemetry/otel.go | 148 +++++++++++++++++++---- cmd/relayproxy/api/server.go | 6 +- cmd/relayproxy/api/server_test.go | 7 +- cmd/relayproxy/main.go | 8 +- go.mod | 22 +++- go.sum | 36 +++++- 6 files changed, 187 insertions(+), 40 deletions(-) diff --git a/cmd/relayproxy/api/opentelemetry/otel.go b/cmd/relayproxy/api/opentelemetry/otel.go index 6844b00300b..c5ffa497673 100644 --- a/cmd/relayproxy/api/opentelemetry/otel.go +++ b/cmd/relayproxy/api/opentelemetry/otel.go @@ -2,20 +2,24 @@ package opentelemetry import ( "context" - "net/url" + "fmt" + "os" + "strconv" + "time" "github.com/thomaspoignant/go-feature-flag/cmd/relayproxy/config" + "go.opentelemetry.io/contrib/exporters/autoexport" + "go.opentelemetry.io/contrib/samplers/jaegerremote" "go.opentelemetry.io/otel" - "go.opentelemetry.io/otel/attribute" - "go.opentelemetry.io/otel/exporters/otlp/otlptrace" - "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp" "go.opentelemetry.io/otel/sdk/resource" sdktrace "go.opentelemetry.io/otel/sdk/trace" + semconv "go.opentelemetry.io/otel/semconv/v1.26.0" + "go.uber.org/zap" ) type OtelService struct { otelTraceProvider *sdktrace.TracerProvider - otelExporter *otlptrace.Exporter + otelExporter sdktrace.SpanExporter } func NewOtelService() OtelService { @@ -23,47 +27,141 @@ func NewOtelService() OtelService { } // Init the OpenTelemetry service -func (s *OtelService) Init(ctx context.Context, config config.Config) error { - // parsing the OpenTelemetry endpoint - u, err := url.Parse(config.OpenTelemetryOtlpEndpoint) +func (s *OtelService) Init(ctx context.Context, zapLog *zap.Logger, config *config.Config) error { + // OTEL_SDK_DISABLED is not supported by the Go SDK, but is a standard env + // var defined by the OTel spec. We'll use it to disable the trace provider. + if disabled, _ := strconv.ParseBool(os.Getenv("OTEL_SDK_DISABLED")); disabled { + return nil + } + + // support the openTelemetryOtlpEndpoint config element + if config.OpenTelemetryOtlpEndpoint != "" && + os.Getenv("OTEL_EXPORTER_OTLP_ENDPOINT") == "" { + os.Setenv("OTEL_EXPORTER_OTLP_ENDPOINT", config.OpenTelemetryOtlpEndpoint) + } + + exporter, err := autoexport.NewSpanExporter(ctx) if err != nil { - return err + return fmt.Errorf("initializing OTel exporter: %w", err) } - var opts []otlptracehttp.Option - if u.Scheme == "http" { - opts = append(opts, otlptracehttp.WithInsecure()) + serviceName := "go-feature-flag" + if v := os.Getenv("OTEL_SERVICE_NAME"); v != "" { + serviceName = v } - opts = append(opts, otlptracehttp.WithEndpoint(u.Host)) - client := otlptracehttp.NewClient(opts...) - s.otelExporter, err = otlptrace.New(ctx, client) + sampler, err := initSampler(serviceName) + if err != nil { + return fmt.Errorf("initializing OTel sampler: %w", err) + } + + resource, err := resource.New(ctx, + resource.WithFromEnv(), + resource.WithProcessPID(), + resource.WithProcessExecutableName(), + resource.WithProcessExecutablePath(), + resource.WithProcessOwner(), + resource.WithProcessRuntimeName(), + resource.WithProcessRuntimeVersion(), + resource.WithProcessRuntimeDescription(), + resource.WithHost(), + resource.WithTelemetrySDK(), + resource.WithOS(), + resource.WithContainer(), + resource.WithAttributes( + semconv.ServiceNameKey.String(serviceName), + semconv.ServiceVersionKey.String(config.Version), + ), + ) if err != nil { - return err + return fmt.Errorf("initializing OTel resources: %w", err) } + s.otelExporter = exporter s.otelTraceProvider = sdktrace.NewTracerProvider( - sdktrace.WithSampler(sdktrace.AlwaysSample()), - sdktrace.WithBatcher(s.otelExporter), - sdktrace.WithResource(resource.NewSchemaless( - attribute.String("service.name", "go-feature-flag"), - attribute.String("service.version", config.Version), - )), + sdktrace.WithBatcher(exporter), + sdktrace.WithSampler(sampler), + sdktrace.WithResource(resource), ) + otel.SetTracerProvider(s.otelTraceProvider) + + // log OTel errors to zap rather than the default log package + otel.SetErrorHandler(otelErrHandler(func(err error) { + zapLog.Error("OTel error", zap.Error(err)) + })) + return nil } +type otelErrHandler func(err error) + +func (o otelErrHandler) Handle(err error) { + o(err) +} + +var _ otel.ErrorHandler = otelErrHandler(nil) + +// initSampler determines which sampling strategy to use. If OTEL_TRACES_SAMPLER +// is unset, we'll always sample. +// If it's set to jaeger_remote, we'll use the Jaeger sampling server (supports +// JAEGER_SAMPLER_MANAGER_HOST_PORT, JAEGER_SAMPLER_REFRESH_INTERVAL, and +// JAEGER_SAMPLER_MAX_OPERATIONS). +// If it's set to any other value, we return nil and sdktrace.NewTracerProvider +// will set up the initSampler from the environment. +func initSampler(serviceName string) (sdktrace.Sampler, error) { + sampler, ok := os.LookupEnv("OTEL_TRACES_SAMPLER") + if !ok { + return sdktrace.AlwaysSample(), nil + } + + if sampler != "jaeger_remote" { + return nil, nil + } + + samplerURL := "http://localhost:5778/sampling" + if v := os.Getenv("JAEGER_SAMPLER_MANAGER_HOST_PORT"); v != "" { + samplerURL = v + } + + samplerRefreshInterval := 1 * time.Minute + if v := os.Getenv("JAEGER_SAMPLER_REFRESH_INTERVAL"); v != "" { + d, err := time.ParseDuration(v) + if err != nil { + return nil, fmt.Errorf("parsing JAEGER_SAMPLER_REFRESH_INTERVAL: %w", err) + } + samplerRefreshInterval = d + } + + maxOperations := 256 + if v := os.Getenv("JAEGER_SAMPLER_MAX_OPERATIONS"); v != "" { + i, err := strconv.Atoi(v) + if err != nil { + return nil, fmt.Errorf("parsing JAEGER_SAMPLER_MAX_OPERATIONS: %w", err) + } + maxOperations = i + } + + return jaegerremote.New( + serviceName, + jaegerremote.WithSamplingServerURL(samplerURL), + jaegerremote.WithSamplingRefreshInterval(samplerRefreshInterval), + jaegerremote.WithMaxOperations(maxOperations), + jaegerremote.WithInitialSampler(sdktrace.AlwaysSample()), + ), nil +} + // Stop the OpenTelemetry service -func (s *OtelService) Stop() error { +func (s *OtelService) Stop(ctx context.Context) error { if s.otelExporter != nil { - err := s.otelExporter.Shutdown(context.Background()) + err := s.otelExporter.Shutdown(ctx) if err != nil { return err } } + if s.otelTraceProvider != nil { - err := s.otelTraceProvider.Shutdown(context.Background()) + err := s.otelTraceProvider.Shutdown(ctx) if err != nil { return err } diff --git a/cmd/relayproxy/api/server.go b/cmd/relayproxy/api/server.go index 85a69f2e44a..8b563a77348 100644 --- a/cmd/relayproxy/api/server.go +++ b/cmd/relayproxy/api/server.go @@ -119,7 +119,7 @@ func (s *Server) Start() { } // start the OpenTelemetry tracing service - err := s.otelService.Init(context.Background(), *s.config) + err := s.otelService.Init(context.Background(), s.zapLog, s.config) if err != nil { s.zapLog.Error("error while initializing Otel", zap.Error(err)) // we can continue because otel is not mandatory to start the server @@ -148,8 +148,8 @@ func (s *Server) StartAwsLambda() { } // Stop shutdown the API server -func (s *Server) Stop() { - err := s.otelService.Stop() +func (s *Server) Stop(ctx context.Context) { + err := s.otelService.Stop(ctx) if err != nil { s.zapLog.Error("impossible to stop otel", zap.Error(err)) } diff --git a/cmd/relayproxy/api/server_test.go b/cmd/relayproxy/api/server_test.go index 1d3ceb9b8cd..266fa399ef5 100644 --- a/cmd/relayproxy/api/server_test.go +++ b/cmd/relayproxy/api/server_test.go @@ -1,6 +1,7 @@ package api_test import ( + "context" "net/http" "strings" "testing" @@ -52,7 +53,7 @@ func Test_Starting_RelayProxy_with_monitoring_on_same_port(t *testing.T) { s := api.New(proxyConf, services, log.ZapLogger) go func() { s.Start() }() - defer s.Stop() + defer s.Stop(context.Background()) time.Sleep(10 * time.Millisecond) @@ -106,7 +107,7 @@ func Test_Starting_RelayProxy_with_monitoring_on_different_port(t *testing.T) { s := api.New(proxyConf, services, log.ZapLogger) go func() { s.Start() }() - defer s.Stop() + defer s.Stop(context.Background()) time.Sleep(10 * time.Millisecond) @@ -175,7 +176,7 @@ func Test_CheckOFREPAPIExists(t *testing.T) { s := api.New(proxyConf, services, log.ZapLogger) go func() { s.Start() }() - defer s.Stop() + defer s.Stop(context.Background()) time.Sleep(10 * time.Millisecond) diff --git a/cmd/relayproxy/main.go b/cmd/relayproxy/main.go index 52a31f5984e..b4be86d4b2a 100644 --- a/cmd/relayproxy/main.go +++ b/cmd/relayproxy/main.go @@ -1,8 +1,10 @@ package main import ( + "context" "fmt" "os" + "time" "github.com/spf13/pflag" "github.com/thomaspoignant/go-feature-flag/cmd/relayproxy/api" @@ -100,7 +102,11 @@ func main() { if proxyConf.StartAsAwsLambda { apiServer.StartAwsLambda() } else { + defer func() { + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + apiServer.Stop(ctx) + }() apiServer.Start() - defer func() { _ = apiServer.Stop }() } } diff --git a/go.mod b/go.mod index dfd5d941387..bc7e20fb9b3 100644 --- a/go.mod +++ b/go.mod @@ -50,10 +50,10 @@ require ( github.com/xitongsys/parquet-go v1.6.2 github.com/xitongsys/parquet-go-source v0.0.0-20230830030807-0dd610dbff1d go.mongodb.org/mongo-driver v1.17.1 + go.opentelemetry.io/contrib/exporters/autoexport v0.55.0 go.opentelemetry.io/contrib/instrumentation/github.com/labstack/echo/otelecho v0.55.0 + go.opentelemetry.io/contrib/samplers/jaegerremote v0.24.0 go.opentelemetry.io/otel v1.30.0 - go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.30.0 - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.30.0 go.opentelemetry.io/otel/sdk v1.30.0 go.uber.org/zap v1.27.0 golang.org/x/net v0.30.0 @@ -191,7 +191,7 @@ require ( github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect github.com/prometheus/client_model v0.6.1 // indirect - github.com/prometheus/common v0.55.0 // indirect + github.com/prometheus/common v0.59.1 // indirect github.com/prometheus/procfs v0.15.1 // indirect github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect github.com/samber/lo v1.44.0 // indirect @@ -215,11 +215,25 @@ require ( github.com/yusufpapurcu/wmi v1.2.3 // indirect go.einride.tech/aip v0.68.0 // indirect go.opencensus.io v0.24.0 // indirect + go.opentelemetry.io/contrib/bridges/prometheus v0.55.0 // indirect go.opentelemetry.io/contrib/detectors/gcp v1.29.0 // indirect go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.54.0 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.6.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.6.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.30.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.30.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.30.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.30.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.30.0 // indirect + go.opentelemetry.io/otel/exporters/prometheus v0.52.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.6.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.30.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.30.0 // indirect + go.opentelemetry.io/otel/log v0.6.0 // indirect go.opentelemetry.io/otel/metric v1.30.0 // indirect - go.opentelemetry.io/otel/sdk/metric v1.29.0 // indirect + go.opentelemetry.io/otel/sdk/log v0.6.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.30.0 // indirect go.opentelemetry.io/otel/trace v1.30.0 // indirect go.opentelemetry.io/proto/otlp v1.3.1 // indirect go.uber.org/multierr v1.11.0 // indirect diff --git a/go.sum b/go.sum index fd3f40dbe04..ebce4efaf49 100644 --- a/go.sum +++ b/go.sum @@ -792,8 +792,8 @@ github.com/prometheus/client_golang v1.20.4/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/j github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= -github.com/prometheus/common v0.55.0 h1:KEi6DK7lXW/m7Ig5i47x0vRzuBsHuvJdi5ee6Y3G1dc= -github.com/prometheus/common v0.55.0/go.mod h1:2SECS4xJG1kd8XF9IcM1gMX6510RAEL65zxzNImwdc8= +github.com/prometheus/common v0.59.1 h1:LXb1quJHWm1P6wq/U824uxYi4Sg0oGvNeUm1z5dJoX0= +github.com/prometheus/common v0.59.1/go.mod h1:GpWM7dewqmVYcd7SmRaiWVe9SSqjf0UrwnYnpEZNuT0= github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= github.com/r3labs/diff/v3 v3.0.1 h1:CBKqf3XmNRHXKmdU7mZP1w7TV0pDyVCis1AUHtA4Xtg= @@ -925,8 +925,12 @@ go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= +go.opentelemetry.io/contrib/bridges/prometheus v0.55.0 h1:1oZYcP3wuazG3O1563m8cs5vc/pBMTymRwgG9yvxMm8= +go.opentelemetry.io/contrib/bridges/prometheus v0.55.0/go.mod h1:sU48aWFqiqBXo2RBtq7KarczkW8uK6RdIU54y4VzpZs= go.opentelemetry.io/contrib/detectors/gcp v1.29.0 h1:TiaiXB4DpGD3sdzNlYQxruQngn5Apwzi1X0DRhuGvDQ= go.opentelemetry.io/contrib/detectors/gcp v1.29.0/go.mod h1:GW2aWZNwR2ZxDLdv8OyC2G8zkRoQBuURgV7RPQgcPoU= +go.opentelemetry.io/contrib/exporters/autoexport v0.55.0 h1:8kNP8SX9id5TY2feLB+79aFxE0kqzh3KvjF1nAfGxVM= +go.opentelemetry.io/contrib/exporters/autoexport v0.55.0/go.mod h1:WhcvzeuTOr58aYsJ7S4ubY1xMs0WXAPaqTQnxr8bRHk= go.opentelemetry.io/contrib/instrumentation/github.com/labstack/echo/otelecho v0.55.0 h1:dJfUeXRQiU+7IhOeqXV7f1hJA47cCOBmCY8uyygIEZg= go.opentelemetry.io/contrib/instrumentation/github.com/labstack/echo/otelecho v0.55.0/go.mod h1:Uk7Flfuk5HGTeggDwlwanunnSDcJydFRihfXT1Z5fEs= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.54.0 h1:r6I7RJCN86bpD/FQwedZ0vSixDpwuWREjW9oRMsmqDc= @@ -935,18 +939,42 @@ go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0 h1:TT4fX+n go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0/go.mod h1:L7UH0GbB0p47T4Rri3uHjbpCFYrVrwc1I25QhNPiGK8= go.opentelemetry.io/contrib/propagators/b3 v1.30.0 h1:vumy4r1KMyaoQRltX7cJ37p3nluzALX9nugCjNNefuY= go.opentelemetry.io/contrib/propagators/b3 v1.30.0/go.mod h1:fRbvRsaeVZ82LIl3u0rIvusIel2UUf+JcaaIpy5taho= +go.opentelemetry.io/contrib/samplers/jaegerremote v0.24.0 h1:LcynmmCFYwa0AySFI+yLEeZpwQi2yQdEkv5+zA3TwcI= +go.opentelemetry.io/contrib/samplers/jaegerremote v0.24.0/go.mod h1:oPzwx3Gp7+u62wvez470Yq/Yu0O7hpVl5SFBRGI4964= go.opentelemetry.io/otel v1.30.0 h1:F2t8sK4qf1fAmY9ua4ohFS/K+FUuOPemHUIXHtktrts= go.opentelemetry.io/otel v1.30.0/go.mod h1:tFw4Br9b7fOS+uEao81PJjVMjW/5fvNCbpsDIXqP0pc= +go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.6.0 h1:WYsDPt0fM4KZaMhLvY+x6TVXd85P/KNl3Ez3t+0+kGs= +go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.6.0/go.mod h1:vfY4arMmvljeXPNJOE0idEwuoPMjAPCWmBMmj6R5Ksw= +go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.6.0 h1:QSKmLBzbFULSyHzOdO9JsN9lpE4zkrz1byYGmJecdVE= +go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.6.0/go.mod h1:sTQ/NH8Yrirf0sJ5rWqVu+oT82i4zL9FaF6rWcqnptM= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.30.0 h1:WypxHH02KX2poqqbaadmkMYalGyy/vil4HE4PM4nRJc= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.30.0/go.mod h1:U79SV99vtvGSEBeeHnpgGJfTsnsdkWLpPN/CcHAzBSI= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.30.0 h1:VrMAbeJz4gnVDg2zEzjHG4dEH86j4jO6VYB+NgtGD8s= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.30.0/go.mod h1:qqN/uFdpeitTvm+JDqqnjm517pmQRYxTORbETHq5tOc= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.30.0 h1:lsInsfvhVIfOI6qHVyysXMNDnjO9Npvl7tlDPJFBVd4= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.30.0/go.mod h1:KQsVNh4OjgjTG0G6EiNi1jVpnaeeKsKMRwbLN+f1+8M= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.30.0 h1:m0yTiGDLUvVYaTFbAvCkVYIYcvwKt3G7OLoN77NUs/8= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.30.0/go.mod h1:wBQbT4UekBfegL2nx0Xk1vBcnzyBPsIVm9hRG4fYcr4= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.30.0 h1:umZgi92IyxfXd/l4kaDhnKgY8rnN/cZcF1LKc6I8OQ8= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.30.0/go.mod h1:4lVs6obhSVRb1EW5FhOuBTyiQhtRtAnnva9vD3yRfq8= +go.opentelemetry.io/otel/exporters/prometheus v0.52.0 h1:kmU3H0b9ufFSi8IQCcxack+sWUblKkFbqWYs6YiACGQ= +go.opentelemetry.io/otel/exporters/prometheus v0.52.0/go.mod h1:+wsAp2+JhuGXX7YRkjlkx6hyWY3ogFPfNA4x3nyiAh0= +go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.6.0 h1:bZHOb8k/CwwSt0DgvgaoOhBXWNdWqFWaIsGTtg1H3KE= +go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.6.0/go.mod h1:XlV163j81kDdIt5b5BXCjdqVfqJFy/LJrHA697SorvQ= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.30.0 h1:IyFlqNsi8VT/nwYlLJfdM0y1gavxGpEvnf6FtVfZ6X4= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.30.0/go.mod h1:bxiX8eUeKoAEQmbq/ecUT8UqZwCjZW52yJrXJUSozsk= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.30.0 h1:kn1BudCgwtE7PxLqcZkErpD8GKqLZ6BSzeW9QihQJeM= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.30.0/go.mod h1:ljkUDtAMdleoi9tIG1R6dJUpVwDcYjw3J2Q6Q/SuiC0= +go.opentelemetry.io/otel/log v0.6.0 h1:nH66tr+dmEgW5y+F9LanGJUBYPrRgP4g2EkmPE3LeK8= +go.opentelemetry.io/otel/log v0.6.0/go.mod h1:KdySypjQHhP069JX0z/t26VHwa8vSwzgaKmXtIB3fJM= go.opentelemetry.io/otel/metric v1.30.0 h1:4xNulvn9gjzo4hjg+wzIKG7iNFEaBMX00Qd4QIZs7+w= go.opentelemetry.io/otel/metric v1.30.0/go.mod h1:aXTfST94tswhWEb+5QjlSqG+cZlmyXy/u8jFpor3WqQ= go.opentelemetry.io/otel/sdk v1.30.0 h1:cHdik6irO49R5IysVhdn8oaiR9m8XluDaJAs4DfOrYE= go.opentelemetry.io/otel/sdk v1.30.0/go.mod h1:p14X4Ok8S+sygzblytT1nqG98QG2KYKv++HE0LY/mhg= -go.opentelemetry.io/otel/sdk/metric v1.29.0 h1:K2CfmJohnRgvZ9UAj2/FhIf/okdWcNdBwe1m8xFXiSY= -go.opentelemetry.io/otel/sdk/metric v1.29.0/go.mod h1:6zZLdCl2fkauYoZIOn/soQIDSWFmNSRcICarHfuhNJQ= +go.opentelemetry.io/otel/sdk/log v0.6.0 h1:4J8BwXY4EeDE9Mowg+CyhWVBhTSLXVXodiXxS/+PGqI= +go.opentelemetry.io/otel/sdk/log v0.6.0/go.mod h1:L1DN8RMAduKkrwRAFDEX3E3TLOq46+XMGSbUfHU/+vE= +go.opentelemetry.io/otel/sdk/metric v1.30.0 h1:QJLT8Pe11jyHBHfSAgYH7kEmT24eX792jZO1bo4BXkM= +go.opentelemetry.io/otel/sdk/metric v1.30.0/go.mod h1:waS6P3YqFNzeP01kuo/MBBYqaoBJl7efRQHOaydhy1Y= go.opentelemetry.io/otel/trace v1.30.0 h1:7UBkkYzeg3C7kQX8VAidWh2biiQbtAKjyIML8dQ9wmc= go.opentelemetry.io/otel/trace v1.30.0/go.mod h1:5EyKqTzzmyqB9bwtCCq6pDLktPK6fmGf/Dph+8VI02o= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=