From 9d884501186b2269d341df6a4242627a70715c46 Mon Sep 17 00:00:00 2001 From: Tonis Tiigi Date: Fri, 2 Jul 2021 21:39:57 -0700 Subject: [PATCH] enable opentelemetry support Signed-off-by: Tonis Tiigi --- build/build.go | 23 +++++++++++++++++++++-- cmd/buildx/main.go | 13 +++++++++++++ commands/bake.go | 9 +++++++++ commands/build.go | 11 ++++++++++- driver/docker-container/driver.go | 10 +++++++++- driver/driver.go | 2 +- driver/kubernetes/driver.go | 11 ++++++++++- util/tracing/trace.go | 30 ++++++++++++++++++++++++++++++ 8 files changed, 103 insertions(+), 6 deletions(-) create mode 100644 util/tracing/trace.go diff --git a/build/build.go b/build/build.go index 7aacb0a2..8c24795c 100644 --- a/build/build.go +++ b/build/build.go @@ -33,10 +33,12 @@ import ( "github.com/moby/buildkit/util/apicaps" "github.com/moby/buildkit/util/entitlements" "github.com/moby/buildkit/util/progress/progresswriter" + "github.com/moby/buildkit/util/tracing" "github.com/opencontainers/go-digest" specs "github.com/opencontainers/image-spec/specs-go/v1" "github.com/pkg/errors" "github.com/sirupsen/logrus" + "go.opentelemetry.io/otel/trace" "golang.org/x/sync/errgroup" ) @@ -191,6 +193,8 @@ func resolveDrivers(ctx context.Context, drivers []DriverInfo, auth Auth, opt ma bopts := make([]gateway.BuildOpts, len(clients)) + span, ctx := tracing.StartSpan(ctx, "load buildkit capabilities", trace.WithSpanKind(trace.SpanKindInternal)) + eg, ctx := errgroup.WithContext(ctx) for i, c := range clients { func(i int, c *client.Client) { @@ -204,7 +208,10 @@ func resolveDrivers(ctx context.Context, drivers []DriverInfo, auth Auth, opt ma }(i, c) } - if err := eg.Wait(); err != nil { + err = eg.Wait() + span.RecordError(err) + span.End() + if err != nil { return nil, nil, err } for key := range dps { @@ -641,13 +648,25 @@ func Build(ctx context.Context, drivers []DriverInfo, opt map[string]Options, do dps := m[k] multiDriver := len(m[k]) > 1 + var span trace.Span + ctx := ctx + if multiTarget { + span, ctx = tracing.StartSpan(ctx, k) + } + res := make([]*client.SolveResponse, len(dps)) wg := &sync.WaitGroup{} wg.Add(len(dps)) var pushNames string - eg.Go(func() error { + eg.Go(func() (err error) { + defer func() { + if span != nil { + span.RecordError(err) + span.End() + } + }() pw := progress.WithPrefix(w, "default", false) wg.Wait() select { diff --git a/cmd/buildx/main.go b/cmd/buildx/main.go index 63bcc70f..08836a56 100644 --- a/cmd/buildx/main.go +++ b/cmd/buildx/main.go @@ -15,6 +15,11 @@ import ( cliflags "github.com/docker/cli/cli/flags" "github.com/moby/buildkit/solver/errdefs" "github.com/moby/buildkit/util/stack" + "github.com/moby/buildkit/util/tracing/detect" + "go.opentelemetry.io/otel" + + _ "github.com/moby/buildkit/util/tracing/detect/delegated" + _ "github.com/moby/buildkit/util/tracing/env" // FIXME: "k8s.io/client-go/plugin/pkg/client/auth/azure" is excluded because of compilation error _ "k8s.io/client-go/plugin/pkg/client/auth/gcp" @@ -31,6 +36,10 @@ var experimental string func init() { seed.WithTimeAndRand() stack.SetVersionInfo(version.Version, version.Revision) + + detect.ServiceName = "buildx" + // do not log tracing errors to stdio + otel.SetErrorHandler(skipErrors{}) } func main() { @@ -90,3 +99,7 @@ func main() { os.Exit(1) } } + +type skipErrors struct{} + +func (skipErrors) Handle(err error) {} diff --git a/commands/bake.go b/commands/bake.go index e98fef12..dffba509 100644 --- a/commands/bake.go +++ b/commands/bake.go @@ -9,6 +9,7 @@ import ( "github.com/docker/buildx/bake" "github.com/docker/buildx/build" "github.com/docker/buildx/util/progress" + "github.com/docker/buildx/util/tracing" "github.com/docker/cli/cli/command" "github.com/docker/docker/pkg/ioutils" "github.com/moby/buildkit/util/appcontext" @@ -26,6 +27,14 @@ type bakeOptions struct { func runBake(dockerCli command.Cli, targets []string, in bakeOptions) (err error) { ctx := appcontext.Context() + ctx, end, err := tracing.TraceCurrentCommand(ctx, "bake") + if err != nil { + return err + } + defer func() { + end(err) + }() + var url string if len(targets) > 0 { diff --git a/commands/build.go b/commands/build.go index 39581bbe..3e623cab 100644 --- a/commands/build.go +++ b/commands/build.go @@ -11,6 +11,7 @@ import ( "github.com/docker/buildx/util/buildflags" "github.com/docker/buildx/util/platformutil" "github.com/docker/buildx/util/progress" + "github.com/docker/buildx/util/tracing" "github.com/docker/cli/cli" "github.com/docker/cli/cli/command" "github.com/docker/docker/pkg/ioutils" @@ -80,7 +81,7 @@ type commonOptions struct { exportLoad bool } -func runBuild(dockerCli command.Cli, in buildOptions) error { +func runBuild(dockerCli command.Cli, in buildOptions) (err error) { if in.squash { return errors.Errorf("squash currently not implemented") } @@ -90,6 +91,14 @@ func runBuild(dockerCli command.Cli, in buildOptions) error { ctx := appcontext.Context() + ctx, end, err := tracing.TraceCurrentCommand(ctx, "build") + if err != nil { + return err + } + defer func() { + end(err) + }() + noCache := false if in.noCache != nil { noCache = *in.noCache diff --git a/driver/docker-container/driver.go b/driver/docker-container/driver.go index 31ded4b5..a2e475e9 100644 --- a/driver/docker-container/driver.go +++ b/driver/docker-container/driver.go @@ -21,6 +21,7 @@ import ( dockerclient "github.com/docker/docker/client" "github.com/docker/docker/pkg/stdcopy" "github.com/moby/buildkit/client" + "github.com/moby/buildkit/util/tracing/detect" "github.com/pkg/errors" ) @@ -279,9 +280,16 @@ func (d *Driver) Client(ctx context.Context) (*client.Client, error) { conn = demuxConn(conn) + exp, err := detect.Exporter() + if err != nil { + return nil, err + } + + td, _ := exp.(client.TracerDelegate) + return client.New(ctx, "", client.WithContextDialer(func(context.Context, string) (net.Conn, error) { return conn, nil - })) + }), client.WithTracerDelegate(td)) } func (d *Driver) Factory() driver.Factory { diff --git a/driver/driver.go b/driver/driver.go index 791694be..c9ed229f 100644 --- a/driver/driver.go +++ b/driver/driver.go @@ -78,7 +78,7 @@ func Boot(ctx context.Context, d Driver, pw progress.Writer) (*client.Client, er } } - c, err := d.Client(context.TODO()) + c, err := d.Client(ctx) if err != nil { if errors.Cause(err) == ErrNotRunning && try <= 2 { continue diff --git a/driver/kubernetes/driver.go b/driver/kubernetes/driver.go index 063fb954..fc0bdff0 100644 --- a/driver/kubernetes/driver.go +++ b/driver/kubernetes/driver.go @@ -15,6 +15,7 @@ import ( "github.com/docker/buildx/util/platformutil" "github.com/docker/buildx/util/progress" "github.com/moby/buildkit/client" + "github.com/moby/buildkit/util/tracing/detect" "github.com/pkg/errors" appsv1 "k8s.io/api/apps/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -169,9 +170,17 @@ func (d *Driver) Client(ctx context.Context) (*client.Client, error) { if err != nil { return nil, err } + + exp, err := detect.Exporter() + if err != nil { + return nil, err + } + + td, _ := exp.(client.TracerDelegate) + return client.New(ctx, "", client.WithContextDialer(func(context.Context, string) (net.Conn, error) { return conn, nil - })) + }), client.WithTracerDelegate(td)) } func (d *Driver) Factory() driver.Factory { diff --git a/util/tracing/trace.go b/util/tracing/trace.go new file mode 100644 index 00000000..c95ad5a4 --- /dev/null +++ b/util/tracing/trace.go @@ -0,0 +1,30 @@ +package tracing + +import ( + "context" + "os" + "strings" + + "github.com/moby/buildkit/util/tracing/detect" + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/trace" +) + +func TraceCurrentCommand(ctx context.Context, name string) (context.Context, func(error), error) { + tp, err := detect.TracerProvider() + if err != nil { + return context.Background(), nil, err + } + ctx, span := tp.Tracer("").Start(ctx, name, trace.WithAttributes( + attribute.String("command", strings.Join(os.Args, " ")), + )) + + return ctx, func(err error) { + if err != nil { + span.RecordError(err) + } + span.End() + + detect.Shutdown(context.TODO()) + }, nil +}