diff options
Diffstat (limited to 'vendor/github.com/mattermost/logr/formatter.go')
-rw-r--r-- | vendor/github.com/mattermost/logr/formatter.go | 119 |
1 files changed, 119 insertions, 0 deletions
diff --git a/vendor/github.com/mattermost/logr/formatter.go b/vendor/github.com/mattermost/logr/formatter.go new file mode 100644 index 00000000..bb8df2d4 --- /dev/null +++ b/vendor/github.com/mattermost/logr/formatter.go @@ -0,0 +1,119 @@ +package logr + +import ( + "bytes" + "fmt" + "io" + "runtime" + "sort" +) + +// Formatter turns a LogRec into a formatted string. +type Formatter interface { + // Format converts a log record to bytes. If buf is not nil then it will be + // be filled with the formatted results, otherwise a new buffer will be allocated. + Format(rec *LogRec, stacktrace bool, buf *bytes.Buffer) (*bytes.Buffer, error) +} + +const ( + // DefTimestampFormat is the default time stamp format used by + // Plain formatter and others. + DefTimestampFormat = "2006-01-02 15:04:05.000 Z07:00" +) + +// DefaultFormatter is the default formatter, outputting only text with +// no colors and a space delimiter. Use `format.Plain` instead. +type DefaultFormatter struct { +} + +// Format converts a log record to bytes. +func (p *DefaultFormatter) Format(rec *LogRec, stacktrace bool, buf *bytes.Buffer) (*bytes.Buffer, error) { + if buf == nil { + buf = &bytes.Buffer{} + } + delim := " " + timestampFmt := DefTimestampFormat + + fmt.Fprintf(buf, "%s%s", rec.Time().Format(timestampFmt), delim) + fmt.Fprintf(buf, "%v%s", rec.Level(), delim) + fmt.Fprint(buf, rec.Msg(), delim) + + ctx := rec.Fields() + if len(ctx) > 0 { + WriteFields(buf, ctx, " ") + } + + if stacktrace { + frames := rec.StackFrames() + if len(frames) > 0 { + buf.WriteString("\n") + WriteStacktrace(buf, rec.StackFrames()) + } + } + buf.WriteString("\n") + + return buf, nil +} + +// WriteFields writes zero or more name value pairs to the io.Writer. +// The pairs are sorted by key name and output in key=value format +// with optional separator between fields. +func WriteFields(w io.Writer, flds Fields, separator string) { + keys := make([]string, 0, len(flds)) + for k := range flds { + keys = append(keys, k) + } + sort.Strings(keys) + sep := "" + for _, key := range keys { + writeField(w, key, flds[key], sep) + sep = separator + } +} + +func writeField(w io.Writer, key string, val interface{}, sep string) { + var template string + switch v := val.(type) { + case error: + val := v.Error() + if shouldQuote(val) { + template = "%s%s=%q" + } else { + template = "%s%s=%s" + } + case string: + if shouldQuote(v) { + template = "%s%s=%q" + } else { + template = "%s%s=%s" + } + default: + template = "%s%s=%v" + } + fmt.Fprintf(w, template, sep, key, val) +} + +// shouldQuote returns true if val contains any characters that might be unsafe +// when injecting log output into an aggregator, viewer or report. +func shouldQuote(val string) bool { + for _, c := range val { + if !((c >= '0' && c <= '9') || + (c >= 'a' && c <= 'z') || + (c >= 'A' && c <= 'Z')) { + return true + } + } + return false +} + +// WriteStacktrace formats and outputs a stack trace to an io.Writer. +func WriteStacktrace(w io.Writer, frames []runtime.Frame) { + for _, frame := range frames { + if frame.Function != "" { + fmt.Fprintf(w, " %s\n", frame.Function) + } + if frame.File != "" { + fmt.Fprintf(w, " %s:%d\n", frame.File, frame.Line) + } + } +} |