Add API Framework Revel Source Files
[iec.git] / src / foundation / api / revel / logger / handlers.go
1 package logger
2
3 import (
4         "fmt"
5         "io"
6 )
7
8 type LevelFilterHandler struct {
9         Level LogLevel
10         h     LogHandler
11 }
12
13 // Filters out records which do not match the level
14 // Uses the `log15.FilterHandler` to perform this task
15 func LevelHandler(lvl LogLevel, h LogHandler) LogHandler {
16         return &LevelFilterHandler{lvl, h}
17 }
18
19 // The implementation of the Log
20 func (h LevelFilterHandler) Log(r *Record) error {
21         if r.Level == h.Level {
22                 return h.h.Log(r)
23         }
24         return nil
25 }
26
27 // Filters out records which do not match the level
28 // Uses the `log15.FilterHandler` to perform this task
29 func MinLevelHandler(lvl LogLevel, h LogHandler) LogHandler {
30         return FilterHandler(func(r *Record) (pass bool) {
31                 return r.Level <= lvl
32         }, h)
33 }
34
35 // Filters out records which match the level
36 // Uses the `log15.FilterHandler` to perform this task
37 func NotLevelHandler(lvl LogLevel, h LogHandler) LogHandler {
38         return FilterHandler(func(r *Record) (pass bool) {
39                 return r.Level != lvl
40         }, h)
41 }
42
43 func CallerFileHandler(h LogHandler) LogHandler {
44         return FuncHandler(func(r *Record) error {
45                 r.Context.Add("caller", fmt.Sprint(r.Call))
46                 return h.Log(r)
47         })
48 }
49
50 // Adds in a context called `caller` to the record (contains file name and line number like `foo.go:12`)
51 // Uses the `log15.CallerFuncHandler` to perform this task
52 func CallerFuncHandler(h LogHandler) LogHandler {
53         return CallerFuncHandler(h)
54 }
55
56 // Filters out records which match the key value pair
57 // Uses the `log15.MatchFilterHandler` to perform this task
58 func MatchHandler(key string, value interface{}, h LogHandler) LogHandler {
59         return MatchFilterHandler(key, value, h)
60 }
61
62 // MatchFilterHandler returns a Handler that only writes records
63 // to the wrapped Handler if the given key in the logged
64 // context matches the value. For example, to only log records
65 // from your ui package:
66 //
67 //    log.MatchFilterHandler("pkg", "app/ui", log.StdoutHandler)
68 //
69 func MatchFilterHandler(key string, value interface{}, h LogHandler) LogHandler {
70         return FilterHandler(func(r *Record) (pass bool) {
71                 return r.Context[key] == value
72         }, h)
73 }
74
75 // If match then A handler is called otherwise B handler is called
76 func MatchAbHandler(key string, value interface{}, a, b LogHandler) LogHandler {
77         return FuncHandler(func(r *Record) error {
78                 if r.Context[key] == value {
79                         return a.Log(r)
80                 } else if b != nil {
81                         return b.Log(r)
82                 }
83
84                 return nil
85         })
86 }
87
88 // The nil handler is used if logging for a specific request needs to be turned off
89 func NilHandler() LogHandler {
90         return FuncHandler(func(r *Record) error {
91                 return nil
92         })
93 }
94
95 // Match all values in map to log
96 func MatchMapHandler(matchMap map[string]interface{}, a LogHandler) LogHandler {
97         return matchMapHandler(matchMap, false, a)
98 }
99
100 // Match !(Match all values in map to log) The inverse of MatchMapHandler
101 func NotMatchMapHandler(matchMap map[string]interface{}, a LogHandler) LogHandler {
102         return matchMapHandler(matchMap, true, a)
103 }
104
105 // Rather then chaining multiple filter handlers, process all here
106 func matchMapHandler(matchMap map[string]interface{}, inverse bool, a LogHandler) LogHandler {
107         return FuncHandler(func(r *Record) error {
108                 matchCount := 0
109                 for k, v := range matchMap {
110                         value, found := r.Context[k]
111                         if !found {
112                                 return nil
113                         }
114                         // Test for two failure cases
115                         if value == v && inverse || value != v && !inverse {
116                                 return nil
117                         } else {
118                                 matchCount++
119                         }
120                 }
121                 if matchCount != len(matchMap) {
122                         return nil
123                 }
124                 return a.Log(r)
125         })
126 }
127
128 // Filters out records which do not match the key value pair
129 // Uses the `log15.FilterHandler` to perform this task
130 func NotMatchHandler(key string, value interface{}, h LogHandler) LogHandler {
131         return FilterHandler(func(r *Record) (pass bool) {
132                 return r.Context[key] != value
133         }, h)
134 }
135
136 func MultiHandler(hs ...LogHandler) LogHandler {
137         return FuncHandler(func(r *Record) error {
138                 for _, h := range hs {
139                         // what to do about failures?
140                         h.Log(r)
141                 }
142                 return nil
143         })
144 }
145
146 // StreamHandler writes log records to an io.Writer
147 // with the given format. StreamHandler can be used
148 // to easily begin writing log records to other
149 // outputs.
150 //
151 // StreamHandler wraps itself with LazyHandler and SyncHandler
152 // to evaluate Lazy objects and perform safe concurrent writes.
153 func StreamHandler(wr io.Writer, fmtr LogFormat) LogHandler {
154         h := FuncHandler(func(r *Record) error {
155                 _, err := wr.Write(fmtr.Format(r))
156                 return err
157         })
158         return LazyHandler(SyncHandler(h))
159 }
160
161 // Filter handler
162 func FilterHandler(fn func(r *Record) bool, h LogHandler) LogHandler {
163         return FuncHandler(func(r *Record) error {
164                 if fn(r) {
165                         return h.Log(r)
166                 }
167                 return nil
168         })
169 }
170
171 // List log handler handles a list of LogHandlers
172 type ListLogHandler struct {
173         handlers []LogHandler
174 }
175
176 // Create a new list of log handlers
177 func NewListLogHandler(h1, h2 LogHandler) *ListLogHandler {
178         ll := &ListLogHandler{handlers: []LogHandler{h1, h2}}
179         return ll
180 }
181
182 // Log the record
183 func (ll *ListLogHandler) Log(r *Record) (err error) {
184         for _, handler := range ll.handlers {
185                 if err == nil {
186                         err = handler.Log(r)
187                 } else {
188                         handler.Log(r)
189                 }
190         }
191         return
192 }
193
194 // Add another log handler
195 func (ll *ListLogHandler) Add(h LogHandler) {
196         if h != nil {
197                 ll.handlers = append(ll.handlers, h)
198         }
199 }
200
201 // Remove a log handler
202 func (ll *ListLogHandler) Del(h LogHandler) {
203         if h != nil {
204                 for i, handler := range ll.handlers {
205                         if handler == h {
206                                 ll.handlers = append(ll.handlers[:i], ll.handlers[i+1:]...)
207                         }
208                 }
209         }
210 }