[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
parent
6af27cb3f9
commit
c429488738
|
@ -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
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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 == "" {
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
||||||
|
|
|
@ -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")
|
||||||
|
}
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
port: 9091
|
port: 9091
|
||||||
|
|
||||||
logs_level: debug
|
log_level: debug
|
||||||
|
|
||||||
jwt_secret: unsecure_secret
|
jwt_secret: unsecure_secret
|
||||||
|
|
||||||
|
|
|
@ -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/
|
||||||
|
|
||||||
|
|
|
@ -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/
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
port: 9091
|
port: 9091
|
||||||
|
|
||||||
logs_level: debug
|
log_level: debug
|
||||||
|
|
||||||
jwt_secret: unsecure_secret
|
jwt_secret: unsecure_secret
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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/
|
||||||
|
|
||||||
|
|
|
@ -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/
|
||||||
|
|
||||||
|
|
|
@ -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/
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
port: 9091
|
port: 9091
|
||||||
|
|
||||||
logs_level: debug
|
log_level: debug
|
||||||
|
|
||||||
jwt_secret: unsecure_password
|
jwt_secret: unsecure_password
|
||||||
|
|
||||||
|
|
|
@ -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/
|
||||||
|
|
||||||
|
|
|
@ -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/
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
port: 9091
|
port: 9091
|
||||||
|
|
||||||
logs_level: debug
|
log_level: debug
|
||||||
|
|
||||||
jwt_secret: unsecure_secret
|
jwt_secret: unsecure_secret
|
||||||
|
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
port: 9091
|
port: 9091
|
||||||
|
|
||||||
logs_level: debug
|
log_level: debug
|
||||||
|
|
||||||
jwt_secret: unsecure_secret
|
jwt_secret: unsecure_secret
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
port: 9091
|
port: 9091
|
||||||
|
|
||||||
logs_level: debug
|
log_level: debug
|
||||||
|
|
||||||
jwt_secret: unsecure_secret
|
jwt_secret: unsecure_secret
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue