package event import ( "git.ma-al.com/maal-libraries/observer/pkg/attr" "git.ma-al.com/maal-libraries/observer/pkg/level" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/codes" "go.opentelemetry.io/otel/trace" ) // An event that maps well to a log message type Event struct { FullMessage string ShortMessage string Attributes []attribute.KeyValue // Defaults to INFO when converted into attributes and unset Level level.SeverityLevel extraSkipInStack int } type IntoEvent interface { IntoEvent() Event } func (e Event) IntoEvent() Event { return e } func (e Event) IntoTraceAttributes() []attribute.KeyValue { attrs := make([]attribute.KeyValue, 0) attrs = append(attrs, attr.SourceCodeLocation(1+e.extraSkipInStack)...) attrs = append(attrs, e.Attributes...) if len(e.FullMessage) > 0 { attrs = append(attrs, attr.LogMessageLong(e.FullMessage)) } if len(e.ShortMessage) > 0 { attrs = append(attrs, attr.LogMessageShort(e.ShortMessage)) } if e.Level == 0 { e.Level = level.INFO } attrs = append(attrs, attr.SeverityLevel(e.Level)) return attrs } func (e Event) AsOpts() trace.EventOption { e.extraSkipInStack += 1 return trace.WithAttributes(e.IntoTraceAttributes()...) } func (e Event) SkipMoreInCallStack(skip int) Event { e.extraSkipInStack += skip return e } func NewInSpan[E IntoEvent](ev E, span trace.Span) { event := ev.IntoEvent() event.extraSkipInStack += 1 span.AddEvent(event.ShortMessage, trace.WithAttributes(event.IntoTraceAttributes()...)) } type Error struct { Err error ExtendedMessage string // Defaults to ALERT when converted into attributes and unset Level level.SeverityLevel Attributes []attribute.KeyValue extraSkipInStack int } type IntoErrorEvent interface { IntoErrorEvent() Error } func (e Error) Error() string { return e.Err.Error() } func (e Error) IntoErrorEvent() Error { return e } func (e Error) IntoTraceAttributes() []attribute.KeyValue { attrs := make([]attribute.KeyValue, 0) attrs = append(attrs, e.Attributes...) if len(e.ExtendedMessage) > 0 { attrs = append(attrs, attr.LogMessageLong(e.ExtendedMessage)) } if e.Level == 0 { e.Level = level.ALERT } attrs = append(attrs, attr.SeverityLevel(e.Level), attr.LogMessageShort(e.Err.Error())) attrs = append(attrs, attr.SourceCodeLocation(1+e.extraSkipInStack)...) return attrs } func (e Error) AsOpts() trace.EventOption { e.extraSkipInStack += 1 return trace.WithAttributes(e.IntoTraceAttributes()...) } func (e Error) SkipMoreInCallStack(skip int) Error { e.extraSkipInStack += skip return e } func NewErrInSpan[E IntoErrorEvent](err E, span trace.Span) E { er := err.IntoErrorEvent() er.extraSkipInStack += 1 span.RecordError(er.Err, er.AsOpts()) if er.Level <= level.ERR { span.SetStatus(codes.Error, er.Error()) } return err }