-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathhandler.go
172 lines (148 loc) · 4.31 KB
/
handler.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
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
package ligno
import (
"io"
"os"
"sync"
)
// Handler processes log records and writes them to appropriate destination.
type Handler interface {
// Handle processes provided log record.
Handle(Record) error
}
// HandlerCloser is interface that allows handlers to be closed.
// If handler implements this interface, when logger is stopped, Close will
// be called.
type HandlerCloser interface {
Close()
}
// HandlerFunc is function that implements Handler interface.
type HandlerFunc func(Record) error
// Handle just calls HandlerFunc.
func (hf HandlerFunc) Handle(record Record) error {
return hf(record)
}
// StreamHandler writes records to provided io.Writer
func StreamHandler(out io.Writer, formatter Formatter) Handler {
return HandlerFunc(func(record Record) error {
_, err := out.Write(formatter.Format(record))
return err
})
}
// Predicate is function that returns true if record should be logged, false otherwise.
type Predicate func(Record) bool
// FilterHandler checks records if by using predicate to check if they should
// be processed and only if they do, record is passed to provided handler.
func FilterHandler(predicate Predicate, handler Handler) Handler {
return HandlerFunc(func(record Record) error {
if predicate(record) {
return handler.Handle(record)
}
return nil
})
}
// FilterLevelHandler is FilterHandler with default predicate function that filters
// all records below provided level.
func FilterLevelHandler(level Level, handler Handler) Handler {
levelPredicate := Predicate(func(record Record) bool {
return record.Level >= level
})
return FilterHandler(levelPredicate, handler)
}
// combiningHandler combines multiple other handlers
type combiningHandler struct {
Handlers []Handler
}
// Handle processes record by passing it to all internal handler of this handler.
func (ch *combiningHandler) Handle(record Record) error {
var err error
for _, h := range ch.Handlers {
err = h.Handle(record)
}
return err
}
// Close closes all internal handlers if they implement HandlerCloser interface.
func (ch *combiningHandler) Close() {
for _, h := range ch.Handlers {
if handlerCloser, ok := h.(HandlerCloser); ok {
handlerCloser.Close()
}
}
}
// CombiningHandler creates and returns handler that passes records to all
// provided handlers.
func CombiningHandler(handlers ...Handler) Handler {
return &combiningHandler{
Handlers: handlers,
}
}
// FileHandler writes log records to file with provided name.
func FileHandler(fileName string, formatter Formatter) Handler {
return &fileHandler{
fileName: fileName,
formatter: formatter,
}
}
// fileHandler writes log messages to file with provided name.
type fileHandler struct {
fileName string
formatter Formatter
f *os.File
}
// Handle writes record to file.
func (fh *fileHandler) Handle(record Record) error {
if fh.f == nil {
f, err := os.OpenFile(fh.fileName, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0644)
if err != nil {
panic(err)
}
fh.f = f
}
_, err := fh.f.Write(fh.formatter.Format(record))
return err
}
// Close closes file were records are being written.
func (fh *fileHandler) Close() {
fh.f.Close()
}
// NullHandler returns handler that discards all records.
func NullHandler() Handler {
return HandlerFunc(func(record Record) error {
return nil
})
}
// InspectHandler is handler that is able to restore logged message and
// return them for inspection.
type InspectHandler interface {
Handler
Messages() []string
}
// MemoryHandler stores all records in memory, to be fetched and inspected later.
type memoryHandler struct {
buffer [][]byte
formatter Formatter
mu sync.Mutex
}
// Handle stores formatted record in memory.
func (mh *memoryHandler) Handle(record Record) error {
mh.mu.Lock()
defer mh.mu.Unlock()
mh.buffer = append(mh.buffer, mh.formatter.Format(record))
return nil
}
// Content returns content sent to logging to memory handler.
func (mh *memoryHandler) Messages() []string {
mh.mu.Lock()
defer mh.mu.Unlock()
messages := make([]string, 0, len(mh.buffer))
for _, msg := range mh.buffer {
messages = append(messages, string(msg))
}
return messages
}
// MemoryHandler returns handler instance that saves all message to memory.
func MemoryHandler(formatter Formatter) InspectHandler {
return &memoryHandler{
buffer: make([][]byte, 0),
formatter: formatter,
}
}