package formatters import ( "bytes" "fmt" "strings" "github.com/mattermost/logr/v2" ) // Plain is the simplest formatter, outputting only text with // no colors. type Plain struct { // DisableTimestamp disables output of timestamp field. DisableTimestamp bool `json:"disable_timestamp"` // DisableLevel disables output of level field. DisableLevel bool `json:"disable_level"` // DisableMsg disables output of msg field. DisableMsg bool `json:"disable_msg"` // DisableFields disables output of all fields. DisableFields bool `json:"disable_fields"` // DisableStacktrace disables output of stack trace. DisableStacktrace bool `json:"disable_stacktrace"` // EnableCaller enables output of the file and line number that emitted a log record. EnableCaller bool `json:"enable_caller"` // Delim is an optional delimiter output between each log field. // Defaults to a single space. Delim string `json:"delim"` // MinLevelLen sets the minimum level name length. If the level name is less // than the minimum it will be padded with spaces. MinLevelLen int `json:"min_level_len"` // MinMessageLen sets the minimum msg length. If the msg text is less // than the minimum it will be padded with spaces. MinMessageLen int `json:"min_msg_len"` // TimestampFormat is an optional format for timestamps. If empty // then DefTimestampFormat is used. TimestampFormat string `json:"timestamp_format"` // LineEnd sets the end of line character(s). Defaults to '\n'. LineEnd string `json:"line_end"` // EnableColor sets whether output should include color. EnableColor bool `json:"enable_color"` } func (p *Plain) CheckValid() error { if p.MinMessageLen < 0 || p.MinMessageLen > 1024 { return fmt.Errorf("min_msg_len is invalid(%d)", p.MinMessageLen) } return nil } // IsStacktraceNeeded returns true if a stacktrace is needed so we can output the `Caller` field. func (p *Plain) IsStacktraceNeeded() bool { return p.EnableCaller } // Format converts a log record to bytes. func (p *Plain) Format(rec *logr.LogRec, level logr.Level, buf *bytes.Buffer) (*bytes.Buffer, error) { delim := p.Delim if delim == "" { delim = " " } if buf == nil { buf = &bytes.Buffer{} } timestampFmt := p.TimestampFormat if timestampFmt == "" { timestampFmt = logr.DefTimestampFormat } color := logr.NoColor if p.EnableColor { color = level.Color } if !p.DisableLevel { _ = logr.WriteWithColor(buf, level.Name, color) count := len(level.Name) if p.MinLevelLen > count { _, _ = buf.WriteString(strings.Repeat(" ", p.MinLevelLen-count)) } buf.WriteString(delim) } if !p.DisableTimestamp { var arr [128]byte tbuf := rec.Time().AppendFormat(arr[:0], timestampFmt) buf.WriteByte('[') buf.Write(tbuf) buf.WriteByte(']') buf.WriteString(delim) } if !p.DisableMsg { count, _ := buf.WriteString(rec.Msg()) if p.MinMessageLen > count { _, _ = buf.WriteString(strings.Repeat(" ", p.MinMessageLen-count)) } _, _ = buf.WriteString(delim) } var fields []logr.Field if p.EnableCaller { fld := logr.Field{ Key: "caller", Type: logr.StringType, String: rec.Caller(), } fields = append(fields, fld) } if !p.DisableFields { fields = append(fields, rec.Fields()...) } if len(fields) > 0 { if err := logr.WriteFields(buf, fields, logr.Space, color); err != nil { return nil, err } } if level.Stacktrace && !p.DisableStacktrace { frames := rec.StackFrames() if len(frames) > 0 { buf.WriteString("\n") if err := logr.WriteStacktrace(buf, rec.StackFrames()); err != nil { return nil, err } } } if p.LineEnd == "" { buf.WriteString("\n") } else { buf.WriteString(p.LineEnd) } return buf, nil }