mirror of
https://github.com/cgzirim/seek-tune.git
synced 2025-12-17 17:04:22 +00:00
83 lines
1.5 KiB
Go
83 lines
1.5 KiB
Go
package utils
|
|
|
|
import (
|
|
"log/slog"
|
|
"os"
|
|
"path/filepath"
|
|
|
|
"github.com/mdobak/go-xerrors"
|
|
)
|
|
|
|
type stackFrame struct {
|
|
Func string `json:"func"`
|
|
Source string `json:"source"`
|
|
Line int `json:"line"`
|
|
}
|
|
|
|
func replaceAttr(_ []string, a slog.Attr) slog.Attr {
|
|
switch a.Value.Kind() {
|
|
case slog.KindAny:
|
|
switch v := a.Value.Any().(type) {
|
|
case error:
|
|
a.Value = fmtErr(v)
|
|
}
|
|
}
|
|
|
|
return a
|
|
}
|
|
|
|
// marshalStack extracts stack frames from the error
|
|
func marshalStack(err error) []stackFrame {
|
|
trace := xerrors.StackTrace(err)
|
|
|
|
if len(trace) == 0 {
|
|
return nil
|
|
}
|
|
|
|
frames := trace.Frames()
|
|
|
|
s := make([]stackFrame, len(frames))
|
|
|
|
for i, v := range frames {
|
|
f := stackFrame{
|
|
Source: filepath.Join(
|
|
filepath.Base(filepath.Dir(v.File)),
|
|
filepath.Base(v.File),
|
|
),
|
|
Func: filepath.Base(v.Function),
|
|
Line: v.Line,
|
|
}
|
|
|
|
s[i] = f
|
|
}
|
|
|
|
return s
|
|
}
|
|
|
|
// fmtErr returns a slog.Value with keys `msg` and `trace`. If the error
|
|
// does not implement interface { StackTrace() errors.StackTrace }, the `trace`
|
|
// key is omitted.
|
|
func fmtErr(err error) slog.Value {
|
|
var groupValues []slog.Attr
|
|
|
|
groupValues = append(groupValues, slog.String("msg", err.Error()))
|
|
|
|
frames := marshalStack(err)
|
|
|
|
if frames != nil {
|
|
groupValues = append(groupValues,
|
|
slog.Any("trace", frames),
|
|
)
|
|
}
|
|
|
|
return slog.GroupValue(groupValues...)
|
|
}
|
|
|
|
func GetLogger() *slog.Logger {
|
|
h := slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{
|
|
ReplaceAttr: replaceAttr,
|
|
})
|
|
|
|
logger := slog.New(h)
|
|
return logger
|
|
}
|