diff --git a/commands/bake.go b/commands/bake.go index 77ad7529d086..6da4e9a99bcd 100644 --- a/commands/bake.go +++ b/commands/bake.go @@ -45,7 +45,7 @@ type bakeOptions struct { func runBake(dockerCli command.Cli, targets []string, in bakeOptions, cFlags commonFlags) (err error) { ctx := appcontext.Context() - ctx, end, err := tracing.TraceCurrentCommand(ctx, "bake") + ctx, end, err := tracing.TraceCurrentCommand(ctx, dockerCli, "bake") if err != nil { return err } diff --git a/util/tracing/trace.go b/util/tracing/trace.go index c95ad5a43424..308de0e517a7 100644 --- a/util/tracing/trace.go +++ b/util/tracing/trace.go @@ -2,16 +2,27 @@ package tracing import ( "context" + "fmt" "os" "strings" + "github.com/docker/cli/cli/command" "github.com/moby/buildkit/util/tracing/detect" "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc" + sdktrace "go.opentelemetry.io/otel/sdk/trace" "go.opentelemetry.io/otel/trace" ) -func TraceCurrentCommand(ctx context.Context, name string) (context.Context, func(error), error) { - tp, err := detect.TracerProvider() +const otelConfigFieldName = "otel" + +func TraceCurrentCommand(ctx context.Context, cli command.Cli, name string) (context.Context, func(error), error) { + opts, err := tracerProviderOptions(cli) + if err != nil { + return context.Background(), nil, err + } + + tp, err := detect.NewTracerProvider(ctx, opts...) if err != nil { return context.Background(), nil, err } @@ -25,6 +36,54 @@ func TraceCurrentCommand(ctx context.Context, name string) (context.Context, fun } span.End() - detect.Shutdown(context.TODO()) + tp.Shutdown(context.TODO()) + }, nil +} + +func tracerProviderOptions(cli command.Cli) ([]sdktrace.TracerProviderOption, error) { + meta, err := cli.ContextStore().GetMetadata(cli.CurrentContext()) + if err != nil { + return nil, err + } + + var otelCfg interface{} + switch m := meta.Metadata.(type) { + case command.DockerContext: + otelCfg = m.AdditionalFields[otelConfigFieldName] + case map[string]interface{}: + otelCfg = m[otelConfigFieldName] + } + + if otelCfg == nil { + return nil, nil + } + + otelMap, ok := otelCfg.(map[string]interface{}) + if !ok { + return nil, fmt.Errorf( + "unexpected type for field %q: %T (expected: %T)", + otelConfigFieldName, + otelCfg, + otelMap, + ) + } + + // keys from https://opentelemetry.io/docs/concepts/sdk-configuration/otlp-exporter-configuration/ + endpoint, _ := otelMap["OTEL_EXPORTER_OTLP_ENDPOINT"].(string) + if endpoint == "" { + return nil, nil + } + + // Hardcoded endpoint from the endpoint. + exp, err := otlptracegrpc.New(context.Background(), + otlptracegrpc.WithEndpoint(endpoint), + otlptracegrpc.WithInsecure()) + if err != nil { + return nil, err + } + + sp := sdktrace.NewBatchSpanProcessor(exp) + return []sdktrace.TracerProviderOption{ + sdktrace.WithSpanProcessor(sp), }, nil }