-
-
Notifications
You must be signed in to change notification settings - Fork 4
/
formatter_error.go
51 lines (43 loc) · 1.18 KB
/
formatter_error.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
package slogformatter
import (
"reflect"
"regexp"
"runtime"
"log/slog"
)
// ErrorFormatter transforms a go error into a readable error.
//
// Example:
//
// err := reader.Close()
// err = fmt.Errorf("could not close reader: %v", err)
// logger.With("error", reader.Close()).Log("error")
//
// passed to ErrorFormatter("error"), will be transformed into:
//
// "error": {
// "message": "could not close reader: file already closed",
// "type": "*io.ErrClosedPipe"
// }
func ErrorFormatter(fieldName string) Formatter {
return FormatByFieldType(fieldName, func(err error) slog.Value {
values := []slog.Attr{
slog.String("message", err.Error()),
slog.String("type", reflect.TypeOf(err).String()),
slog.String("stacktrace", stacktrace()),
}
return slog.GroupValue(values...)
})
}
// bearer:disable go_lang_permissive_regex_validation
var reStacktrace = regexp.MustCompile(`log/slog.*\n`)
func stacktrace() string {
stackInfo := make([]byte, 1024*1024)
if stackSize := runtime.Stack(stackInfo, false); stackSize > 0 {
traceLines := reStacktrace.Split(string(stackInfo[:stackSize]), -1)
if len(traceLines) > 0 {
return traceLines[len(traceLines)-1]
}
}
return ""
}