Skip to content

Commit ae0bc20

Browse files
committed
OTel: add command.time metric to plugin commands
Signed-off-by: Laura Brehm <laurabrehm@hey.com>
1 parent e81b835 commit ae0bc20

3 files changed

Lines changed: 34 additions & 6 deletions

File tree

cli-plugins/plugin/plugin.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,24 @@ func RunPlugin(dockerCli *command.DockerCli, plugin *cobra.Command, meta manager
4646
opts = append(opts, withPluginClientConn(plugin.Name()))
4747
}
4848
err = tcmd.Initialize(opts...)
49+
ogRunE := cmd.RunE
50+
if ogRunE == nil {
51+
ogRun := cmd.Run
52+
// necessary because error will always be nil here
53+
// see: https://github.com/golangci/golangci-lint/issues/1379
54+
//nolint:unparam
55+
ogRunE = func(cmd *cobra.Command, args []string) error {
56+
ogRun(cmd, args)
57+
return nil
58+
}
59+
cmd.Run = nil
60+
}
61+
cmd.RunE = func(cmd *cobra.Command, args []string) error {
62+
stopInstrumentation := dockerCli.StartInstrumentation(ctx, cmd)
63+
err := ogRunE(cmd, args)
64+
stopInstrumentation(err)
65+
return err
66+
}
4967
})
5068
return err
5169
}

cli/command/telemetry_utils.go

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,7 @@ func BaseCommandAttributes(cmd *cobra.Command, streams Streams) []attribute.KeyV
2626
// Note: this should be the last func to wrap/modify the PersistentRunE/RunE funcs before command execution.
2727
//
2828
// can also be used for spans!
29-
func (cli *DockerCli) InstrumentCobraCommands(cmd *cobra.Command, mp metric.MeterProvider) {
30-
meter := getDefaultMeter(mp)
29+
func (cli *DockerCli) InstrumentCobraCommands(ctx context.Context, cmd *cobra.Command) {
3130
// If PersistentPreRunE is nil, make it execute PersistentPreRun and return nil by default
3231
ogPersistentPreRunE := cmd.PersistentPreRunE
3332
if ogPersistentPreRunE == nil {
@@ -55,17 +54,27 @@ func (cli *DockerCli) InstrumentCobraCommands(cmd *cobra.Command, mp metric.Mete
5554
}
5655
cmd.RunE = func(cmd *cobra.Command, args []string) error {
5756
// start the timer as the first step of every cobra command
58-
baseAttrs := BaseCommandAttributes(cmd, cli)
59-
stopCobraCmdTimer := startCobraCommandTimer(cmd, meter, baseAttrs)
57+
stopInstrumentation := cli.StartInstrumentation(ctx, cmd)
6058
cmdErr := ogRunE(cmd, args)
61-
stopCobraCmdTimer(cmdErr)
59+
stopInstrumentation(cmdErr)
6260
return cmdErr
6361
}
6462

6563
return ogPersistentPreRunE(cmd, args)
6664
}
6765
}
6866

67+
// StartInstrumentation instruments CLI commands with the individual metrics and spans configured.
68+
// It's the main command OTel utility, and new command-related metrics should be added to it.
69+
// It should be called immediately before command execution, and returns a stopInstrumentation function
70+
// that must be called with the error resulting from the command execution.
71+
func (cli *DockerCli) StartInstrumentation(ctx context.Context, cmd *cobra.Command) (stopInstrumentation func(error)) {
72+
mp := cli.MeterProvider(ctx)
73+
meter := getDefaultMeter(mp)
74+
baseAttrs := BaseCommandAttributes(cmd, cli)
75+
return startCobraCommandTimer(cmd, meter, baseAttrs)
76+
}
77+
6978
func startCobraCommandTimer(cmd *cobra.Command, meter metric.Meter, attrs []attribute.KeyValue) func(err error) {
7079
ctx := cmd.Context()
7180
durationCounter, _ := meter.Float64Counter(

cmd/docker/docker.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -310,8 +310,9 @@ func runDocker(ctx context.Context, dockerCli *command.DockerCli) error {
310310

311311
mp := dockerCli.MeterProvider(ctx)
312312
defer mp.Shutdown(ctx)
313+
313314
otel.SetMeterProvider(mp)
314-
dockerCli.InstrumentCobraCommands(cmd, mp)
315+
dockerCli.InstrumentCobraCommands(ctx, cmd)
315316

316317
var envs []string
317318
args, os.Args, envs, err = processAliases(dockerCli, cmd, args, os.Args)

0 commit comments

Comments
 (0)