diff options
Diffstat (limited to 'vendor/github.com/hashicorp/go-hclog/int.go')
-rw-r--r-- | vendor/github.com/hashicorp/go-hclog/int.go | 385 |
1 files changed, 385 insertions, 0 deletions
diff --git a/vendor/github.com/hashicorp/go-hclog/int.go b/vendor/github.com/hashicorp/go-hclog/int.go new file mode 100644 index 0000000..9f90c28 --- /dev/null +++ b/vendor/github.com/hashicorp/go-hclog/int.go | |||
@@ -0,0 +1,385 @@ | |||
1 | package hclog | ||
2 | |||
3 | import ( | ||
4 | "bufio" | ||
5 | "encoding/json" | ||
6 | "fmt" | ||
7 | "log" | ||
8 | "os" | ||
9 | "runtime" | ||
10 | "strconv" | ||
11 | "strings" | ||
12 | "sync" | ||
13 | "time" | ||
14 | ) | ||
15 | |||
16 | var ( | ||
17 | _levelToBracket = map[Level]string{ | ||
18 | Debug: "[DEBUG]", | ||
19 | Trace: "[TRACE]", | ||
20 | Info: "[INFO ]", | ||
21 | Warn: "[WARN ]", | ||
22 | Error: "[ERROR]", | ||
23 | } | ||
24 | ) | ||
25 | |||
26 | // Given the options (nil for defaults), create a new Logger | ||
27 | func New(opts *LoggerOptions) Logger { | ||
28 | if opts == nil { | ||
29 | opts = &LoggerOptions{} | ||
30 | } | ||
31 | |||
32 | output := opts.Output | ||
33 | if output == nil { | ||
34 | output = os.Stderr | ||
35 | } | ||
36 | |||
37 | level := opts.Level | ||
38 | if level == NoLevel { | ||
39 | level = DefaultLevel | ||
40 | } | ||
41 | |||
42 | return &intLogger{ | ||
43 | m: new(sync.Mutex), | ||
44 | json: opts.JSONFormat, | ||
45 | caller: opts.IncludeLocation, | ||
46 | name: opts.Name, | ||
47 | w: bufio.NewWriter(output), | ||
48 | level: level, | ||
49 | } | ||
50 | } | ||
51 | |||
52 | // The internal logger implementation. Internal in that it is defined entirely | ||
53 | // by this package. | ||
54 | type intLogger struct { | ||
55 | json bool | ||
56 | caller bool | ||
57 | name string | ||
58 | |||
59 | // this is a pointer so that it's shared by any derived loggers, since | ||
60 | // those derived loggers share the bufio.Writer as well. | ||
61 | m *sync.Mutex | ||
62 | w *bufio.Writer | ||
63 | level Level | ||
64 | |||
65 | implied []interface{} | ||
66 | } | ||
67 | |||
68 | // Make sure that intLogger is a Logger | ||
69 | var _ Logger = &intLogger{} | ||
70 | |||
71 | // The time format to use for logging. This is a version of RFC3339 that | ||
72 | // contains millisecond precision | ||
73 | const TimeFormat = "2006-01-02T15:04:05.000Z0700" | ||
74 | |||
75 | // Log a message and a set of key/value pairs if the given level is at | ||
76 | // or more severe that the threshold configured in the Logger. | ||
77 | func (z *intLogger) Log(level Level, msg string, args ...interface{}) { | ||
78 | if level < z.level { | ||
79 | return | ||
80 | } | ||
81 | |||
82 | t := time.Now() | ||
83 | |||
84 | z.m.Lock() | ||
85 | defer z.m.Unlock() | ||
86 | |||
87 | if z.json { | ||
88 | z.logJson(t, level, msg, args...) | ||
89 | } else { | ||
90 | z.log(t, level, msg, args...) | ||
91 | } | ||
92 | |||
93 | z.w.Flush() | ||
94 | } | ||
95 | |||
96 | // Cleanup a path by returning the last 2 segments of the path only. | ||
97 | func trimCallerPath(path string) string { | ||
98 | // lovely borrowed from zap | ||
99 | // nb. To make sure we trim the path correctly on Windows too, we | ||
100 | // counter-intuitively need to use '/' and *not* os.PathSeparator here, | ||
101 | // because the path given originates from Go stdlib, specifically | ||
102 | // runtime.Caller() which (as of Mar/17) returns forward slashes even on | ||
103 | // Windows. | ||
104 | // | ||
105 | // See https://github.com/golang/go/issues/3335 | ||
106 | // and https://github.com/golang/go/issues/18151 | ||
107 | // | ||
108 | // for discussion on the issue on Go side. | ||
109 | // | ||
110 | |||
111 | // Find the last separator. | ||
112 | // | ||
113 | idx := strings.LastIndexByte(path, '/') | ||
114 | if idx == -1 { | ||
115 | return path | ||
116 | } | ||
117 | |||
118 | // Find the penultimate separator. | ||
119 | idx = strings.LastIndexByte(path[:idx], '/') | ||
120 | if idx == -1 { | ||
121 | return path | ||
122 | } | ||
123 | |||
124 | return path[idx+1:] | ||
125 | } | ||
126 | |||
127 | // Non-JSON logging format function | ||
128 | func (z *intLogger) log(t time.Time, level Level, msg string, args ...interface{}) { | ||
129 | z.w.WriteString(t.Format(TimeFormat)) | ||
130 | z.w.WriteByte(' ') | ||
131 | |||
132 | s, ok := _levelToBracket[level] | ||
133 | if ok { | ||
134 | z.w.WriteString(s) | ||
135 | } else { | ||
136 | z.w.WriteString("[UNKN ]") | ||
137 | } | ||
138 | |||
139 | if z.caller { | ||
140 | if _, file, line, ok := runtime.Caller(3); ok { | ||
141 | z.w.WriteByte(' ') | ||
142 | z.w.WriteString(trimCallerPath(file)) | ||
143 | z.w.WriteByte(':') | ||
144 | z.w.WriteString(strconv.Itoa(line)) | ||
145 | z.w.WriteByte(':') | ||
146 | } | ||
147 | } | ||
148 | |||
149 | z.w.WriteByte(' ') | ||
150 | |||
151 | if z.name != "" { | ||
152 | z.w.WriteString(z.name) | ||
153 | z.w.WriteString(": ") | ||
154 | } | ||
155 | |||
156 | z.w.WriteString(msg) | ||
157 | |||
158 | args = append(z.implied, args...) | ||
159 | |||
160 | var stacktrace CapturedStacktrace | ||
161 | |||
162 | if args != nil && len(args) > 0 { | ||
163 | if len(args)%2 != 0 { | ||
164 | cs, ok := args[len(args)-1].(CapturedStacktrace) | ||
165 | if ok { | ||
166 | args = args[:len(args)-1] | ||
167 | stacktrace = cs | ||
168 | } else { | ||
169 | args = append(args, "<unknown>") | ||
170 | } | ||
171 | } | ||
172 | |||
173 | z.w.WriteByte(':') | ||
174 | |||
175 | FOR: | ||
176 | for i := 0; i < len(args); i = i + 2 { | ||
177 | var val string | ||
178 | |||
179 | switch st := args[i+1].(type) { | ||
180 | case string: | ||
181 | val = st | ||
182 | case int: | ||
183 | val = strconv.FormatInt(int64(st), 10) | ||
184 | case int64: | ||
185 | val = strconv.FormatInt(int64(st), 10) | ||
186 | case int32: | ||
187 | val = strconv.FormatInt(int64(st), 10) | ||
188 | case int16: | ||
189 | val = strconv.FormatInt(int64(st), 10) | ||
190 | case int8: | ||
191 | val = strconv.FormatInt(int64(st), 10) | ||
192 | case uint: | ||
193 | val = strconv.FormatUint(uint64(st), 10) | ||
194 | case uint64: | ||
195 | val = strconv.FormatUint(uint64(st), 10) | ||
196 | case uint32: | ||
197 | val = strconv.FormatUint(uint64(st), 10) | ||
198 | case uint16: | ||
199 | val = strconv.FormatUint(uint64(st), 10) | ||
200 | case uint8: | ||
201 | val = strconv.FormatUint(uint64(st), 10) | ||
202 | case CapturedStacktrace: | ||
203 | stacktrace = st | ||
204 | continue FOR | ||
205 | default: | ||
206 | val = fmt.Sprintf("%v", st) | ||
207 | } | ||
208 | |||
209 | z.w.WriteByte(' ') | ||
210 | z.w.WriteString(args[i].(string)) | ||
211 | z.w.WriteByte('=') | ||
212 | |||
213 | if strings.ContainsAny(val, " \t\n\r") { | ||
214 | z.w.WriteByte('"') | ||
215 | z.w.WriteString(val) | ||
216 | z.w.WriteByte('"') | ||
217 | } else { | ||
218 | z.w.WriteString(val) | ||
219 | } | ||
220 | } | ||
221 | } | ||
222 | |||
223 | z.w.WriteString("\n") | ||
224 | |||
225 | if stacktrace != "" { | ||
226 | z.w.WriteString(string(stacktrace)) | ||
227 | } | ||
228 | } | ||
229 | |||
230 | // JSON logging function | ||
231 | func (z *intLogger) logJson(t time.Time, level Level, msg string, args ...interface{}) { | ||
232 | vals := map[string]interface{}{ | ||
233 | "@message": msg, | ||
234 | "@timestamp": t.Format("2006-01-02T15:04:05.000000Z07:00"), | ||
235 | } | ||
236 | |||
237 | var levelStr string | ||
238 | switch level { | ||
239 | case Error: | ||
240 | levelStr = "error" | ||
241 | case Warn: | ||
242 | levelStr = "warn" | ||
243 | case Info: | ||
244 | levelStr = "info" | ||
245 | case Debug: | ||
246 | levelStr = "debug" | ||
247 | case Trace: | ||
248 | levelStr = "trace" | ||
249 | default: | ||
250 | levelStr = "all" | ||
251 | } | ||
252 | |||
253 | vals["@level"] = levelStr | ||
254 | |||
255 | if z.name != "" { | ||
256 | vals["@module"] = z.name | ||
257 | } | ||
258 | |||
259 | if z.caller { | ||
260 | if _, file, line, ok := runtime.Caller(3); ok { | ||
261 | vals["@caller"] = fmt.Sprintf("%s:%d", file, line) | ||
262 | } | ||
263 | } | ||
264 | |||
265 | if args != nil && len(args) > 0 { | ||
266 | if len(args)%2 != 0 { | ||
267 | cs, ok := args[len(args)-1].(CapturedStacktrace) | ||
268 | if ok { | ||
269 | args = args[:len(args)-1] | ||
270 | vals["stacktrace"] = cs | ||
271 | } else { | ||
272 | args = append(args, "<unknown>") | ||
273 | } | ||
274 | } | ||
275 | |||
276 | for i := 0; i < len(args); i = i + 2 { | ||
277 | if _, ok := args[i].(string); !ok { | ||
278 | // As this is the logging function not much we can do here | ||
279 | // without injecting into logs... | ||
280 | continue | ||
281 | } | ||
282 | vals[args[i].(string)] = args[i+1] | ||
283 | } | ||
284 | } | ||
285 | |||
286 | err := json.NewEncoder(z.w).Encode(vals) | ||
287 | if err != nil { | ||
288 | panic(err) | ||
289 | } | ||
290 | } | ||
291 | |||
292 | // Emit the message and args at DEBUG level | ||
293 | func (z *intLogger) Debug(msg string, args ...interface{}) { | ||
294 | z.Log(Debug, msg, args...) | ||
295 | } | ||
296 | |||
297 | // Emit the message and args at TRACE level | ||
298 | func (z *intLogger) Trace(msg string, args ...interface{}) { | ||
299 | z.Log(Trace, msg, args...) | ||
300 | } | ||
301 | |||
302 | // Emit the message and args at INFO level | ||
303 | func (z *intLogger) Info(msg string, args ...interface{}) { | ||
304 | z.Log(Info, msg, args...) | ||
305 | } | ||
306 | |||
307 | // Emit the message and args at WARN level | ||
308 | func (z *intLogger) Warn(msg string, args ...interface{}) { | ||
309 | z.Log(Warn, msg, args...) | ||
310 | } | ||
311 | |||
312 | // Emit the message and args at ERROR level | ||
313 | func (z *intLogger) Error(msg string, args ...interface{}) { | ||
314 | z.Log(Error, msg, args...) | ||
315 | } | ||
316 | |||
317 | // Indicate that the logger would emit TRACE level logs | ||
318 | func (z *intLogger) IsTrace() bool { | ||
319 | return z.level == Trace | ||
320 | } | ||
321 | |||
322 | // Indicate that the logger would emit DEBUG level logs | ||
323 | func (z *intLogger) IsDebug() bool { | ||
324 | return z.level <= Debug | ||
325 | } | ||
326 | |||
327 | // Indicate that the logger would emit INFO level logs | ||
328 | func (z *intLogger) IsInfo() bool { | ||
329 | return z.level <= Info | ||
330 | } | ||
331 | |||
332 | // Indicate that the logger would emit WARN level logs | ||
333 | func (z *intLogger) IsWarn() bool { | ||
334 | return z.level <= Warn | ||
335 | } | ||
336 | |||
337 | // Indicate that the logger would emit ERROR level logs | ||
338 | func (z *intLogger) IsError() bool { | ||
339 | return z.level <= Error | ||
340 | } | ||
341 | |||
342 | // Return a sub-Logger for which every emitted log message will contain | ||
343 | // the given key/value pairs. This is used to create a context specific | ||
344 | // Logger. | ||
345 | func (z *intLogger) With(args ...interface{}) Logger { | ||
346 | var nz intLogger = *z | ||
347 | |||
348 | nz.implied = append(nz.implied, args...) | ||
349 | |||
350 | return &nz | ||
351 | } | ||
352 | |||
353 | // Create a new sub-Logger that a name decending from the current name. | ||
354 | // This is used to create a subsystem specific Logger. | ||
355 | func (z *intLogger) Named(name string) Logger { | ||
356 | var nz intLogger = *z | ||
357 | |||
358 | if nz.name != "" { | ||
359 | nz.name = nz.name + "." + name | ||
360 | } | ||
361 | |||
362 | return &nz | ||
363 | } | ||
364 | |||
365 | // Create a new sub-Logger with an explicit name. This ignores the current | ||
366 | // name. This is used to create a standalone logger that doesn't fall | ||
367 | // within the normal hierarchy. | ||
368 | func (z *intLogger) ResetNamed(name string) Logger { | ||
369 | var nz intLogger = *z | ||
370 | |||
371 | nz.name = name | ||
372 | |||
373 | return &nz | ||
374 | } | ||
375 | |||
376 | // Create a *log.Logger that will send it's data through this Logger. This | ||
377 | // allows packages that expect to be using the standard library log to actually | ||
378 | // use this logger. | ||
379 | func (z *intLogger) StandardLogger(opts *StandardLoggerOptions) *log.Logger { | ||
380 | if opts == nil { | ||
381 | opts = &StandardLoggerOptions{} | ||
382 | } | ||
383 | |||
384 | return log.New(&stdlogAdapter{z, opts.InferLevels}, "", 0) | ||
385 | } | ||