From 22a963533ad73adafe71c976a650fe9b10f4c27d Mon Sep 17 00:00:00 2001 From: "Jonathan A. Sternberg" Date: Mon, 1 Apr 2024 09:23:41 -0500 Subject: [PATCH] command: include default otel error handler for the cli This adds a default otel error handler for the cli in the debug package. It uses logrus to log the error on the debug level and should work out of the box with the `--debug` flag and `DEBUG` environment variable. Signed-off-by: Jonathan A. Sternberg --- cli-plugins/plugin/plugin.go | 6 +++++- cli/command/telemetry_utils.go | 5 +++++ cli/debug/debug.go | 11 +++++++++++ cmd/docker/docker.go | 2 ++ 4 files changed, 23 insertions(+), 1 deletion(-) diff --git a/cli-plugins/plugin/plugin.go b/cli-plugins/plugin/plugin.go index 54471b41b09b..c04edbb549ec 100644 --- a/cli-plugins/plugin/plugin.go +++ b/cli-plugins/plugin/plugin.go @@ -12,15 +12,17 @@ import ( "github.com/docker/cli/cli-plugins/socket" "github.com/docker/cli/cli/command" "github.com/docker/cli/cli/connhelper" + "github.com/docker/cli/cli/debug" "github.com/docker/docker/client" "github.com/spf13/cobra" + "go.opentelemetry.io/otel" ) // PersistentPreRunE must be called by any plugin command (or // subcommand) which uses the cobra `PersistentPreRun*` hook. Plugins // which do not make use of `PersistentPreRun*` do not need to call // this (although it remains safe to do so). Plugins are recommended -// to use `PersistenPreRunE` to enable the error to be +// to use `PersistentPreRunE` to enable the error to be // returned. Should not be called outside of a command's // PersistentPreRunE hook and must not be run unless Run has been // called. @@ -66,6 +68,8 @@ func RunPlugin(dockerCli *command.DockerCli, plugin *cobra.Command, meta manager // Run is the top-level entry point to the CLI plugin framework. It should be called from your plugin's `main()` function. func Run(makeCmd func(command.Cli) *cobra.Command, meta manager.Metadata) { + otel.SetErrorHandler(debug.OTELErrorHandler) + dockerCli, err := command.NewDockerCli() if err != nil { fmt.Fprintln(os.Stderr, err) diff --git a/cli/command/telemetry_utils.go b/cli/command/telemetry_utils.go index 034fa1f00ae2..05de4f0d3739 100644 --- a/cli/command/telemetry_utils.go +++ b/cli/command/telemetry_utils.go @@ -9,6 +9,7 @@ import ( "github.com/docker/cli/cli/version" "github.com/pkg/errors" + "github.com/sirupsen/logrus" "github.com/spf13/cobra" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/metric" @@ -156,3 +157,7 @@ func getDefaultMeter(mp metric.MeterProvider) metric.Meter { metric.WithInstrumentationVersion(version.Version), ) } + +func handleOTELError(err error) { + logrus.WithError(err).Debug("otel error") +} diff --git a/cli/debug/debug.go b/cli/debug/debug.go index b00ea63ad887..1a9a46abcca7 100644 --- a/cli/debug/debug.go +++ b/cli/debug/debug.go @@ -4,6 +4,7 @@ import ( "os" "github.com/sirupsen/logrus" + "go.opentelemetry.io/otel" ) // Enable sets the DEBUG env var to true @@ -24,3 +25,13 @@ func Disable() { func IsEnabled() bool { return os.Getenv("DEBUG") != "" } + +// OTELErrorHandler is an error handler for OTEL that +// uses the CLI debug package to log messages when an error +// occurs. +// +// The default is to log to the debug level which is only +// enabled when debugging is enabled. +var OTELErrorHandler otel.ErrorHandler = otel.ErrorHandlerFunc(func(err error) { + logrus.WithError(err).Debug("otel error") +}) diff --git a/cmd/docker/docker.go b/cmd/docker/docker.go index 1b871289ee72..1cf2bb45a214 100644 --- a/cmd/docker/docker.go +++ b/cmd/docker/docker.go @@ -14,6 +14,7 @@ import ( "github.com/docker/cli/cli-plugins/socket" "github.com/docker/cli/cli/command" "github.com/docker/cli/cli/command/commands" + "github.com/docker/cli/cli/debug" cliflags "github.com/docker/cli/cli/flags" "github.com/docker/cli/cli/version" platformsignals "github.com/docker/cli/cmd/docker/internal/signals" @@ -33,6 +34,7 @@ func main() { os.Exit(1) } logrus.SetOutput(dockerCli.Err()) + otel.SetErrorHandler(debug.OTELErrorHandler) if err := runDocker(ctx, dockerCli); err != nil { if sterr, ok := err.(cli.StatusError); ok {