-
Notifications
You must be signed in to change notification settings - Fork 1
/
writer.go
97 lines (86 loc) · 2.05 KB
/
writer.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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
package tracer
import (
"bytes"
"fmt"
"io"
"os"
"regexp"
"strings"
"text/template"
"time"
)
var pointerPattern = regexp.MustCompile(`<\*>\([^)]+\)`)
type Entry struct {
Owner string
Level uint8
Message string
Args []interface{}
Time time.Time
TransactionId string
StackTrace StackTrace
}
type Writer interface {
Write(entry Entry)
}
func DefaultStringer(value interface{}) string {
if stringer, ok := value.(fmt.Stringer); ok {
return stringer.String()
} else if err, ok := value.(error); ok {
return err.Error()
}
rep := fmt.Sprintf("%+v", value)
return pointerPattern.ReplaceAllStringFunc(rep, func(str string) string {
return ""
})
}
type Formatter func(entry Entry) string
type FileWriter struct {
formatter Formatter
writer io.Writer
}
func (fw *FileWriter) Write(entry Entry) {
_, err := fw.writer.Write([]byte(fw.formatter(entry)))
if err != nil {
_, _ = fmt.Fprintf(os.Stderr, "FAIL ON LOGGING ENTRY BECAUSE: %v\n", err.Error())
}
}
func NewFileWriter(file io.Writer, formatter Formatter) *FileWriter {
return &FileWriter{
writer: file,
formatter: formatter,
}
}
var variablePattern = regexp.MustCompile(`@\w+`)
func SimpleFormatter(format string, stringer func(interface{}) string) Formatter {
if stringer == nil {
stringer = DefaultStringer
}
format = variablePattern.ReplaceAllStringFunc(format, func(match string) string {
return fmt.Sprintf("{{.%s}}", strings.Title(match[1:]))
})
t, err := template.New("log").Parse(format)
if err != nil {
panic(err)
}
return func(entry Entry) string {
var buf bytes.Buffer
reps := make([]interface{}, len(entry.Args))
for i := range entry.Args {
reps[i] = stringer(entry.Args[i])
}
entry.Args = reps
err := t.Execute(&buf, struct {
Entry
Time string
LevelName string
}{
Entry: entry,
Time: entry.Time.Format(time.RFC3339),
LevelName: LevelNames[entry.Level],
})
if err != nil {
return fmt.Sprintf("FAILED TO FORMAT ENTRY BECAUSE: %v\n", err.Error())
}
return buf.String()
}
}