From 6691085012a5d0a711aebe0e0e126c2b12c31ab2 Mon Sep 17 00:00:00 2001 From: Christopher Petito Date: Tue, 14 May 2024 15:23:49 +0000 Subject: [PATCH] Use funcs on DockerCli to return Meter/TracerProviders, not initialize them. Initialize them during DockerCli struct init Signed-off-by: Christopher Petito (cherry picked from commit 02537eac596a6e1bab435c8d2445603990445678) --- cli/command/cli.go | 5 ++++ cli/command/telemetry.go | 52 ++++++++++++++++++++++++---------------- cmd/docker/docker.go | 10 +++++--- 3 files changed, 44 insertions(+), 23 deletions(-) diff --git a/cli/command/cli.go b/cli/command/cli.go index a8b4c88bcad1..28253f8c16c1 100644 --- a/cli/command/cli.go +++ b/cli/command/cli.go @@ -273,6 +273,11 @@ func (cli *DockerCli) Initialize(opts *cliflags.ClientOptions, ops ...CLIOption) return ResolveDefaultContext(cli.options, cli.contextStoreConfig) }, } + + // TODO(krissetto): pass ctx to the funcs instead of using this + cli.createGlobalMeterProvider(cli.baseCtx) + cli.createGlobalTracerProvider(cli.baseCtx) + return nil } diff --git a/cli/command/telemetry.go b/cli/command/telemetry.go index 92e80420ac4e..8db51c0596b5 100644 --- a/cli/command/telemetry.go +++ b/cli/command/telemetry.go @@ -41,35 +41,25 @@ type TelemetryClient interface { // each time this function is invoked. Resource() *resource.Resource - // TracerProvider returns a TracerProvider. This TracerProvider will be configured - // with the default tracing components for a CLI program along with any options given - // for the SDK. - TracerProvider(ctx context.Context, opts ...sdktrace.TracerProviderOption) TracerProvider + // TracerProvider returns the currently initialized TracerProvider. This TracerProvider will be configured + // with the default tracing components for a CLI program + TracerProvider() trace.TracerProvider - // MeterProvider returns a MeterProvider. This MeterProvider will be configured - // with the default metric components for a CLI program along with any options given - // for the SDK. - MeterProvider(ctx context.Context, opts ...sdkmetric.Option) MeterProvider + // MeterProvider returns the currently initialized MeterProvider. This MeterProvider will be configured + // with the default metric components for a CLI program + MeterProvider() metric.MeterProvider } func (cli *DockerCli) Resource() *resource.Resource { return cli.res.Get() } -func (cli *DockerCli) TracerProvider(ctx context.Context, opts ...sdktrace.TracerProviderOption) TracerProvider { - allOpts := make([]sdktrace.TracerProviderOption, 0, len(opts)+2) - allOpts = append(allOpts, sdktrace.WithResource(cli.Resource())) - allOpts = append(allOpts, dockerSpanExporter(ctx, cli)...) - allOpts = append(allOpts, opts...) - return sdktrace.NewTracerProvider(allOpts...) +func (cli *DockerCli) TracerProvider() trace.TracerProvider { + return otel.GetTracerProvider() } -func (cli *DockerCli) MeterProvider(ctx context.Context, opts ...sdkmetric.Option) MeterProvider { - allOpts := make([]sdkmetric.Option, 0, len(opts)+2) - allOpts = append(allOpts, sdkmetric.WithResource(cli.Resource())) - allOpts = append(allOpts, dockerMetricExporter(ctx, cli)...) - allOpts = append(allOpts, opts...) - return sdkmetric.NewMeterProvider(allOpts...) +func (cli *DockerCli) MeterProvider() metric.MeterProvider { + return otel.GetMeterProvider() } // WithResourceOptions configures additional options for the default resource. The default @@ -122,6 +112,28 @@ func (r *telemetryResource) init() { r.opts = nil } +// createGlobalMeterProvider creates a new MeterProvider from the initialized DockerCli struct +// with the given options and sets it as the global meter provider +func (cli *DockerCli) createGlobalMeterProvider(ctx context.Context, opts ...sdkmetric.Option) { + allOpts := make([]sdkmetric.Option, 0, len(opts)+2) + allOpts = append(allOpts, sdkmetric.WithResource(cli.Resource())) + allOpts = append(allOpts, dockerMetricExporter(ctx, cli)...) + allOpts = append(allOpts, opts...) + mp := sdkmetric.NewMeterProvider(allOpts...) + otel.SetMeterProvider(mp) +} + +// createGlobalTracerProvider creates a new TracerProvider from the initialized DockerCli struct +// with the given options and sets it as the global tracer provider +func (cli *DockerCli) createGlobalTracerProvider(ctx context.Context, opts ...sdktrace.TracerProviderOption) { + allOpts := make([]sdktrace.TracerProviderOption, 0, len(opts)+2) + allOpts = append(allOpts, sdktrace.WithResource(cli.Resource())) + allOpts = append(allOpts, dockerSpanExporter(ctx, cli)...) + allOpts = append(allOpts, opts...) + tp := sdktrace.NewTracerProvider(allOpts...) + otel.SetTracerProvider(tp) +} + func defaultResourceOptions() []resource.Option { return []resource.Option{ resource.WithDetectors(serviceNameDetector{}), diff --git a/cmd/docker/docker.go b/cmd/docker/docker.go index b87c24fba715..3021184dd35f 100644 --- a/cmd/docker/docker.go +++ b/cmd/docker/docker.go @@ -307,9 +307,13 @@ func runDocker(ctx context.Context, dockerCli *command.DockerCli) error { return err } - mp := dockerCli.MeterProvider(ctx) - defer mp.Shutdown(ctx) - otel.SetMeterProvider(mp) + mp := dockerCli.MeterProvider() + if mp, ok := mp.(command.MeterProvider); ok { + defer mp.Shutdown(ctx) + } else { + fmt.Fprint(dockerCli.Err(), "Warning: Unexpected OTEL error, metrics may not be flushed") + } + dockerCli.InstrumentCobraCommands(cmd, mp) var envs []string