package common import ( "context" "sort" "strings" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" "git.frostfs.info/TrueCloudLab/frostfs-node/misc" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" "github.com/spf13/cobra" "go.opentelemetry.io/otel/trace" ) type spanKey struct{} // StopClientCommandSpan stops tracing span for the command and prints trace ID on the standard output. func StopClientCommandSpan(cmd *cobra.Command, _ []string) { span, ok := cmd.Context().Value(spanKey{}).(trace.Span) if !ok { return } span.End() // Noop provider cannot fail on flush. _ = tracing.Shutdown(cmd.Context()) cmd.PrintErrf("Trace ID: %s\n", span.SpanContext().TraceID()) } // StartClientCommandSpan starts tracing span for the command. func StartClientCommandSpan(cmd *cobra.Command) { enableTracing, err := cmd.Flags().GetBool(commonflags.TracingFlag) if err != nil || !enableTracing { return } _, err = tracing.Setup(cmd.Context(), tracing.Config{ Enabled: true, Exporter: tracing.NoOpExporter, Service: "frostfs-cli", Version: misc.Version, }) commonCmd.ExitOnErr(cmd, "init tracing: %w", err) var components sort.StringSlice for c := cmd; c != nil; c = c.Parent() { components = append(components, c.Name()) } for i, j := 0, len(components)-1; i < j; { components.Swap(i, j) i++ j-- } operation := strings.Join(components, ".") ctx, span := tracing.StartSpanFromContext(cmd.Context(), operation) ctx = context.WithValue(ctx, spanKey{}, span) cmd.SetContext(ctx) }