feat: add option to keep stdout logging with log_file_path (#2037)
Currently if a `log_file_path` is defined Authelia will redirect all logging from standard output to said defined location. This change allows users to keep standard output logging along with a defined `log_file_path`.pull/2048/head
parent
03a1b004cf
commit
05df642f3e
|
@ -52,7 +52,7 @@ func startServer() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := logging.InitializeLogger(config.LogFormat, config.LogFilePath); err != nil {
|
if err := logging.InitializeLogger(config.LogFormat, config.LogFilePath, config.LogKeepStdout); err != nil {
|
||||||
logger.Fatalf("Cannot initialize logger: %v", err)
|
logger.Fatalf("Cannot initialize logger: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -43,6 +43,9 @@ log_level: debug
|
||||||
## File path where the logs will be written. If not set logs are written to stdout.
|
## 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
|
||||||
|
|
||||||
|
## Whether to also log to stdout when a log_file_path is defined.
|
||||||
|
# log_keep_stdout: false
|
||||||
|
|
||||||
## The secret used to generate JWT tokens when validating user identity by email confirmation. JWT Secret can also be
|
## The secret used to generate JWT tokens when validating user identity by email confirmation. JWT Secret can also be
|
||||||
## set using a secret: https://www.authelia.com/docs/configuration/secrets.html
|
## set using a secret: https://www.authelia.com/docs/configuration/secrets.html
|
||||||
jwt_secret: a_very_important_secret
|
jwt_secret: a_very_important_secret
|
||||||
|
|
|
@ -158,6 +158,23 @@ they rotate and/or truncate the logs over time to prevent significant long-term
|
||||||
log_file_path: /config/authelia.log
|
log_file_path: /config/authelia.log
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### log_keep_stdout
|
||||||
|
<div markdown="1">
|
||||||
|
type: boolean
|
||||||
|
{: .label .label-config .label-purple }
|
||||||
|
default: false
|
||||||
|
{: .label .label-config .label-blue }
|
||||||
|
required: no
|
||||||
|
{: .label .label-config .label-green }
|
||||||
|
</div>
|
||||||
|
|
||||||
|
Overrides the behaviour to redirect logging only to the `log_file_path`. If set to `true` logs will be written to both
|
||||||
|
standard output, and the defined logging location.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
log_keep_stdout: true
|
||||||
|
```
|
||||||
|
|
||||||
## jwt_secret
|
## jwt_secret
|
||||||
<div markdown="1">
|
<div markdown="1">
|
||||||
type: string
|
type: string
|
||||||
|
|
|
@ -43,6 +43,9 @@ log_level: debug
|
||||||
## File path where the logs will be written. If not set logs are written to stdout.
|
## 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
|
||||||
|
|
||||||
|
## Whether to also log to stdout when a log_file_path is defined.
|
||||||
|
# log_keep_stdout: false
|
||||||
|
|
||||||
## The secret used to generate JWT tokens when validating user identity by email confirmation. JWT Secret can also be
|
## The secret used to generate JWT tokens when validating user identity by email confirmation. JWT Secret can also be
|
||||||
## set using a secret: https://www.authelia.com/docs/configuration/secrets.html
|
## set using a secret: https://www.authelia.com/docs/configuration/secrets.html
|
||||||
jwt_secret: a_very_important_secret
|
jwt_secret: a_very_important_secret
|
||||||
|
|
|
@ -11,6 +11,7 @@ type Configuration struct {
|
||||||
LogLevel string `mapstructure:"log_level"`
|
LogLevel string `mapstructure:"log_level"`
|
||||||
LogFormat string `mapstructure:"log_format"`
|
LogFormat string `mapstructure:"log_format"`
|
||||||
LogFilePath string `mapstructure:"log_file_path"`
|
LogFilePath string `mapstructure:"log_file_path"`
|
||||||
|
LogKeepStdout bool `mapstructure:"log_keep_stdout"`
|
||||||
JWTSecret string `mapstructure:"jwt_secret"`
|
JWTSecret string `mapstructure:"jwt_secret"`
|
||||||
DefaultRedirectionURL string `mapstructure:"default_redirection_url"`
|
DefaultRedirectionURL string `mapstructure:"default_redirection_url"`
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package logging
|
package logging
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"io"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
logrus_stack "github.com/Gurpartap/logrus-stack"
|
logrus_stack "github.com/Gurpartap/logrus-stack"
|
||||||
|
@ -18,7 +19,7 @@ func SetLevel(level logrus.Level) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// InitializeLogger initialize logger.
|
// InitializeLogger initialize logger.
|
||||||
func InitializeLogger(format, filename string) error {
|
func InitializeLogger(format, filename string, stdout bool) 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))
|
||||||
|
@ -43,7 +44,12 @@ func InitializeLogger(format, filename string) error {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
logrus.SetOutput(f)
|
if stdout {
|
||||||
|
logLocations := io.MultiWriter(os.Stdout, f)
|
||||||
|
logrus.SetOutput(logLocations)
|
||||||
|
} else {
|
||||||
|
logrus.SetOutput(f)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -20,7 +20,30 @@ 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("text", path)
|
err = InitializeLogger("text", path, false)
|
||||||
|
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")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestShouldWriteLogsToFileAndStdout(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("text", path, true)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
Logger().Info("This is a test")
|
Logger().Info("This is a test")
|
||||||
|
@ -43,7 +66,7 @@ func TestShouldFormatLogsAsJSON(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("json", path)
|
err = InitializeLogger("json", path, false)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
Logger().Info("This is a test")
|
Logger().Info("This is a test")
|
||||||
|
|
Loading…
Reference in New Issue