Просмотр исходного кода

feat(logging): added log format option, #4590

Torkel Ödegaard 9 лет назад
Родитель
Сommit
1d8fdc09e7
3 измененных файлов с 71 добавлено и 16 удалено
  1. 14 4
      conf/defaults.ini
  2. 27 3
      conf/sample.ini
  3. 30 9
      pkg/log/log.go

+ 14 - 4
conf/defaults.ini

@@ -251,18 +251,23 @@ templates_pattern = emails/*.html
 # Use space to separate multiple modes, e.g. "console file"
 # Use space to separate multiple modes, e.g. "console file"
 mode = console, file
 mode = console, file
 
 
-# Either "Trace", "Debug", "Info", "Warn", "Error", "Critical", default is "Info"
-level = Info
+# Either "trace", "debug", "info", "warn", "error", "critical", default is "info"
+level = info
 
 
 # For "console" mode only
 # For "console" mode only
 [log.console]
 [log.console]
 level =
 level =
-# Set formatting to "false" to disable color formatting of console logs
-formatting = false
+
+# log line format, valid options are text, console and json
+format = console
 
 
 # For "file" mode only
 # For "file" mode only
 [log.file]
 [log.file]
 level =
 level =
+
+# log line format, valid options are text, console and json
+format = text
+
 # This enables automated log rotate(switch of following options), default is true
 # This enables automated log rotate(switch of following options), default is true
 log_rotate = true
 log_rotate = true
 
 
@@ -280,6 +285,10 @@ max_days = 7
 
 
 [log.syslog]
 [log.syslog]
 level =
 level =
+
+# log line format, valid options are text, console and json
+format = text
+
 # Syslog network type and address. This can be udp, tcp, or unix. If left blank, the default unix endpoints will be used.
 # Syslog network type and address. This can be udp, tcp, or unix. If left blank, the default unix endpoints will be used.
 network =
 network =
 address =
 address =
@@ -290,6 +299,7 @@ facility =
 # Syslog tag. By default, the process' argv[0] is used.
 # Syslog tag. By default, the process' argv[0] is used.
 tag =
 tag =
 
 
+
 #################################### AMQP Event Publisher ##########################
 #################################### AMQP Event Publisher ##########################
 [event_publisher]
 [event_publisher]
 enabled = false
 enabled = false

+ 27 - 3
conf/sample.ini

@@ -230,19 +230,26 @@ check_for_updates = true
 #################################### Logging ##########################
 #################################### Logging ##########################
 [log]
 [log]
 # Either "console", "file", "syslog". Default is console and  file
 # Either "console", "file", "syslog". Default is console and  file
-# Use comma to separate multiple modes, e.g. "console, file"
+# Use space to separate multiple modes, e.g. "console file"
 ;mode = console, file
 ;mode = console, file
 
 
-# Either "Trace", "Debug", "Info", "Warn", "Error", "Critical", default is "Info"
-;level = Info
+# Either "trace", "debug", "info", "warn", "error", "critical", default is "info"
+;level = info
 
 
 # For "console" mode only
 # For "console" mode only
 [log.console]
 [log.console]
 ;level =
 ;level =
 
 
+# log line format, valid options are text, console and json
+;format = console
+
 # For "file" mode only
 # For "file" mode only
 [log.file]
 [log.file]
 ;level =
 ;level =
+
+# log line format, valid options are text, console and json
+;format = text
+
 # This enables automated log rotate(switch of following options), default is true
 # This enables automated log rotate(switch of following options), default is true
 ;log_rotate = true
 ;log_rotate = true
 
 
@@ -258,6 +265,23 @@ check_for_updates = true
 # Expired days of log file(delete after max days), default is 7
 # Expired days of log file(delete after max days), default is 7
 ;max_days = 7
 ;max_days = 7
 
 
+[log.syslog]
+;level =
+
+# log line format, valid options are text, console and json
+;format = text
+
+# Syslog network type and address. This can be udp, tcp, or unix. If left blank, the default unix endpoints will be used.
+;network =
+;address =
+
+# Syslog facility. user, daemon and local0 through local7 are valid.
+;facility =
+
+# Syslog tag. By default, the process' argv[0] is used.
+;tag =
+
+
 #################################### AMQP Event Publisher ##########################
 #################################### AMQP Event Publisher ##########################
 [event_publisher]
 [event_publisher]
 ;enabled = false
 ;enabled = false

+ 30 - 9
pkg/log/log.go

@@ -13,6 +13,7 @@ import (
 	"gopkg.in/ini.v1"
 	"gopkg.in/ini.v1"
 
 
 	"github.com/inconshreveable/log15"
 	"github.com/inconshreveable/log15"
+	"github.com/inconshreveable/log15/term"
 )
 )
 
 
 var Root log15.Logger
 var Root log15.Logger
@@ -82,16 +83,17 @@ func Close() {
 }
 }
 
 
 var logLevels = map[string]log15.Lvl{
 var logLevels = map[string]log15.Lvl{
-	"Trace":    log15.LvlDebug,
-	"Debug":    log15.LvlDebug,
-	"Info":     log15.LvlInfo,
-	"Warn":     log15.LvlWarn,
-	"Error":    log15.LvlError,
-	"Critical": log15.LvlCrit,
+	"trace":    log15.LvlDebug,
+	"debug":    log15.LvlDebug,
+	"info":     log15.LvlInfo,
+	"warn":     log15.LvlWarn,
+	"error":    log15.LvlError,
+	"critical": log15.LvlCrit,
 }
 }
 
 
 func getLogLevelFromConfig(key string, defaultName string, cfg *ini.File) (string, log15.Lvl) {
 func getLogLevelFromConfig(key string, defaultName string, cfg *ini.File) (string, log15.Lvl) {
-	levelName := cfg.Section(key).Key("level").In(defaultName, []string{"Trace", "Debug", "Info", "Warn", "Error", "Critical"})
+	levelName := cfg.Section(key).Key("level").MustString("info")
+	levelName = strings.ToLower(levelName)
 	level := getLogLevelFromString(levelName)
 	level := getLogLevelFromString(levelName)
 	return levelName, level
 	return levelName, level
 }
 }
@@ -118,10 +120,26 @@ func getFilters(filterStrArray []string) map[string]log15.Lvl {
 	return filterMap
 	return filterMap
 }
 }
 
 
+func getLogFormat(format string) log15.Format {
+	switch format {
+	case "console":
+		if term.IsTty(os.Stdout.Fd()) {
+			return log15.TerminalFormat()
+		}
+		return log15.LogfmtFormat()
+	case "text":
+		return log15.LogfmtFormat()
+	case "json":
+		return log15.JsonFormat()
+	default:
+		return log15.LogfmtFormat()
+	}
+}
+
 func ReadLoggingConfig(modes []string, logsPath string, cfg *ini.File) {
 func ReadLoggingConfig(modes []string, logsPath string, cfg *ini.File) {
 	Close()
 	Close()
 
 
-	defaultLevelName, _ := getLogLevelFromConfig("log", "Info", cfg)
+	defaultLevelName, _ := getLogLevelFromConfig("log", "info", cfg)
 	defaultFilters := getFilters(cfg.Section("log").Key("filters").Strings(" "))
 	defaultFilters := getFilters(cfg.Section("log").Key("filters").Strings(" "))
 
 
 	handlers := make([]log15.Handler, 0)
 	handlers := make([]log15.Handler, 0)
@@ -136,18 +154,20 @@ func ReadLoggingConfig(modes []string, logsPath string, cfg *ini.File) {
 		// Log level.
 		// Log level.
 		_, level := getLogLevelFromConfig("log."+mode, defaultLevelName, cfg)
 		_, level := getLogLevelFromConfig("log."+mode, defaultLevelName, cfg)
 		modeFilters := getFilters(sec.Key("filters").Strings(" "))
 		modeFilters := getFilters(sec.Key("filters").Strings(" "))
+		format := getLogFormat(sec.Key("format").MustString(""))
 
 
 		var handler log15.Handler
 		var handler log15.Handler
 
 
 		// Generate log configuration.
 		// Generate log configuration.
 		switch mode {
 		switch mode {
 		case "console":
 		case "console":
-			handler = log15.StdoutHandler
+			handler = log15.StreamHandler(os.Stdout, format)
 		case "file":
 		case "file":
 			fileName := sec.Key("file_name").MustString(filepath.Join(logsPath, "grafana.log"))
 			fileName := sec.Key("file_name").MustString(filepath.Join(logsPath, "grafana.log"))
 			os.MkdirAll(filepath.Dir(fileName), os.ModePerm)
 			os.MkdirAll(filepath.Dir(fileName), os.ModePerm)
 			fileHandler := NewFileWriter()
 			fileHandler := NewFileWriter()
 			fileHandler.Filename = fileName
 			fileHandler.Filename = fileName
+			fileHandler.Format = format
 			fileHandler.Rotate = sec.Key("log_rotate").MustBool(true)
 			fileHandler.Rotate = sec.Key("log_rotate").MustBool(true)
 			fileHandler.Maxlines = sec.Key("max_lines").MustInt(1000000)
 			fileHandler.Maxlines = sec.Key("max_lines").MustInt(1000000)
 			fileHandler.Maxsize = 1 << uint(sec.Key("max_size_shift").MustInt(28))
 			fileHandler.Maxsize = 1 << uint(sec.Key("max_size_shift").MustInt(28))
@@ -159,6 +179,7 @@ func ReadLoggingConfig(modes []string, logsPath string, cfg *ini.File) {
 			handler = fileHandler
 			handler = fileHandler
 		case "syslog":
 		case "syslog":
 			sysLogHandler := NewSyslog()
 			sysLogHandler := NewSyslog()
+			sysLogHandler.Format = format
 			sysLogHandler.Network = sec.Key("network").MustString("")
 			sysLogHandler.Network = sec.Key("network").MustString("")
 			sysLogHandler.Address = sec.Key("address").MustString("")
 			sysLogHandler.Address = sec.Key("address").MustString("")
 			sysLogHandler.Facility = sec.Key("facility").MustString("local7")
 			sysLogHandler.Facility = sec.Key("facility").MustString("local7")