[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
parent
f1ecc5b82a
commit
a29eeb52b6
|
@ -35,7 +35,7 @@ func startServer() {
|
||||||
os.Exit(1)
|
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)
|
logging.Logger().Fatalf("Cannot initialize logger: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,9 @@ server:
|
||||||
|
|
||||||
# Level of verbosity for logs: info, debug, trace
|
# Level of verbosity for logs: info, debug, trace
|
||||||
log_level: debug
|
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
|
# log_file_path: /config/authelia.log
|
||||||
|
|
||||||
# The secret used to generate JWT tokens when validating user identity by
|
# The secret used to generate JWT tokens when validating user identity by
|
||||||
|
|
|
@ -47,6 +47,28 @@ generate a large amount of log entries and expose the `/debug/vars` and
|
||||||
log_level: debug
|
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
|
### Log file path
|
||||||
|
|
||||||
`optional: true`
|
`optional: true`
|
||||||
|
@ -61,7 +83,6 @@ logs over time to prevent significant long-term disk usage.
|
||||||
log_file_path: /config/authelia.log
|
log_file_path: /config/authelia.log
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
## JWT Secret
|
## JWT Secret
|
||||||
|
|
||||||
`optional: false`
|
`optional: false`
|
||||||
|
|
|
@ -7,6 +7,7 @@ type Configuration struct {
|
||||||
TLSCert string `mapstructure:"tls_cert"`
|
TLSCert string `mapstructure:"tls_cert"`
|
||||||
TLSKey string `mapstructure:"tls_key"`
|
TLSKey string `mapstructure:"tls_key"`
|
||||||
LogLevel string `mapstructure:"log_level"`
|
LogLevel string `mapstructure:"log_level"`
|
||||||
|
LogFormat string `mapstructure:"log_format"`
|
||||||
LogFilePath string `mapstructure:"log_file_path"`
|
LogFilePath string `mapstructure:"log_file_path"`
|
||||||
JWTSecret string `mapstructure:"jwt_secret"`
|
JWTSecret string `mapstructure:"jwt_secret"`
|
||||||
DefaultRedirectionURL string `mapstructure:"default_redirection_url"`
|
DefaultRedirectionURL string `mapstructure:"default_redirection_url"`
|
||||||
|
|
|
@ -14,6 +14,7 @@ func newDefaultConfig() schema.Configuration {
|
||||||
config.Host = "127.0.0.1"
|
config.Host = "127.0.0.1"
|
||||||
config.Port = 9090
|
config.Port = 9090
|
||||||
config.LogLevel = "info"
|
config.LogLevel = "info"
|
||||||
|
config.LogFormat = "text"
|
||||||
config.JWTSecret = testJWTSecret
|
config.JWTSecret = testJWTSecret
|
||||||
config.AuthenticationBackend.File = new(schema.FileAuthenticationBackendConfiguration)
|
config.AuthenticationBackend.File = new(schema.FileAuthenticationBackendConfiguration)
|
||||||
config.AuthenticationBackend.File.Path = "/a/path"
|
config.AuthenticationBackend.File.Path = "/a/path"
|
||||||
|
|
|
@ -5,6 +5,7 @@ var validKeys = []string{
|
||||||
"host",
|
"host",
|
||||||
"port",
|
"port",
|
||||||
"log_level",
|
"log_level",
|
||||||
|
"log_format",
|
||||||
"log_file_path",
|
"log_file_path",
|
||||||
"default_redirection_url",
|
"default_redirection_url",
|
||||||
"jwt_secret",
|
"jwt_secret",
|
||||||
|
|
|
@ -18,11 +18,17 @@ func SetLevel(level logrus.Level) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// InitializeLogger initialize logger.
|
// InitializeLogger initialize logger.
|
||||||
func InitializeLogger(filename string) error {
|
func InitializeLogger(format, filename string) error {
|
||||||
callerLevels := []logrus.Level{}
|
callerLevels := []logrus.Level{}
|
||||||
stackLevels := []logrus.Level{logrus.PanicLevel, logrus.FatalLevel, logrus.ErrorLevel}
|
stackLevels := []logrus.Level{logrus.PanicLevel, logrus.FatalLevel, logrus.ErrorLevel}
|
||||||
logrus.AddHook(logrus_stack.NewHook(callerLevels, stackLevels))
|
logrus.AddHook(logrus_stack.NewHook(callerLevels, stackLevels))
|
||||||
|
|
||||||
|
if format == "json" {
|
||||||
|
logrus.SetFormatter(&logrus.JSONFormatter{})
|
||||||
|
} else {
|
||||||
|
logrus.SetFormatter(&logrus.TextFormatter{})
|
||||||
|
}
|
||||||
|
|
||||||
if filename != "" {
|
if filename != "" {
|
||||||
f, err := os.OpenFile(filename, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0600)
|
f, err := os.OpenFile(filename, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0600)
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@ func TestShouldWriteLogsToFile(t *testing.T) {
|
||||||
defer os.RemoveAll(dir)
|
defer os.RemoveAll(dir)
|
||||||
|
|
||||||
path := fmt.Sprintf("%s/authelia.log", dir)
|
path := fmt.Sprintf("%s/authelia.log", dir)
|
||||||
err = InitializeLogger(path)
|
err = InitializeLogger("text", path)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
Logger().Info("This is a test")
|
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")
|
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\",")
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue