[FEATURE] Add JSON log formatting option (#1488)

This change adds the ability to format Authelia's log output as JSON.

Example below:
```
{"level":"info","msg":"Logging severity set to info","time":"2020-01-01T00:00:00+11:00"}
{"level":"info","msg":"Authelia is listening for non-TLS connections on 0.0.0.0:9091","time":"2020-01-01T00:00:00+11:00"}
```
pull/1490/head^2
Amir Zarrinkafsh 2020-11-25 10:46:41 +11:00 committed by GitHub
parent f1ecc5b82a
commit a29eeb52b6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 60 additions and 5 deletions

View File

@ -35,7 +35,7 @@ func startServer() {
os.Exit(1)
}
if err := logging.InitializeLogger(config.LogFilePath); err != nil {
if err := logging.InitializeLogger(config.LogFormat, config.LogFilePath); err != nil {
logging.Logger().Fatalf("Cannot initialize logger: %v", err)
}

View File

@ -21,7 +21,9 @@ server:
# Level of verbosity for logs: info, debug, trace
log_level: debug
## File path where the logs will be written. If not set logs are written to stdout.
# Format the logs are written as: json, text
# log_format: json
# File path where the logs will be written. If not set logs are written to stdout.
# log_file_path: /config/authelia.log
# The secret used to generate JWT tokens when validating user identity by

View File

@ -47,6 +47,28 @@ generate a large amount of log entries and expose the `/debug/vars` and
log_level: debug
```
### Log format
`optional: true`
Defines the format of the logs written by Authelia.
This format can be set to `json` or `text`.
```yaml
log_format: json
```
#### JSON format
```
{"level":"info","msg":"Logging severity set to info","time":"2020-01-01T00:00:00+11:00"}
{"level":"info","msg":"Authelia is listening for non-TLS connections on 0.0.0.0:9091","time":"2020-01-01T00:00:00+11:00"}
```
#### Text format
```
time="2020-01-01T00:00:00+11:00" level=info msg="Logging severity set to info"
time="2020-01-01T00:00:00+11:00" level=info msg="Authelia is listening for non-TLS connections on 0.0.0.0:9091"
```
### Log file path
`optional: true`
@ -61,7 +83,6 @@ logs over time to prevent significant long-term disk usage.
log_file_path: /config/authelia.log
```
## JWT Secret
`optional: false`

View File

@ -7,6 +7,7 @@ type Configuration struct {
TLSCert string `mapstructure:"tls_cert"`
TLSKey string `mapstructure:"tls_key"`
LogLevel string `mapstructure:"log_level"`
LogFormat string `mapstructure:"log_format"`
LogFilePath string `mapstructure:"log_file_path"`
JWTSecret string `mapstructure:"jwt_secret"`
DefaultRedirectionURL string `mapstructure:"default_redirection_url"`

View File

@ -14,6 +14,7 @@ func newDefaultConfig() schema.Configuration {
config.Host = "127.0.0.1"
config.Port = 9090
config.LogLevel = "info"
config.LogFormat = "text"
config.JWTSecret = testJWTSecret
config.AuthenticationBackend.File = new(schema.FileAuthenticationBackendConfiguration)
config.AuthenticationBackend.File.Path = "/a/path"

View File

@ -5,6 +5,7 @@ var validKeys = []string{
"host",
"port",
"log_level",
"log_format",
"log_file_path",
"default_redirection_url",
"jwt_secret",

View File

@ -18,11 +18,17 @@ func SetLevel(level logrus.Level) {
}
// InitializeLogger initialize logger.
func InitializeLogger(filename string) error {
func InitializeLogger(format, filename string) error {
callerLevels := []logrus.Level{}
stackLevels := []logrus.Level{logrus.PanicLevel, logrus.FatalLevel, logrus.ErrorLevel}
logrus.AddHook(logrus_stack.NewHook(callerLevels, stackLevels))
if format == "json" {
logrus.SetFormatter(&logrus.JSONFormatter{})
} else {
logrus.SetFormatter(&logrus.TextFormatter{})
}
if filename != "" {
f, err := os.OpenFile(filename, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0600)

View File

@ -20,7 +20,7 @@ func TestShouldWriteLogsToFile(t *testing.T) {
defer os.RemoveAll(dir)
path := fmt.Sprintf("%s/authelia.log", dir)
err = InitializeLogger(path)
err = InitializeLogger("text", path)
require.NoError(t, err)
Logger().Info("This is a test")
@ -33,3 +33,26 @@ func TestShouldWriteLogsToFile(t *testing.T) {
assert.Contains(t, string(b), "level=info msg=\"This is a test\"\n")
}
func TestShouldFormatLogsAsJSON(t *testing.T) {
dir, err := ioutil.TempDir("/tmp", "logs-dir")
if err != nil {
log.Fatal(err)
}
defer os.RemoveAll(dir)
path := fmt.Sprintf("%s/authelia.log", dir)
err = InitializeLogger("json", path)
require.NoError(t, err)
Logger().Info("This is a test")
f, err := os.OpenFile(path, os.O_RDONLY, 0)
require.NoError(t, err)
b, err := ioutil.ReadAll(f)
require.NoError(t, err)
assert.Contains(t, string(b), "{\"level\":\"info\",\"msg\":\"This is a test\",")
}