summaryrefslogtreecommitdiffstats
path: root/vendor/github.com/mattermost/logr/v2/formatter.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/mattermost/logr/v2/formatter.go')
-rw-r--r--vendor/github.com/mattermost/logr/v2/formatter.go184
1 files changed, 184 insertions, 0 deletions
diff --git a/vendor/github.com/mattermost/logr/v2/formatter.go b/vendor/github.com/mattermost/logr/v2/formatter.go
new file mode 100644
index 00000000..c8bb9b70
--- /dev/null
+++ b/vendor/github.com/mattermost/logr/v2/formatter.go
@@ -0,0 +1,184 @@
+package logr
+
+import (
+ "bytes"
+ "io"
+ "runtime"
+ "strconv"
+)
+
+// Formatter turns a LogRec into a formatted string.
+type Formatter interface {
+ // IsStacktraceNeeded returns true if this formatter requires a stacktrace to be
+ // generated for each LogRecord. Enabling features such as `Caller` field require
+ // a stacktrace.
+ IsStacktraceNeeded() bool
+
+ // 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, level Level, 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"
+
+ // TimestampMillisFormat is the format for logging milliseconds UTC
+ TimestampMillisFormat = "Jan _2 15:04:05.000"
+)
+
+type Writer struct {
+ io.Writer
+}
+
+func (w Writer) Writes(elems ...[]byte) (int, error) {
+ var count int
+ for _, e := range elems {
+ if c, err := w.Write(e); err != nil {
+ return count + c, err
+ } else {
+ count += c
+ }
+ }
+ return count, nil
+}
+
+// DefaultFormatter is the default formatter, outputting only text with
+// no colors and a space delimiter. Use `format.Plain` instead.
+type DefaultFormatter struct {
+}
+
+// IsStacktraceNeeded always returns false for default formatter since the
+// `Caller` field is not supported.
+func (p *DefaultFormatter) IsStacktraceNeeded() bool {
+ return false
+}
+
+// Format converts a log record to bytes.
+func (p *DefaultFormatter) Format(rec *LogRec, level Level, buf *bytes.Buffer) (*bytes.Buffer, error) {
+ if buf == nil {
+ buf = &bytes.Buffer{}
+ }
+ timestampFmt := DefTimestampFormat
+
+ buf.WriteString(rec.Time().Format(timestampFmt))
+ buf.Write(Space)
+
+ buf.WriteString(level.Name)
+ buf.Write(Space)
+
+ buf.WriteString(rec.Msg())
+ buf.Write(Space)
+
+ fields := rec.Fields()
+ if len(fields) > 0 {
+ if err := WriteFields(buf, fields, Space, NoColor); err != nil {
+ return nil, err
+ }
+ }
+
+ if level.Stacktrace {
+ frames := rec.StackFrames()
+ if len(frames) > 0 {
+ buf.Write(Newline)
+ if err := WriteStacktrace(buf, rec.StackFrames()); err != nil {
+ return nil, err
+ }
+ }
+ }
+ buf.Write(Newline)
+
+ return buf, nil
+}
+
+// WriteFields writes zero or more name value pairs to the io.Writer.
+// The pairs output in key=value format with optional separator between fields.
+func WriteFields(w io.Writer, fields []Field, separator []byte, color Color) error {
+ ws := Writer{w}
+
+ sep := []byte{}
+ for _, field := range fields {
+ if err := writeField(ws, field, sep, color); err != nil {
+ return err
+ }
+ sep = separator
+ }
+ return nil
+}
+
+func writeField(ws Writer, field Field, sep []byte, color Color) error {
+ if len(sep) != 0 {
+ if _, err := ws.Write(sep); err != nil {
+ return err
+ }
+ }
+ if err := WriteWithColor(ws, field.Key, color); err != nil {
+ return err
+ }
+ if _, err := ws.Write(Equals); err != nil {
+ return err
+ }
+ return field.ValueString(ws, shouldQuote)
+}
+
+// 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') ||
+ c == '-' || c == '.' || c == '_' || c == '/' || c == '@' || c == '^' || c == '+') {
+ return true
+ }
+ }
+ return false
+}
+
+// WriteStacktrace formats and outputs a stack trace to an io.Writer.
+func WriteStacktrace(w io.Writer, frames []runtime.Frame) error {
+ ws := Writer{w}
+ for _, frame := range frames {
+ if frame.Function != "" {
+ if _, err := ws.Writes(Space, Space, []byte(frame.Function), Newline); err != nil {
+ return err
+ }
+ }
+ if frame.File != "" {
+ s := strconv.FormatInt(int64(frame.Line), 10)
+ if _, err := ws.Writes([]byte{' ', ' ', ' ', ' ', ' ', ' '}, []byte(frame.File), Colon, []byte(s), Newline); err != nil {
+ return err
+ }
+ }
+ }
+ return nil
+}
+
+// WriteWithColor outputs a string with the specified ANSI color.
+func WriteWithColor(w io.Writer, s string, color Color) error {
+ var err error
+
+ writer := func(buf []byte) {
+ if err != nil {
+ return
+ }
+ _, err = w.Write(buf)
+ }
+
+ if color != NoColor {
+ writer(AnsiColorPrefix)
+ writer([]byte(strconv.FormatInt(int64(color), 10)))
+ writer(AnsiColorSuffix)
+ }
+
+ if err == nil {
+ _, err = io.WriteString(w, s)
+ }
+
+ if color != NoColor {
+ writer(AnsiColorPrefix)
+ writer([]byte(strconv.FormatInt(int64(NoColor), 10)))
+ writer(AnsiColorSuffix)
+ }
+ return err
+}