122 lines
3.1 KiB
Go
122 lines
3.1 KiB
Go
package trace
|
|
|
|
import (
|
|
"context"
|
|
"log/slog"
|
|
"slices"
|
|
"time"
|
|
|
|
"m8sh.su/d/jules/chat"
|
|
"m8sh.su/d/jules/database"
|
|
"m8sh.su/d/jules/engine/actions"
|
|
"m8sh.su/d/jules/engine/user"
|
|
)
|
|
|
|
type Span struct {
|
|
ctx context.Context
|
|
attrs []slog.Attr
|
|
start time.Time
|
|
}
|
|
|
|
func FromMessage(ctx context.Context, msg chat.Message) *Span {
|
|
e := &Span{start: time.Now(), ctx: ctx}
|
|
e.attrs = append(e.attrs,
|
|
slog.String("type", "message_processing"),
|
|
slog.String("message_platform", msg.Chat),
|
|
slog.String("message_platform_user_id", msg.ID),
|
|
slog.String("message_content", msg.Text),
|
|
)
|
|
return e
|
|
}
|
|
|
|
func FromNotification(ctx context.Context, notif database.Notification) *Span {
|
|
e := &Span{start: time.Now(), ctx: ctx}
|
|
e.attrs = append(e.attrs,
|
|
slog.String("type", "notification_processing"),
|
|
slog.String("notification_id", notif.ID.String()),
|
|
slog.String("notification_user_id", notif.UserID.String()),
|
|
slog.String("notification_initiator_id", notif.InitiatorID.String()),
|
|
slog.String("notification_content", notif.Content),
|
|
)
|
|
return e
|
|
}
|
|
|
|
func (s *Span) User(u *user.User) *Span {
|
|
if u == nil || u.User == nil {
|
|
return s
|
|
}
|
|
s.attrs = append(s.attrs,
|
|
slog.String("user_id", u.ID.String()),
|
|
slog.String("user_lang", u.Language),
|
|
slog.String("user_tz", u.Timezone),
|
|
slog.String("user_chat", u.PreferredChat),
|
|
slog.String("user_role", u.Role),
|
|
)
|
|
for _, chat := range u.Chats {
|
|
s.attrs = append(s.attrs, slog.String("chat", chat.Platform))
|
|
}
|
|
for _, fact := range u.Facts {
|
|
s.attrs = append(s.attrs, slog.String("fact", fact.Value))
|
|
}
|
|
for _, contact := range u.Contacts {
|
|
s.attrs = append(s.attrs, slog.String("contact", contact.Name))
|
|
}
|
|
for _, n := range u.IncomingNotifications {
|
|
s.attrs = append(s.attrs, slog.String("incoming_notif", n.Content))
|
|
}
|
|
for _, n := range u.OutgoingNotifications {
|
|
s.attrs = append(s.attrs, slog.String("outgoing_notif", n.Content))
|
|
}
|
|
for _, a := range u.RecentActions {
|
|
s.attrs = append(s.attrs, slog.String("action", a.Type+" "+a.Content))
|
|
}
|
|
return s
|
|
}
|
|
|
|
func (s *Span) LLMResponse(content string) *Span {
|
|
for i, attr := range s.attrs {
|
|
if attr.Key == "llm_response" {
|
|
s.attrs[i] = slog.String("llm_response", content)
|
|
return s
|
|
}
|
|
}
|
|
s.attrs = append(s.attrs, slog.String("llm_response", content))
|
|
return s
|
|
}
|
|
|
|
func (s *Span) Actions(as []actions.Action) *Span {
|
|
s.attrs = slices.DeleteFunc(s.attrs, func(a slog.Attr) bool {
|
|
return a.Key == "action"
|
|
})
|
|
for _, action := range as {
|
|
s.attrs = append(s.attrs, slog.Any("action", string(actions.Raw(action))))
|
|
}
|
|
return s
|
|
}
|
|
|
|
func (s *Span) Info(msg string) {
|
|
s.log(slog.LevelInfo, msg)
|
|
}
|
|
|
|
func (s *Span) Warn(msg string, errs ...error) {
|
|
if len(errs) > 0 {
|
|
for _, err := range errs {
|
|
s.attrs = append(s.attrs, slog.Any("error", err))
|
|
}
|
|
}
|
|
s.log(slog.LevelWarn, msg)
|
|
}
|
|
|
|
func (s *Span) Error(msg string, err error) {
|
|
s.attrs = append(s.attrs, slog.String("error", err.Error()))
|
|
s.log(slog.LevelError, msg)
|
|
}
|
|
|
|
func (s *Span) log(level slog.Level, msg string) {
|
|
if s.ctx == nil {
|
|
s.ctx = context.Background()
|
|
}
|
|
s.attrs = append(s.attrs, slog.String("duration", time.Since(s.start).String()))
|
|
slog.LogAttrs(s.ctx, level, msg, s.attrs...)
|
|
}
|