[FEATURE] [BREAKING] Support writing logs in a file. (#686)

* [FEATURE] Support writing logs in a file.

* Add documentation about logs file path.

* Rename logs_level and logs_file_path into log_level and log_file_path.

* Update BREAKING.md

Fixes #338

Co-authored-by: Amir Zarrinkafsh <nightah@me.com>
pull/698/head
Clément Michaud 2020-03-09 20:57:53 +01:00 committed by GitHub
parent 6af27cb3f9
commit c429488738
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
27 changed files with 108 additions and 40 deletions

View File

@ -6,6 +6,10 @@ recommended not to use the 'latest' Docker image tag blindly but pick a version
and read this documentation before upgrading. This is where you will get information about and read this documentation before upgrading. This is where you will get information about
breaking changes and about what you should do to overcome those changes. breaking changes and about what you should do to overcome those changes.
## Breaking in v4.7.0
`logs_level` configuration key has been renamed to `log_level`.
## Breaking in v4.0.0 ## Breaking in v4.0.0
Authelia has been rewritten in Go for better code maintainability and for performance and Authelia has been rewritten in Go for better code maintainability and for performance and

View File

@ -29,10 +29,6 @@ func startServer() {
log.Fatal(errors.New("No config file path provided")) log.Fatal(errors.New("No config file path provided"))
} }
if os.Getenv("ENVIRONMENT") == "dev" {
logging.Logger().Info("===> Authelia is running in development mode. <===")
}
config, errs := configuration.Read(configPathFlag) config, errs := configuration.Read(configPathFlag)
if len(errs) > 0 { if len(errs) > 0 {
@ -42,7 +38,11 @@ func startServer() {
panic(errors.New("Some errors have been reported")) panic(errors.New("Some errors have been reported"))
} }
switch config.LogsLevel { if err := logging.InitializeLogger(config.LogFilePath); err != nil {
log.Fatalf("Cannot initialize logger: %v", err)
}
switch config.LogLevel {
case "info": case "info":
logging.Logger().Info("Logging severity set to info") logging.Logger().Info("Logging severity set to info")
logging.SetLevel(logrus.InfoLevel) logging.SetLevel(logrus.InfoLevel)
@ -56,6 +56,10 @@ func startServer() {
logging.SetLevel(logrus.TraceLevel) logging.SetLevel(logrus.TraceLevel)
} }
if os.Getenv("ENVIRONMENT") == "dev" {
logging.Logger().Info("===> Authelia is running in development mode. <===")
}
var userProvider authentication.UserProvider var userProvider authentication.UserProvider
if config.AuthenticationBackend.File != nil { if config.AuthenticationBackend.File != nil {

View File

@ -9,7 +9,9 @@ port: 9091
# tls_cert: /var/lib/authelia/ssl/cert.pem # tls_cert: /var/lib/authelia/ssl/cert.pem
# Level of verbosity for logs: info, debug, trace # Level of verbosity for logs: info, debug, trace
logs_level: debug log_level: debug
## File path where the logs will be written. If not set logs are written to stdout.
# log_file_path: /var/log/authelia
# The secret used to generate JWT tokens when validating user identity by # The secret used to generate JWT tokens when validating user identity by
# email confirmation. # email confirmation.

View File

@ -29,14 +29,25 @@ following configuration options:
tls_cert: /var/lib/authelia/ssl/cert.pem tls_cert: /var/lib/authelia/ssl/cert.pem
## Logs level ## Log
### Log level
`optional: true` `optional: true`
Defines the level of logs used by Authelia. This level can be set to Defines the level of logs used by Authelia. This level can be set to
`trace`, `debug`, `info`. `trace`, `debug`, `info`.
logs_level: debug log_level: debug
### Log file path
`optional: true`
Logs can be stored in a file when file path is provided. Otherwise logs
are written to standard output.
log_file_path: /var/log/authelia.log
## JWT Secret ## JWT Secret

View File

@ -23,7 +23,7 @@ func TestShouldParseConfigFile(t *testing.T) {
require.Len(t, errors, 0) require.Len(t, errors, 0)
assert.Equal(t, 9091, config.Port) assert.Equal(t, 9091, config.Port)
assert.Equal(t, "debug", config.LogsLevel) assert.Equal(t, "debug", config.LogLevel)
assert.Equal(t, "https://home.example.com:8080/", config.DefaultRedirectionURL) assert.Equal(t, "https://home.example.com:8080/", config.DefaultRedirectionURL)
assert.Equal(t, "authelia.com", config.TOTP.Issuer) assert.Equal(t, "authelia.com", config.TOTP.Issuer)
assert.Equal(t, "secret_from_env", config.JWTSecret) assert.Equal(t, "secret_from_env", config.JWTSecret)

View File

@ -7,7 +7,8 @@ type Configuration struct {
TLSCert string `mapstructure:"tls_cert"` TLSCert string `mapstructure:"tls_cert"`
TLSKey string `mapstructure:"tls_key"` TLSKey string `mapstructure:"tls_key"`
LogsLevel string `mapstructure:"logs_level"` LogLevel string `mapstructure:"log_level"`
LogFilePath string `mapstructure:"log_file_path"`
// This secret is used by the identity validation process to forge JWT tokens // This secret is used by the identity validation process to forge JWT tokens
// representing the permission to proceed with the operation. // representing the permission to proceed with the operation.

View File

@ -5,7 +5,7 @@
host: 127.0.0.1 host: 127.0.0.1
port: 9091 port: 9091
logs_level: debug log_level: debug
default_redirection_url: https://home.example.com:8080/ default_redirection_url: https://home.example.com:8080/
totp: totp:

View File

@ -8,7 +8,7 @@ import (
) )
var defaultPort = 8080 var defaultPort = 8080
var defaultLogsLevel = "info" var defaultLogLevel = "info"
// Validate and adapt the configuration read from file. // Validate and adapt the configuration read from file.
func Validate(configuration *schema.Configuration, validator *schema.StructValidator) { func Validate(configuration *schema.Configuration, validator *schema.StructValidator) {
@ -20,8 +20,8 @@ func Validate(configuration *schema.Configuration, validator *schema.StructValid
configuration.Port = defaultPort configuration.Port = defaultPort
} }
if configuration.LogsLevel == "" { if configuration.LogLevel == "" {
configuration.LogsLevel = defaultLogsLevel configuration.LogLevel = defaultLogLevel
} }
if configuration.TLSKey != "" && configuration.TLSCert == "" { if configuration.TLSKey != "" && configuration.TLSCert == "" {

View File

@ -12,7 +12,7 @@ func newDefaultConfig() schema.Configuration {
config := schema.Configuration{} config := schema.Configuration{}
config.Host = "127.0.0.1" config.Host = "127.0.0.1"
config.Port = 9090 config.Port = 9090
config.LogsLevel = "info" config.LogLevel = "info"
config.JWTSecret = "a_secret" config.JWTSecret = "a_secret"
config.AuthenticationBackend.File = new(schema.FileAuthenticationBackendConfiguration) config.AuthenticationBackend.File = new(schema.FileAuthenticationBackendConfiguration)
config.AuthenticationBackend.File.Path = "/a/path" config.AuthenticationBackend.File.Path = "/a/path"
@ -40,7 +40,7 @@ func TestShouldNotUpdateConfig(t *testing.T) {
require.Len(t, validator.Errors(), 0) require.Len(t, validator.Errors(), 0)
assert.Equal(t, 9090, config.Port) assert.Equal(t, 9090, config.Port)
assert.Equal(t, "info", config.LogsLevel) assert.Equal(t, "info", config.LogLevel)
} }
func TestShouldValidateAndUpdatePort(t *testing.T) { func TestShouldValidateAndUpdatePort(t *testing.T) {
@ -68,12 +68,12 @@ func TestShouldValidateAndUpdateHost(t *testing.T) {
func TestShouldValidateAndUpdateLogsLevel(t *testing.T) { func TestShouldValidateAndUpdateLogsLevel(t *testing.T) {
validator := schema.NewStructValidator() validator := schema.NewStructValidator()
config := newDefaultConfig() config := newDefaultConfig()
config.LogsLevel = "" config.LogLevel = ""
Validate(&config, validator) Validate(&config, validator)
require.Len(t, validator.Errors(), 0) require.Len(t, validator.Errors(), 0)
assert.Equal(t, "info", config.LogsLevel) assert.Equal(t, "info", config.LogLevel)
} }
func TestShouldEnsureNotifierConfigIsProvided(t *testing.T) { func TestShouldEnsureNotifierConfigIsProvided(t *testing.T) {

View File

@ -1,16 +1,12 @@
package logging package logging
import ( import (
"os"
logrus_stack "github.com/Gurpartap/logrus-stack" logrus_stack "github.com/Gurpartap/logrus-stack"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
) )
func init() {
callerLevels := []logrus.Level{}
stackLevels := []logrus.Level{logrus.PanicLevel, logrus.FatalLevel, logrus.ErrorLevel}
logrus.AddHook(logrus_stack.NewHook(callerLevels, stackLevels))
}
// Logger return the standard logrus logger. // Logger return the standard logrus logger.
func Logger() *logrus.Logger { func Logger() *logrus.Logger {
return logrus.StandardLogger() return logrus.StandardLogger()
@ -20,3 +16,19 @@ func Logger() *logrus.Logger {
func SetLevel(level logrus.Level) { func SetLevel(level logrus.Level) {
logrus.SetLevel(level) logrus.SetLevel(level)
} }
// InitializeLogger initialize logger
func InitializeLogger(filename string) error {
callerLevels := []logrus.Level{}
stackLevels := []logrus.Level{logrus.PanicLevel, logrus.FatalLevel, logrus.ErrorLevel}
logrus.AddHook(logrus_stack.NewHook(callerLevels, stackLevels))
if filename != "" {
f, err := os.OpenFile(filename, os.O_WRONLY|os.O_CREATE, 0600)
if err != nil {
return err
}
logrus.SetOutput(f)
}
return nil
}

View File

@ -0,0 +1,34 @@
package logging
import (
"fmt"
"io/ioutil"
"log"
"os"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestShouldWriteLogsToFile(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(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\"\n")
}

View File

@ -4,7 +4,7 @@
port: 9091 port: 9091
logs_level: debug log_level: debug
jwt_secret: unsecure_secret jwt_secret: unsecure_secret

View File

@ -4,7 +4,7 @@
port: 9091 port: 9091
logs_level: debug log_level: debug
default_redirection_url: https://home.example.com:8080/ default_redirection_url: https://home.example.com:8080/

View File

@ -4,7 +4,7 @@
port: 9091 port: 9091
logs_level: trace log_level: trace
default_redirection_url: https://home.example.com:8080/ default_redirection_url: https://home.example.com:8080/

View File

@ -4,7 +4,7 @@
port: 9091 port: 9091
logs_level: debug log_level: debug
jwt_secret: unsecure_secret jwt_secret: unsecure_secret

View File

@ -8,7 +8,7 @@ port: 9091
# Log level # Log level
# #
# Level of verbosity for logs # Level of verbosity for logs
logs_level: debug log_level: debug
jwt_secret: unsecure_secret jwt_secret: unsecure_secret

View File

@ -4,7 +4,7 @@
port: 9091 port: 9091
logs_level: debug log_level: debug
default_redirection_url: https://home.example.com:8080/ default_redirection_url: https://home.example.com:8080/

View File

@ -4,7 +4,7 @@
port: 9091 port: 9091
logs_level: debug log_level: debug
default_redirection_url: https://home.example.com:8080/ default_redirection_url: https://home.example.com:8080/

View File

@ -4,7 +4,7 @@
port: 9091 port: 9091
logs_level: debug log_level: debug
default_redirection_url: https://home.example.com:8080/ default_redirection_url: https://home.example.com:8080/

View File

@ -4,7 +4,7 @@
port: 9091 port: 9091
logs_level: debug log_level: debug
jwt_secret: unsecure_password jwt_secret: unsecure_password

View File

@ -4,7 +4,7 @@
port: 9091 port: 9091
logs_level: debug log_level: debug
default_redirection_url: https://home.example.com:8080/ default_redirection_url: https://home.example.com:8080/

View File

@ -4,7 +4,7 @@
port: 9091 port: 9091
logs_level: debug log_level: debug
default_redirection_url: https://home.example.com:8080/ default_redirection_url: https://home.example.com:8080/

View File

@ -4,7 +4,7 @@
port: 9091 port: 9091
logs_level: debug log_level: debug
jwt_secret: unsecure_secret jwt_secret: unsecure_secret

View File

@ -6,7 +6,7 @@ port: 9091
tls_cert: /var/lib/authelia/ssl/cert.pem tls_cert: /var/lib/authelia/ssl/cert.pem
tls_key: /var/lib/authelia/ssl/key.pem tls_key: /var/lib/authelia/ssl/key.pem
logs_level: debug log_level: debug
authentication_backend: authentication_backend:
file: file:

View File

@ -4,7 +4,7 @@
port: 9091 port: 9091
logs_level: debug log_level: debug
jwt_secret: unsecure_secret jwt_secret: unsecure_secret

View File

@ -4,7 +4,7 @@
port: 9091 port: 9091
logs_level: debug log_level: debug
jwt_secret: unsecure_secret jwt_secret: unsecure_secret

View File

@ -3,7 +3,7 @@
############################################################### ###############################################################
port: 80 port: 80
logs_level: debug log_level: debug
default_redirection_url: https://home.example.com:8080 default_redirection_url: https://home.example.com:8080