diff --git a/lib/logger/logger.go b/lib/logger/logger.go index 80e7a97a7..f886427f0 100644 --- a/lib/logger/logger.go +++ b/lib/logger/logger.go @@ -16,7 +16,10 @@ import ( "github.com/VictoriaMetrics/metrics" ) -var loggerLevel = flag.String("loggerLevel", "INFO", "Minimum level of errors to log. Possible values: INFO, ERROR, FATAL, PANIC") +var ( + loggerLevel = flag.String("loggerLevel", "INFO", "Minimum level of errors to log. Possible values: INFO, ERROR, FATAL, PANIC") + loggerFormat = flag.String("loggerFormat", "default", "Format for logs. Possible values: default, json") +) // Init initializes the logger. // @@ -25,6 +28,7 @@ var loggerLevel = flag.String("loggerLevel", "INFO", "Minimum level of errors to // There is no need in calling Init from tests. func Init() { validateLoggerLevel() + validateLoggerFormat() go errorsLoggedCleaner() logAllFlags() } @@ -38,6 +42,15 @@ func validateLoggerLevel() { } } +func validateLoggerFormat() { + switch *loggerFormat { + case "default", "json": + default: + // We cannot use logger.Pancif here, since the logger isn't initialized yet. + panic(fmt.Errorf("FATAL: unsupported `-loggerFormat` value: %q; supported values are: default, json", *loggerFormat)) + } +} + var stdErrorLogger = log.New(&logWriter{}, "", 0) // StdErrorLogger returns standard error logger. @@ -101,7 +114,7 @@ func (lw *logWriter) Write(p []byte) (int, error) { } func logMessage(level, msg string, skipframes int) { - timestamp := time.Now().UTC().Format("2006-01-02T15:04:05.000+0000") + timestamp := time.Now().UTC().Format("2006-01-02T15:04:05.000Z") levelLowercase := strings.ToLower(level) _, file, line, ok := runtime.Caller(skipframes) if !ok { @@ -115,7 +128,14 @@ func logMessage(level, msg string, skipframes int) { for len(msg) > 0 && msg[len(msg)-1] == '\n' { msg = msg[:len(msg)-1] } - logMsg := fmt.Sprintf("%s\t%s\t%s:%d\t%s\n", timestamp, levelLowercase, file, line, msg) + var logMsg string + switch *loggerFormat { + case "json": + caller := fmt.Sprintf("%s:%d", file, line) + logMsg = fmt.Sprintf(`{"ts":%q,"level":%q,"caller":%q,"msg":%q}`+"\n", timestamp, levelLowercase, caller, msg) + default: + logMsg = fmt.Sprintf("%s\t%s\t%s:%d\t%s\n", timestamp, levelLowercase, file, line, msg) + } // Serialize writes to log. mu.Lock()