package console_exporter import ( "fmt" "slices" "git.ma-al.com/maal-libraries/observer/pkg/console_fmt" "git.ma-al.com/maal-libraries/observer/pkg/level" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/sdk/trace" ) func NewPrettyMultilineFormatter() TraceFormatter { return &PrettyMultilineFormatter{} } // A formatter that will print only events using a multiline format with colors. // It uses attributes from the [attr] and [semconv] packages. type PrettyMultilineFormatter struct{} func AttrValueToString(val attribute.Value) string { switch val.Type() { case attribute.STRING: return val.AsString() case attribute.BOOL: if val.AsBool() { return "true" } else { return "false" } case attribute.BOOLSLICE, attribute.INT64SLICE, attribute.FLOAT64SLICE, attribute.STRINGSLICE: json, _ := val.MarshalJSON() return string(json) case attribute.FLOAT64: fmt.Sprintf("%f", val.AsFloat64()) case attribute.INT64: return fmt.Sprintf("%d", val.AsInt64()) default: json, _ := val.MarshalJSON() return string(json) } return "" } func (f *PrettyMultilineFormatter) FormatSpanStart(span trace.ReadOnlySpan, selectedAttrs []attribute.KeyValue, lvl level.SeverityLevel) (string, error) { attrs := "" slices.SortFunc(selectedAttrs, func(a, b attribute.KeyValue) int { if a.Key > b.Key { return 1 } else { return -1 } }) for _, kv := range selectedAttrs { if len(kv.Key) > 0 { attrs += fmt.Sprintf("\t%s = %s\n", string(kv.Key), AttrValueToString(kv.Value)) } } formattedSpanString := fmt.Sprintf( "%s\n%s", console_fmt.Bold(console_fmt.SeverityLevelToColor(lvl)+fmt.Sprintf("[%s][SpanStart] ", lvl.String())+span.Name()), attrs, ) return formattedSpanString, nil } func (f *PrettyMultilineFormatter) FormatSpanEnd(span trace.ReadOnlySpan, selectedAttrs []attribute.KeyValue, lvl level.SeverityLevel) (string, error) { attrs := "" slices.SortFunc(selectedAttrs, func(a, b attribute.KeyValue) int { if a.Key > b.Key { return 1 } else { return -1 } }) for _, kv := range selectedAttrs { if len(kv.Key) > 0 { attrs += fmt.Sprintf("\t%s = %s\n", string(kv.Key), AttrValueToString(kv.Value)) } } formattedSpanString := fmt.Sprintf( "%s\n%s", console_fmt.Bold(console_fmt.SeverityLevelToColor(lvl)+fmt.Sprintf("[%s][SpanEnd] ", lvl.String())+span.Name()), attrs, ) return formattedSpanString, nil } func (f *PrettyMultilineFormatter) FormatEvent(event trace.Event, span trace.ReadOnlySpan, selectedAttrs []attribute.KeyValue, lvl level.SeverityLevel) (string, error) { attrs := "" slices.SortFunc(selectedAttrs, func(a, b attribute.KeyValue) int { if a.Key > b.Key { return 1 } else { return -1 } }) for _, kv := range selectedAttrs { if len(kv.Key) > 0 { attrs += fmt.Sprintf("\t%s = %s\n", string(kv.Key), AttrValueToString(kv.Value)) } } formattedSpanString := fmt.Sprintf( "%s\n%s", console_fmt.Bold(console_fmt.SeverityLevelToColor(lvl)+fmt.Sprintf("[%s][Event] ", lvl.String())+event.Name), attrs, ) return formattedSpanString, nil }