diff options
Diffstat (limited to 'vendor/github.com/hashicorp/go-hclog')
-rw-r--r-- | vendor/github.com/hashicorp/go-hclog/LICENSE | 21 | ||||
-rw-r--r-- | vendor/github.com/hashicorp/go-hclog/README.md | 123 | ||||
-rw-r--r-- | vendor/github.com/hashicorp/go-hclog/global.go | 34 | ||||
-rw-r--r-- | vendor/github.com/hashicorp/go-hclog/int.go | 385 | ||||
-rw-r--r-- | vendor/github.com/hashicorp/go-hclog/log.go | 138 | ||||
-rw-r--r-- | vendor/github.com/hashicorp/go-hclog/stacktrace.go | 108 | ||||
-rw-r--r-- | vendor/github.com/hashicorp/go-hclog/stdlog.go | 62 |
7 files changed, 871 insertions, 0 deletions
diff --git a/vendor/github.com/hashicorp/go-hclog/LICENSE b/vendor/github.com/hashicorp/go-hclog/LICENSE new file mode 100644 index 0000000..abaf1e4 --- /dev/null +++ b/vendor/github.com/hashicorp/go-hclog/LICENSE | |||
@@ -0,0 +1,21 @@ | |||
1 | MIT License | ||
2 | |||
3 | Copyright (c) 2017 HashiCorp | ||
4 | |||
5 | Permission is hereby granted, free of charge, to any person obtaining a copy | ||
6 | of this software and associated documentation files (the "Software"), to deal | ||
7 | in the Software without restriction, including without limitation the rights | ||
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
9 | copies of the Software, and to permit persons to whom the Software is | ||
10 | furnished to do so, subject to the following conditions: | ||
11 | |||
12 | The above copyright notice and this permission notice shall be included in all | ||
13 | copies or substantial portions of the Software. | ||
14 | |||
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
21 | SOFTWARE. | ||
diff --git a/vendor/github.com/hashicorp/go-hclog/README.md b/vendor/github.com/hashicorp/go-hclog/README.md new file mode 100644 index 0000000..614342b --- /dev/null +++ b/vendor/github.com/hashicorp/go-hclog/README.md | |||
@@ -0,0 +1,123 @@ | |||
1 | # go-hclog | ||
2 | |||
3 | [![Go Documentation](http://img.shields.io/badge/go-documentation-blue.svg?style=flat-square)][godocs] | ||
4 | |||
5 | [godocs]: https://godoc.org/github.com/hashicorp/go-hclog | ||
6 | |||
7 | `go-hclog` is a package for Go that provides a simple key/value logging | ||
8 | interface for use in development and production environments. | ||
9 | |||
10 | It provides logging levels that provide decreased output based upon the | ||
11 | desired amount of output, unlike the standard library `log` package. | ||
12 | |||
13 | It does not provide `Printf` style logging, only key/value logging that is | ||
14 | exposed as arguments to the logging functions for simplicity. | ||
15 | |||
16 | It provides a human readable output mode for use in development as well as | ||
17 | JSON output mode for production. | ||
18 | |||
19 | ## Stability Note | ||
20 | |||
21 | While this library is fully open source and HashiCorp will be maintaining it | ||
22 | (since we are and will be making extensive use of it), the API and output | ||
23 | format is subject to minor changes as we fully bake and vet it in our projects. | ||
24 | This notice will be removed once it's fully integrated into our major projects | ||
25 | and no further changes are anticipated. | ||
26 | |||
27 | ## Installation and Docs | ||
28 | |||
29 | Install using `go get github.com/hashicorp/go-hclog`. | ||
30 | |||
31 | Full documentation is available at | ||
32 | http://godoc.org/github.com/hashicorp/go-hclog | ||
33 | |||
34 | ## Usage | ||
35 | |||
36 | ### Use the global logger | ||
37 | |||
38 | ```go | ||
39 | hclog.Default().Info("hello world") | ||
40 | ``` | ||
41 | |||
42 | ```text | ||
43 | 2017-07-05T16:15:55.167-0700 [INFO ] hello world | ||
44 | ``` | ||
45 | |||
46 | (Note timestamps are removed in future examples for brevity.) | ||
47 | |||
48 | ### Create a new logger | ||
49 | |||
50 | ```go | ||
51 | appLogger := hclog.New(&hclog.LoggerOptions{ | ||
52 | Name: "my-app", | ||
53 | Level: hclog.LevelFromString("DEBUG"), | ||
54 | }) | ||
55 | ``` | ||
56 | |||
57 | ### Emit an Info level message with 2 key/value pairs | ||
58 | |||
59 | ```go | ||
60 | input := "5.5" | ||
61 | _, err := strconv.ParseInt(input, 10, 32) | ||
62 | if err != nil { | ||
63 | appLogger.Info("Invalid input for ParseInt", "input", input, "error", err) | ||
64 | } | ||
65 | ``` | ||
66 | |||
67 | ```text | ||
68 | ... [INFO ] my-app: Invalid input for ParseInt: input=5.5 error="strconv.ParseInt: parsing "5.5": invalid syntax" | ||
69 | ``` | ||
70 | |||
71 | ### Create a new Logger for a major subsystem | ||
72 | |||
73 | ```go | ||
74 | subsystemLogger := appLogger.Named("transport") | ||
75 | subsystemLogger.Info("we are transporting something") | ||
76 | ``` | ||
77 | |||
78 | ```text | ||
79 | ... [INFO ] my-app.transport: we are transporting something | ||
80 | ``` | ||
81 | |||
82 | Notice that logs emitted by `subsystemLogger` contain `my-app.transport`, | ||
83 | reflecting both the application and subsystem names. | ||
84 | |||
85 | ### Create a new Logger with fixed key/value pairs | ||
86 | |||
87 | Using `With()` will include a specific key-value pair in all messages emitted | ||
88 | by that logger. | ||
89 | |||
90 | ```go | ||
91 | requestID := "5fb446b6-6eba-821d-df1b-cd7501b6a363" | ||
92 | requestLogger := subsystemLogger.With("request", requestID) | ||
93 | requestLogger.Info("we are transporting a request") | ||
94 | ``` | ||
95 | |||
96 | ```text | ||
97 | ... [INFO ] my-app.transport: we are transporting a request: request=5fb446b6-6eba-821d-df1b-cd7501b6a363 | ||
98 | ``` | ||
99 | |||
100 | This allows sub Loggers to be context specific without having to thread that | ||
101 | into all the callers. | ||
102 | |||
103 | ### Use this with code that uses the standard library logger | ||
104 | |||
105 | If you want to use the standard library's `log.Logger` interface you can wrap | ||
106 | `hclog.Logger` by calling the `StandardLogger()` method. This allows you to use | ||
107 | it with the familiar `Println()`, `Printf()`, etc. For example: | ||
108 | |||
109 | ```go | ||
110 | stdLogger := appLogger.StandardLogger(&hclog.StandardLoggerOptions{ | ||
111 | InferLevels: true, | ||
112 | }) | ||
113 | // Printf() is provided by stdlib log.Logger interface, not hclog.Logger | ||
114 | stdLogger.Printf("[DEBUG] %+v", stdLogger) | ||
115 | ``` | ||
116 | |||
117 | ```text | ||
118 | ... [DEBUG] my-app: &{mu:{state:0 sema:0} prefix: flag:0 out:0xc42000a0a0 buf:[]} | ||
119 | ``` | ||
120 | |||
121 | Notice that if `appLogger` is initialized with the `INFO` log level _and_ you | ||
122 | specify `InferLevels: true`, you will not see any output here. You must change | ||
123 | `appLogger` to `DEBUG` to see output. See the docs for more information. | ||
diff --git a/vendor/github.com/hashicorp/go-hclog/global.go b/vendor/github.com/hashicorp/go-hclog/global.go new file mode 100644 index 0000000..55ce439 --- /dev/null +++ b/vendor/github.com/hashicorp/go-hclog/global.go | |||
@@ -0,0 +1,34 @@ | |||
1 | package hclog | ||
2 | |||
3 | import ( | ||
4 | "sync" | ||
5 | ) | ||
6 | |||
7 | var ( | ||
8 | protect sync.Once | ||
9 | def Logger | ||
10 | |||
11 | // The options used to create the Default logger. These are | ||
12 | // read only when the Default logger is created, so set them | ||
13 | // as soon as the process starts. | ||
14 | DefaultOptions = &LoggerOptions{ | ||
15 | Level: DefaultLevel, | ||
16 | Output: DefaultOutput, | ||
17 | } | ||
18 | ) | ||
19 | |||
20 | // Return a logger that is held globally. This can be a good starting | ||
21 | // place, and then you can use .With() and .Name() to create sub-loggers | ||
22 | // to be used in more specific contexts. | ||
23 | func Default() Logger { | ||
24 | protect.Do(func() { | ||
25 | def = New(DefaultOptions) | ||
26 | }) | ||
27 | |||
28 | return def | ||
29 | } | ||
30 | |||
31 | // A short alias for Default() | ||
32 | func L() Logger { | ||
33 | return Default() | ||
34 | } | ||
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 | } | ||
diff --git a/vendor/github.com/hashicorp/go-hclog/log.go b/vendor/github.com/hashicorp/go-hclog/log.go new file mode 100644 index 0000000..6bb16ba --- /dev/null +++ b/vendor/github.com/hashicorp/go-hclog/log.go | |||
@@ -0,0 +1,138 @@ | |||
1 | package hclog | ||
2 | |||
3 | import ( | ||
4 | "io" | ||
5 | "log" | ||
6 | "os" | ||
7 | "strings" | ||
8 | ) | ||
9 | |||
10 | var ( | ||
11 | DefaultOutput = os.Stderr | ||
12 | DefaultLevel = Info | ||
13 | ) | ||
14 | |||
15 | type Level int | ||
16 | |||
17 | const ( | ||
18 | // This is a special level used to indicate that no level has been | ||
19 | // set and allow for a default to be used. | ||
20 | NoLevel Level = 0 | ||
21 | |||
22 | // The most verbose level. Intended to be used for the tracing of actions | ||
23 | // in code, such as function enters/exits, etc. | ||
24 | Trace Level = 1 | ||
25 | |||
26 | // For programmer lowlevel analysis. | ||
27 | Debug Level = 2 | ||
28 | |||
29 | // For information about steady state operations. | ||
30 | Info Level = 3 | ||
31 | |||
32 | // For information about rare but handled events. | ||
33 | Warn Level = 4 | ||
34 | |||
35 | // For information about unrecoverable events. | ||
36 | Error Level = 5 | ||
37 | ) | ||
38 | |||
39 | // LevelFromString returns a Level type for the named log level, or "NoLevel" if | ||
40 | // the level string is invalid. This facilitates setting the log level via | ||
41 | // config or environment variable by name in a predictable way. | ||
42 | func LevelFromString(levelStr string) Level { | ||
43 | // We don't care about case. Accept "INFO" or "info" | ||
44 | levelStr = strings.ToLower(strings.TrimSpace(levelStr)) | ||
45 | switch levelStr { | ||
46 | case "trace": | ||
47 | return Trace | ||
48 | case "debug": | ||
49 | return Debug | ||
50 | case "info": | ||
51 | return Info | ||
52 | case "warn": | ||
53 | return Warn | ||
54 | case "error": | ||
55 | return Error | ||
56 | default: | ||
57 | return NoLevel | ||
58 | } | ||
59 | } | ||
60 | |||
61 | // The main Logger interface. All code should code against this interface only. | ||
62 | type Logger interface { | ||
63 | // Args are alternating key, val pairs | ||
64 | // keys must be strings | ||
65 | // vals can be any type, but display is implementation specific | ||
66 | // Emit a message and key/value pairs at the TRACE level | ||
67 | Trace(msg string, args ...interface{}) | ||
68 | |||
69 | // Emit a message and key/value pairs at the DEBUG level | ||
70 | Debug(msg string, args ...interface{}) | ||
71 | |||
72 | // Emit a message and key/value pairs at the INFO level | ||
73 | Info(msg string, args ...interface{}) | ||
74 | |||
75 | // Emit a message and key/value pairs at the WARN level | ||
76 | Warn(msg string, args ...interface{}) | ||
77 | |||
78 | // Emit a message and key/value pairs at the ERROR level | ||
79 | Error(msg string, args ...interface{}) | ||
80 | |||
81 | // Indicate if TRACE logs would be emitted. This and the other Is* guards | ||
82 | // are used to elide expensive logging code based on the current level. | ||
83 | IsTrace() bool | ||
84 | |||
85 | // Indicate if DEBUG logs would be emitted. This and the other Is* guards | ||
86 | IsDebug() bool | ||
87 | |||
88 | // Indicate if INFO logs would be emitted. This and the other Is* guards | ||
89 | IsInfo() bool | ||
90 | |||
91 | // Indicate if WARN logs would be emitted. This and the other Is* guards | ||
92 | IsWarn() bool | ||
93 | |||
94 | // Indicate if ERROR logs would be emitted. This and the other Is* guards | ||
95 | IsError() bool | ||
96 | |||
97 | // Creates a sublogger that will always have the given key/value pairs | ||
98 | With(args ...interface{}) Logger | ||
99 | |||
100 | // Create a logger that will prepend the name string on the front of all messages. | ||
101 | // If the logger already has a name, the new value will be appended to the current | ||
102 | // name. That way, a major subsystem can use this to decorate all it's own logs | ||
103 | // without losing context. | ||
104 | Named(name string) Logger | ||
105 | |||
106 | // Create a logger that will prepend the name string on the front of all messages. | ||
107 | // This sets the name of the logger to the value directly, unlike Named which honor | ||
108 | // the current name as well. | ||
109 | ResetNamed(name string) Logger | ||
110 | |||
111 | // Return a value that conforms to the stdlib log.Logger interface | ||
112 | StandardLogger(opts *StandardLoggerOptions) *log.Logger | ||
113 | } | ||
114 | |||
115 | type StandardLoggerOptions struct { | ||
116 | // Indicate that some minimal parsing should be done on strings to try | ||
117 | // and detect their level and re-emit them. | ||
118 | // This supports the strings like [ERROR], [ERR] [TRACE], [WARN], [INFO], | ||
119 | // [DEBUG] and strip it off before reapplying it. | ||
120 | InferLevels bool | ||
121 | } | ||
122 | |||
123 | type LoggerOptions struct { | ||
124 | // Name of the subsystem to prefix logs with | ||
125 | Name string | ||
126 | |||
127 | // The threshold for the logger. Anything less severe is supressed | ||
128 | Level Level | ||
129 | |||
130 | // Where to write the logs to. Defaults to os.Stdout if nil | ||
131 | Output io.Writer | ||
132 | |||
133 | // Control if the output should be in JSON. | ||
134 | JSONFormat bool | ||
135 | |||
136 | // Intclude file and line information in each log line | ||
137 | IncludeLocation bool | ||
138 | } | ||
diff --git a/vendor/github.com/hashicorp/go-hclog/stacktrace.go b/vendor/github.com/hashicorp/go-hclog/stacktrace.go new file mode 100644 index 0000000..8af1a3b --- /dev/null +++ b/vendor/github.com/hashicorp/go-hclog/stacktrace.go | |||
@@ -0,0 +1,108 @@ | |||
1 | // Copyright (c) 2016 Uber Technologies, Inc. | ||
2 | // | ||
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy | ||
4 | // of this software and associated documentation files (the "Software"), to deal | ||
5 | // in the Software without restriction, including without limitation the rights | ||
6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
7 | // copies of the Software, and to permit persons to whom the Software is | ||
8 | // furnished to do so, subject to the following conditions: | ||
9 | // | ||
10 | // The above copyright notice and this permission notice shall be included in | ||
11 | // all copies or substantial portions of the Software. | ||
12 | // | ||
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
19 | // THE SOFTWARE. | ||
20 | |||
21 | package hclog | ||
22 | |||
23 | import ( | ||
24 | "bytes" | ||
25 | "runtime" | ||
26 | "strconv" | ||
27 | "strings" | ||
28 | "sync" | ||
29 | ) | ||
30 | |||
31 | var ( | ||
32 | _stacktraceIgnorePrefixes = []string{ | ||
33 | "runtime.goexit", | ||
34 | "runtime.main", | ||
35 | } | ||
36 | _stacktracePool = sync.Pool{ | ||
37 | New: func() interface{} { | ||
38 | return newProgramCounters(64) | ||
39 | }, | ||
40 | } | ||
41 | ) | ||
42 | |||
43 | // A stacktrace gathered by a previous call to log.Stacktrace. If passed | ||
44 | // to a logging function, the stacktrace will be appended. | ||
45 | type CapturedStacktrace string | ||
46 | |||
47 | // Gather a stacktrace of the current goroutine and return it to be passed | ||
48 | // to a logging function. | ||
49 | func Stacktrace() CapturedStacktrace { | ||
50 | return CapturedStacktrace(takeStacktrace()) | ||
51 | } | ||
52 | |||
53 | func takeStacktrace() string { | ||
54 | programCounters := _stacktracePool.Get().(*programCounters) | ||
55 | defer _stacktracePool.Put(programCounters) | ||
56 | |||
57 | var buffer bytes.Buffer | ||
58 | |||
59 | for { | ||
60 | // Skip the call to runtime.Counters and takeStacktrace so that the | ||
61 | // program counters start at the caller of takeStacktrace. | ||
62 | n := runtime.Callers(2, programCounters.pcs) | ||
63 | if n < cap(programCounters.pcs) { | ||
64 | programCounters.pcs = programCounters.pcs[:n] | ||
65 | break | ||
66 | } | ||
67 | // Don't put the too-short counter slice back into the pool; this lets | ||
68 | // the pool adjust if we consistently take deep stacktraces. | ||
69 | programCounters = newProgramCounters(len(programCounters.pcs) * 2) | ||
70 | } | ||
71 | |||
72 | i := 0 | ||
73 | frames := runtime.CallersFrames(programCounters.pcs) | ||
74 | for frame, more := frames.Next(); more; frame, more = frames.Next() { | ||
75 | if shouldIgnoreStacktraceFunction(frame.Function) { | ||
76 | continue | ||
77 | } | ||
78 | if i != 0 { | ||
79 | buffer.WriteByte('\n') | ||
80 | } | ||
81 | i++ | ||
82 | buffer.WriteString(frame.Function) | ||
83 | buffer.WriteByte('\n') | ||
84 | buffer.WriteByte('\t') | ||
85 | buffer.WriteString(frame.File) | ||
86 | buffer.WriteByte(':') | ||
87 | buffer.WriteString(strconv.Itoa(int(frame.Line))) | ||
88 | } | ||
89 | |||
90 | return buffer.String() | ||
91 | } | ||
92 | |||
93 | func shouldIgnoreStacktraceFunction(function string) bool { | ||
94 | for _, prefix := range _stacktraceIgnorePrefixes { | ||
95 | if strings.HasPrefix(function, prefix) { | ||
96 | return true | ||
97 | } | ||
98 | } | ||
99 | return false | ||
100 | } | ||
101 | |||
102 | type programCounters struct { | ||
103 | pcs []uintptr | ||
104 | } | ||
105 | |||
106 | func newProgramCounters(size int) *programCounters { | ||
107 | return &programCounters{make([]uintptr, size)} | ||
108 | } | ||
diff --git a/vendor/github.com/hashicorp/go-hclog/stdlog.go b/vendor/github.com/hashicorp/go-hclog/stdlog.go new file mode 100644 index 0000000..2bb927f --- /dev/null +++ b/vendor/github.com/hashicorp/go-hclog/stdlog.go | |||
@@ -0,0 +1,62 @@ | |||
1 | package hclog | ||
2 | |||
3 | import ( | ||
4 | "bytes" | ||
5 | "strings" | ||
6 | ) | ||
7 | |||
8 | // Provides a io.Writer to shim the data out of *log.Logger | ||
9 | // and back into our Logger. This is basically the only way to | ||
10 | // build upon *log.Logger. | ||
11 | type stdlogAdapter struct { | ||
12 | hl Logger | ||
13 | inferLevels bool | ||
14 | } | ||
15 | |||
16 | // Take the data, infer the levels if configured, and send it through | ||
17 | // a regular Logger | ||
18 | func (s *stdlogAdapter) Write(data []byte) (int, error) { | ||
19 | str := string(bytes.TrimRight(data, " \t\n")) | ||
20 | |||
21 | if s.inferLevels { | ||
22 | level, str := s.pickLevel(str) | ||
23 | switch level { | ||
24 | case Trace: | ||
25 | s.hl.Trace(str) | ||
26 | case Debug: | ||
27 | s.hl.Debug(str) | ||
28 | case Info: | ||
29 | s.hl.Info(str) | ||
30 | case Warn: | ||
31 | s.hl.Warn(str) | ||
32 | case Error: | ||
33 | s.hl.Error(str) | ||
34 | default: | ||
35 | s.hl.Info(str) | ||
36 | } | ||
37 | } else { | ||
38 | s.hl.Info(str) | ||
39 | } | ||
40 | |||
41 | return len(data), nil | ||
42 | } | ||
43 | |||
44 | // Detect, based on conventions, what log level this is | ||
45 | func (s *stdlogAdapter) pickLevel(str string) (Level, string) { | ||
46 | switch { | ||
47 | case strings.HasPrefix(str, "[DEBUG]"): | ||
48 | return Debug, strings.TrimSpace(str[7:]) | ||
49 | case strings.HasPrefix(str, "[TRACE]"): | ||
50 | return Trace, strings.TrimSpace(str[7:]) | ||
51 | case strings.HasPrefix(str, "[INFO]"): | ||
52 | return Info, strings.TrimSpace(str[6:]) | ||
53 | case strings.HasPrefix(str, "[WARN]"): | ||
54 | return Warn, strings.TrimSpace(str[7:]) | ||
55 | case strings.HasPrefix(str, "[ERROR]"): | ||
56 | return Error, strings.TrimSpace(str[7:]) | ||
57 | case strings.HasPrefix(str, "[ERR]"): | ||
58 | return Error, strings.TrimSpace(str[5:]) | ||
59 | default: | ||
60 | return Info, str | ||
61 | } | ||
62 | } | ||