package console_exporter import ( "context" "fmt" "sync" "git.ma-al.com/gora_filip/pkg/level" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/sdk/trace" ) type TraceFormatter interface { FormatSpans(spans []trace.ReadOnlySpan, removeFields []attribute.Key, verbosityLevel level.SeverityLevel, addTraceId bool, onlyErrors bool) (string, error) } // Configuration for the exporter. // // Most of options are passed to the formatter. type ExporterOptions struct { // Try to parse filters from an environment variable with a name provided by this field. // Result will only by applied to unset options. NOT IMPLEMENTED! FilterFromEnvVar *string // Filter the output based on the [level.SeverityLevel]. FilterOnLevel *level.SeverityLevel // Fields that should be removed from the output. FilterOutFields []attribute.Key // Print only trace events instead of whole traces. EmitEventsOnly bool // Add trace id to output EmitTraceId bool // Print output only when an error is found EmitOnlyOnError bool // Used only when `EmitEventsOnly` is set to true. TraceFormatter *TraceFormatter } type Exporter struct { lvl level.SeverityLevel removedFields []attribute.Key addTraceId bool onlyErrs bool traceFormatter TraceFormatter printerMu sync.Mutex stoppedMu sync.RWMutex stopped bool } func NewExporter(opts ExporterOptions) trace.SpanExporter { var formatter TraceFormatter var lvl level.SeverityLevel if opts.TraceFormatter != nil { formatter = *opts.TraceFormatter } else { formatter = TraceFormatter(&EventsOnlyFormatter{}) } if opts.FilterOnLevel != nil { lvl = *opts.FilterOnLevel } else { lvl = level.TRACE } return &Exporter{ traceFormatter: formatter, removedFields: opts.FilterOutFields, addTraceId: opts.EmitTraceId, onlyErrs: opts.EmitOnlyOnError, lvl: lvl, } } // Implements [trace.SpanExporter] func (e *Exporter) ExportSpans(ctx context.Context, spans []trace.ReadOnlySpan) error { e.stoppedMu.RLock() stopped := e.stopped e.stoppedMu.RUnlock() if stopped { return nil } if len(spans) == 0 { return nil } e.printerMu.Lock() defer e.printerMu.Unlock() printLine, err := e.traceFormatter.FormatSpans(spans, e.removedFields, e.lvl, e.addTraceId, e.onlyErrs) if err != nil { fmt.Printf("FAILED TO FORMAT A TRACE WITH ERR: %#v\n", err) } if len(printLine) > 0 { fmt.Println(printLine) } return nil } // Implements [trace.SpanExporter] func (e *Exporter) Shutdown(ctx context.Context) error { e.stoppedMu.Lock() e.stopped = true e.stoppedMu.Unlock() select { case <-ctx.Done(): return ctx.Err() default: } return nil }