Skip to content

Commit

Permalink
pkg/logutil: add json log format (#626)
Browse files Browse the repository at this point in the history
  • Loading branch information
andelf authored and siddontang committed Apr 25, 2017
1 parent 4d52abb commit fe564d4
Show file tree
Hide file tree
Showing 2 changed files with 73 additions and 27 deletions.
15 changes: 14 additions & 1 deletion conf/config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,21 @@ tso-save-interval = "3s"
[log]
level = "info"

#[log.file]
# log format, one of json, text, console
#format = "text"

# disable automatic timestamps in output
#disable-timestamp = false

# file logging
[log.file]
#filename = ""
# max log file size in MB
#max-size = 300
# max log file keep days
#max-days = 28
# maximum number of old log files to retain
#max-backups = 7

[metric]
# prometheus client push interval, set "0s" to disable prometheus.
Expand Down
85 changes: 59 additions & 26 deletions pkg/logutil/log.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,23 +30,33 @@ import (
const (
defaultLogTimeFormat = "2006/01/02 15:04:05"
defaultLogMaxSize = 300 // MB
defaultLogMaxBackups = 3
defaultLogMaxAge = 28 // days
defaultLogFormat = "text"
defaultLogLevel = log.InfoLevel

logDirMode = 0755
)

// FileLogConfig serializes file log related config in toml/json.
type FileLogConfig struct {
// Log filename, leave empty to disable file log.
Filename string `toml:"filename" json:"filename"`
// Is log rotate enabled. TODO.
LogRotate bool `toml:"log-rotate" json:"log-rotate"`
// Max size for a single file, in MB.
MaxSize int `toml:"max-size" json:"max-size"`
// Max log keep days, default is never deleting.
MaxDays int `toml:"max-days" json:"max-days"`
// Maximum number of old log files to retain.
MaxBackups int `toml:"max-backups" json:"max-backups"`
}

// LogConfig serializes log related config in toml/json.
type LogConfig struct {
// Log level.
Level string `toml:"level" json:"level"`
// Log file.
// Log format. one of json, text, or console.
Format string `toml:"format" json:"format"`
// Disable automatic timestamps in output.
DisableTimestamp bool `toml:"disable-timestamp" json:"disable-timestamp"`
// File log config.
File FileLogConfig `toml:"file" json:"file"`
}

Expand Down Expand Up @@ -130,7 +140,9 @@ func stringToLogLevel(level string) log.Level {
}

// textFormatter is for compatability with ngaut/log
type textFormatter struct{}
type textFormatter struct {
DisableTimestamp bool
}

// Format implements logrus.Formatter
func (f *textFormatter) Format(entry *log.Entry) ([]byte, error) {
Expand All @@ -140,9 +152,11 @@ func (f *textFormatter) Format(entry *log.Entry) ([]byte, error) {
} else {
b = &bytes.Buffer{}
}
b.WriteString(entry.Time.Format(defaultLogTimeFormat))
if !f.DisableTimestamp {
fmt.Fprintf(b, "%s ", entry.Time.Format(defaultLogTimeFormat))
}
if file, ok := entry.Data["file"]; ok {
fmt.Fprintf(b, " %s:%v:", file, entry.Data["line"])
fmt.Fprintf(b, "%s:%v:", file, entry.Data["line"])
}
fmt.Fprintf(b, " [%s] %s", entry.Level.String(), entry.Message)
for k, v := range entry.Data {
Expand All @@ -154,33 +168,48 @@ func (f *textFormatter) Format(entry *log.Entry) ([]byte, error) {
return b.Bytes(), nil
}

// setLogOutput sets output path for all logs.
func setLogOutput(filename string) error {
// PD log
if st, err := os.Stat(filename); err == nil {
func stringToLogFormatter(format string, disableTimestamp bool) log.Formatter {
switch strings.ToLower(format) {
case "text":
return &textFormatter{
DisableTimestamp: disableTimestamp,
}
case "json":
return &log.JSONFormatter{
TimestampFormat: defaultLogTimeFormat,
DisableTimestamp: disableTimestamp,
}
case "console":
return &log.TextFormatter{
FullTimestamp: true,
TimestampFormat: defaultLogTimeFormat,
DisableTimestamp: disableTimestamp,
}
default:
return &textFormatter{}
}
}

// InitFileLog initializes file based logging options.
func InitFileLog(cfg *FileLogConfig) error {
if st, err := os.Stat(cfg.Filename); err == nil {
if st.IsDir() {
return errors.New("can't use directory as log file name")
}
}
dir := path.Dir(filename)
err := os.MkdirAll(dir, logDirMode)
if err != nil {
return errors.Trace(err)
if cfg.MaxSize == 0 {
cfg.MaxSize = defaultLogMaxSize
}

// use lumberjack to logrotate
output := &lumberjack.Logger{
Filename: filename,
MaxSize: defaultLogMaxSize, // megabytes
MaxBackups: defaultLogMaxBackups,
MaxAge: defaultLogMaxAge, // days
Filename: cfg.Filename,
MaxSize: cfg.MaxSize,
MaxBackups: cfg.MaxBackups,
MaxAge: cfg.MaxDays,
LocalTime: true,
}

if _, err := output.Write([]byte{}); err != nil {
return errors.Errorf("log file is not writable: %v", err)
}

log.SetOutput(output)
return nil
}
Expand All @@ -189,7 +218,11 @@ func setLogOutput(filename string) error {
func InitLogger(cfg *LogConfig) error {
log.SetLevel(stringToLogLevel(cfg.Level))
log.AddHook(&contextHook{})
log.SetFormatter(&textFormatter{})

if cfg.Format == "" {
cfg.Format = defaultLogFormat
}
log.SetFormatter(stringToLogFormatter(cfg.Format, cfg.DisableTimestamp))

// etcd log
capnslog.SetFormatter(&redirectFormatter{})
Expand All @@ -198,7 +231,7 @@ func InitLogger(cfg *LogConfig) error {
return nil
}

err := setLogOutput(cfg.File.Filename)
err := InitFileLog(&cfg.File)
if err != nil {
return errors.Trace(err)
}
Expand Down

0 comments on commit fe564d4

Please sign in to comment.