diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 000000000..3dcb869d2 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,8 @@ +root = true + +[*] +end_of_line = lf +insert_final_newline = true + +[*.go] +indent_style = tab diff --git a/formatter/formatter.go b/formatter/formatter.go index a37c67914..74de38603 100644 --- a/formatter/formatter.go +++ b/formatter/formatter.go @@ -14,14 +14,29 @@ type TextFormatter struct { levelDesc []string } +// SyslogFormatter formats logs into text +type SyslogFormatter struct { + levelDesc []string +} + +var validLevelDesc = []string{"PANC", "FATL", "ERRO", "WARN", "INFO", "DEBG", "TRAC"} + + // NewTextFormatter create new MyTextFormatter instance func NewTextFormatter() *TextFormatter { return &TextFormatter{ - levelDesc: []string{"PANC", "FATL", "ERRO", "WARN", "INFO", "DEBG", "TRAC"}, + levelDesc: validLevelDesc, timestampFormat: time.RFC3339, // or RFC3339 } } +// NewSyslogFormatter create new MySyslogFormatter instance +func NewSyslogFormatter() *SyslogFormatter { + return &SyslogFormatter{ + levelDesc: validLevelDesc, + } +} + // Format renders a single log entry func (f *TextFormatter) Format(entry *logrus.Entry) ([]byte, error) { var fields string @@ -49,3 +64,20 @@ func (f *TextFormatter) parseLevel(level logrus.Level) string { return f.levelDesc[level] } + +// Format renders a single log entry +func (f *SyslogFormatter) Format(entry *logrus.Entry) ([]byte, error) { + var fields string + keys := make([]string, 0, len(entry.Data)) + for k, v := range entry.Data { + if k == "source" { + continue + } + keys = append(keys, fmt.Sprintf("%s: %v", k, v)) + } + + if len(keys) > 0 { + fields = fmt.Sprintf("[%s] ", strings.Join(keys, ", ")) + } + return []byte(fmt.Sprintf("%s%s\n", fields, entry.Message)), nil +} diff --git a/formatter/formatter_test.go b/formatter/formatter_test.go index 54bc8a756..1ed207958 100644 --- a/formatter/formatter_test.go +++ b/formatter/formatter_test.go @@ -8,7 +8,7 @@ import ( "github.com/stretchr/testify/assert" ) -func TestLogMessageFormat(t *testing.T) { +func TestLogTextFormat(t *testing.T) { someEntry := &logrus.Entry{ Data: logrus.Fields{"att1": 1, "att2": 2, "source": "some/fancy/path.go:46"}, @@ -24,3 +24,20 @@ func TestLogMessageFormat(t *testing.T) { expectedString := "^2021-02-21T01:10:30Z WARN \\[(att1: 1, att2: 2|att2: 2, att1: 1)\\] some/fancy/path.go:46: Some Message\\s+$" assert.Regexp(t, expectedString, parsedString) } + +func TestLogSyslogFormat(t *testing.T) { + + someEntry := &logrus.Entry{ + Data: logrus.Fields{"att1": 1, "att2": 2, "source": "some/fancy/path.go:46"}, + Time: time.Date(2021, time.Month(2), 21, 1, 10, 30, 0, time.UTC), + Level: 3, + Message: "Some Message", + } + + formatter := NewSyslogFormatter() + result, _ := formatter.Format(someEntry) + + parsedString := string(result) + expectedString := "^\\[(att1: 1, att2: 2|att2: 2, att1: 1)\\] Some Message\\s+$" + assert.Regexp(t, expectedString, parsedString) +} diff --git a/formatter/set.go b/formatter/set.go index f9ccef601..9dfea5a7f 100644 --- a/formatter/set.go +++ b/formatter/set.go @@ -10,6 +10,12 @@ func SetTextFormatter(logger *logrus.Logger) { logger.ReportCaller = true logger.AddHook(NewContextHook()) } +// SetSyslogFormatter set the text formatter for given logger. +func SetSyslogFormatter(logger *logrus.Logger) { + logger.Formatter = NewSyslogFormatter() + logger.ReportCaller = true + logger.AddHook(NewContextHook()) +} // SetJSONFormatter set the JSON formatter for given logger. func SetJSONFormatter(logger *logrus.Logger) { diff --git a/util/log.go b/util/log.go index 74b99311e..4bce75e4a 100644 --- a/util/log.go +++ b/util/log.go @@ -35,8 +35,11 @@ func InitLog(logLevel string, logPath string) error { AddSyslogHook() } + //nolint:gocritic if os.Getenv("NB_LOG_FORMAT") == "json" { formatter.SetJSONFormatter(log.StandardLogger()) + } else if logPath == "syslog" { + formatter.SetSyslogFormatter(log.StandardLogger()) } else { formatter.SetTextFormatter(log.StandardLogger()) }