blob: f5be9ad40470a44ee6dff4f692f94273e9c51ca4 [file] [log] [blame]
package log
import (
"fmt"
"io"
"runtime/debug"
"time"
)
// Formatter records log entries.
type Formatter interface {
Format(writer io.Writer, level int, msg string, args []interface{})
}
// TextFormatter is the default recorder used if one is unspecified when
// creating a new Logger.
type TextFormatter struct {
name string
itoaLevelMap map[int]string
timeLabel string
}
// NewTextFormatter returns a new instance of TextFormatter. SetName
// must be called befored using it.
func NewTextFormatter(name string) *TextFormatter {
timeLabel := KeyMap.Time + AssignmentChar
levelLabel := Separator + KeyMap.Level + AssignmentChar
messageLabel := Separator + KeyMap.Message + AssignmentChar
nameLabel := Separator + KeyMap.Name + AssignmentChar
pidLabel := Separator + KeyMap.PID + AssignmentChar
var buildKV = func(level string) string {
buf := pool.Get()
defer pool.Put(buf)
buf.WriteString(pidLabel)
buf.WriteString(pidStr)
//buf.WriteString(Separator)
buf.WriteString(nameLabel)
buf.WriteString(name)
//buf.WriteString(Separator)
buf.WriteString(levelLabel)
buf.WriteString(level)
//buf.WriteString(Separator)
buf.WriteString(messageLabel)
return buf.String()
}
itoaLevelMap := map[int]string{
LevelDebug: buildKV(LevelMap[LevelDebug]),
LevelWarn: buildKV(LevelMap[LevelWarn]),
LevelInfo: buildKV(LevelMap[LevelInfo]),
LevelError: buildKV(LevelMap[LevelError]),
LevelFatal: buildKV(LevelMap[LevelFatal]),
}
return &TextFormatter{itoaLevelMap: itoaLevelMap, name: name, timeLabel: timeLabel}
}
func (tf *TextFormatter) set(buf bufferWriter, key string, val interface{}) {
buf.WriteString(Separator)
buf.WriteString(key)
buf.WriteString(AssignmentChar)
if err, ok := val.(error); ok {
buf.WriteString(err.Error())
buf.WriteRune('\n')
buf.WriteString(string(debug.Stack()))
return
}
buf.WriteString(fmt.Sprintf("%v", val))
}
// Format records a log entry.
func (tf *TextFormatter) Format(writer io.Writer, level int, msg string, args []interface{}) {
buf := pool.Get()
defer pool.Put(buf)
buf.WriteString(tf.timeLabel)
buf.WriteString(time.Now().Format(timeFormat))
buf.WriteString(tf.itoaLevelMap[level])
buf.WriteString(msg)
var lenArgs = len(args)
if lenArgs > 0 {
if lenArgs == 1 {
tf.set(buf, singleArgKey, args[0])
} else if lenArgs%2 == 0 {
for i := 0; i < lenArgs; i += 2 {
if key, ok := args[i].(string); ok {
if key == "" {
// show key is invalid
tf.set(buf, badKeyAtIndex(i), args[i+1])
} else {
tf.set(buf, key, args[i+1])
}
} else {
// show key is invalid
tf.set(buf, badKeyAtIndex(i), args[i+1])
}
}
} else {
tf.set(buf, warnImbalancedKey, args)
}
}
buf.WriteRune('\n')
buf.WriteTo(writer)
}