Backport of fix `-log-file` so that it uses the correct name and only adds timestamps on rotation into release/1.14.x (#24322)
* backport of commit 06b9325bb9e6616789c4fe5e7778459ba98a14ab * fix server.go imports --------- Co-authored-by: Peter Wilson <peter.wilson@hashicorp.com>
This commit is contained in:
parent
062747a05d
commit
5efd02708e
|
@ -0,0 +1,2 @@
|
||||||
|
```release-note:change
|
||||||
|
logging: Vault server, Agent and Proxy now honor log file value and only add a timestamp on rotation.
|
|
@ -20,7 +20,7 @@ import (
|
||||||
|
|
||||||
systemd "github.com/coreos/go-systemd/daemon"
|
systemd "github.com/coreos/go-systemd/daemon"
|
||||||
ctconfig "github.com/hashicorp/consul-template/config"
|
ctconfig "github.com/hashicorp/consul-template/config"
|
||||||
hclog "github.com/hashicorp/go-hclog"
|
"github.com/hashicorp/go-hclog"
|
||||||
"github.com/hashicorp/go-multierror"
|
"github.com/hashicorp/go-multierror"
|
||||||
"github.com/hashicorp/go-secure-stdlib/gatedwriter"
|
"github.com/hashicorp/go-secure-stdlib/gatedwriter"
|
||||||
"github.com/hashicorp/go-secure-stdlib/parseutil"
|
"github.com/hashicorp/go-secure-stdlib/parseutil"
|
||||||
|
@ -39,7 +39,7 @@ import (
|
||||||
"github.com/hashicorp/vault/command/agent/template"
|
"github.com/hashicorp/vault/command/agent/template"
|
||||||
"github.com/hashicorp/vault/command/agentproxyshared"
|
"github.com/hashicorp/vault/command/agentproxyshared"
|
||||||
"github.com/hashicorp/vault/command/agentproxyshared/auth"
|
"github.com/hashicorp/vault/command/agentproxyshared/auth"
|
||||||
cache "github.com/hashicorp/vault/command/agentproxyshared/cache"
|
"github.com/hashicorp/vault/command/agentproxyshared/cache"
|
||||||
"github.com/hashicorp/vault/command/agentproxyshared/sink"
|
"github.com/hashicorp/vault/command/agentproxyshared/sink"
|
||||||
"github.com/hashicorp/vault/command/agentproxyshared/sink/file"
|
"github.com/hashicorp/vault/command/agentproxyshared/sink/file"
|
||||||
"github.com/hashicorp/vault/command/agentproxyshared/sink/inmem"
|
"github.com/hashicorp/vault/command/agentproxyshared/sink/inmem"
|
||||||
|
@ -63,6 +63,7 @@ const (
|
||||||
// flagNameAgentExitAfterAuth is used as an Agent specific flag to indicate
|
// flagNameAgentExitAfterAuth is used as an Agent specific flag to indicate
|
||||||
// that agent should exit after a single successful auth
|
// that agent should exit after a single successful auth
|
||||||
flagNameAgentExitAfterAuth = "exit-after-auth"
|
flagNameAgentExitAfterAuth = "exit-after-auth"
|
||||||
|
nameAgent = "agent"
|
||||||
)
|
)
|
||||||
|
|
||||||
type AgentCommand struct {
|
type AgentCommand struct {
|
||||||
|
@ -1123,15 +1124,17 @@ func (c *AgentCommand) newLogger() (hclog.InterceptLogger, error) {
|
||||||
return nil, errs
|
return nil, errs
|
||||||
}
|
}
|
||||||
|
|
||||||
logCfg := &logging.LogConfig{
|
logCfg, err := logging.NewLogConfig(nameAgent)
|
||||||
Name: "agent",
|
if err != nil {
|
||||||
LogLevel: logLevel,
|
return nil, err
|
||||||
LogFormat: logFormat,
|
|
||||||
LogFilePath: c.config.LogFile,
|
|
||||||
LogRotateDuration: logRotateDuration,
|
|
||||||
LogRotateBytes: c.config.LogRotateBytes,
|
|
||||||
LogRotateMaxFiles: c.config.LogRotateMaxFiles,
|
|
||||||
}
|
}
|
||||||
|
logCfg.Name = nameAgent
|
||||||
|
logCfg.LogLevel = logLevel
|
||||||
|
logCfg.LogFormat = logFormat
|
||||||
|
logCfg.LogFilePath = c.config.LogFile
|
||||||
|
logCfg.LogRotateDuration = logRotateDuration
|
||||||
|
logCfg.LogRotateBytes = c.config.LogRotateBytes
|
||||||
|
logCfg.LogRotateMaxFiles = c.config.LogRotateMaxFiles
|
||||||
|
|
||||||
l, err := logging.Setup(logCfg, c.logWriter)
|
l, err := logging.Setup(logCfg, c.logWriter)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -27,7 +27,7 @@ import (
|
||||||
"github.com/hashicorp/vault/api"
|
"github.com/hashicorp/vault/api"
|
||||||
"github.com/hashicorp/vault/command/agentproxyshared"
|
"github.com/hashicorp/vault/command/agentproxyshared"
|
||||||
"github.com/hashicorp/vault/command/agentproxyshared/auth"
|
"github.com/hashicorp/vault/command/agentproxyshared/auth"
|
||||||
cache "github.com/hashicorp/vault/command/agentproxyshared/cache"
|
"github.com/hashicorp/vault/command/agentproxyshared/cache"
|
||||||
"github.com/hashicorp/vault/command/agentproxyshared/sink"
|
"github.com/hashicorp/vault/command/agentproxyshared/sink"
|
||||||
"github.com/hashicorp/vault/command/agentproxyshared/sink/file"
|
"github.com/hashicorp/vault/command/agentproxyshared/sink/file"
|
||||||
"github.com/hashicorp/vault/command/agentproxyshared/sink/inmem"
|
"github.com/hashicorp/vault/command/agentproxyshared/sink/inmem"
|
||||||
|
@ -59,6 +59,7 @@ const (
|
||||||
// flagNameProxyExitAfterAuth is used as a Proxy specific flag to indicate
|
// flagNameProxyExitAfterAuth is used as a Proxy specific flag to indicate
|
||||||
// that proxy should exit after a single successful auth
|
// that proxy should exit after a single successful auth
|
||||||
flagNameProxyExitAfterAuth = "exit-after-auth"
|
flagNameProxyExitAfterAuth = "exit-after-auth"
|
||||||
|
nameProxy = "proxy"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ProxyCommand struct {
|
type ProxyCommand struct {
|
||||||
|
@ -983,15 +984,17 @@ func (c *ProxyCommand) newLogger() (log.InterceptLogger, error) {
|
||||||
return nil, errors
|
return nil, errors
|
||||||
}
|
}
|
||||||
|
|
||||||
logCfg := &logging.LogConfig{
|
logCfg, err := logging.NewLogConfig(nameProxy)
|
||||||
Name: "proxy",
|
if err != nil {
|
||||||
LogLevel: logLevel,
|
return nil, err
|
||||||
LogFormat: logFormat,
|
|
||||||
LogFilePath: c.config.LogFile,
|
|
||||||
LogRotateDuration: logRotateDuration,
|
|
||||||
LogRotateBytes: c.config.LogRotateBytes,
|
|
||||||
LogRotateMaxFiles: c.config.LogRotateMaxFiles,
|
|
||||||
}
|
}
|
||||||
|
logCfg.Name = nameProxy
|
||||||
|
logCfg.LogLevel = logLevel
|
||||||
|
logCfg.LogFormat = logFormat
|
||||||
|
logCfg.LogFilePath = c.config.LogFile
|
||||||
|
logCfg.LogRotateDuration = logRotateDuration
|
||||||
|
logCfg.LogRotateBytes = c.config.LogRotateBytes
|
||||||
|
logCfg.LogRotateMaxFiles = c.config.LogRotateMaxFiles
|
||||||
|
|
||||||
l, err := logging.Setup(logCfg, c.logWriter)
|
l, err := logging.Setup(logCfg, c.logWriter)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -1815,14 +1815,16 @@ func (c *ServerCommand) configureLogging(config *server.Config) (hclog.Intercept
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
logCfg := &loghelper.LogConfig{
|
logCfg, err := loghelper.NewLogConfig("vault")
|
||||||
LogLevel: logLevel,
|
if err != nil {
|
||||||
LogFormat: logFormat,
|
return nil, err
|
||||||
LogFilePath: config.LogFile,
|
|
||||||
LogRotateDuration: logRotateDuration,
|
|
||||||
LogRotateBytes: config.LogRotateBytes,
|
|
||||||
LogRotateMaxFiles: config.LogRotateMaxFiles,
|
|
||||||
}
|
}
|
||||||
|
logCfg.LogLevel = logLevel
|
||||||
|
logCfg.LogFormat = logFormat
|
||||||
|
logCfg.LogFilePath = config.LogFile
|
||||||
|
logCfg.LogRotateDuration = logRotateDuration
|
||||||
|
logCfg.LogRotateBytes = config.LogRotateBytes
|
||||||
|
logCfg.LogRotateMaxFiles = config.LogRotateMaxFiles
|
||||||
|
|
||||||
return loghelper.Setup(logCfg, c.logWriter)
|
return loghelper.Setup(logCfg, c.logWriter)
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,7 +57,8 @@ func (l *LogFile) Write(b []byte) (n int, err error) {
|
||||||
if err := l.openNew(); err != nil {
|
if err := l.openNew(); err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
} else if err := l.rotate(); err != nil { // Check for the last contact and rotate if necessary
|
}
|
||||||
|
if err := l.rotate(); err != nil { // Check for the last contact and rotate if necessary
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,21 +83,20 @@ func (l *LogFile) fileNamePattern() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *LogFile) openNew() error {
|
func (l *LogFile) openNew() error {
|
||||||
fileNamePattern := l.fileNamePattern()
|
newFileName := l.fileName
|
||||||
|
|
||||||
createTime := now()
|
|
||||||
newFileName := fmt.Sprintf(fileNamePattern, strconv.FormatInt(createTime.UnixNano(), 10))
|
|
||||||
newFilePath := filepath.Join(l.logPath, newFileName)
|
newFilePath := filepath.Join(l.logPath, newFileName)
|
||||||
|
|
||||||
// Try creating a file. We truncate the file because we are the only authority to write the logs
|
// Try creating or opening the active log file. Since the active log file
|
||||||
filePointer, err := os.OpenFile(newFilePath, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0o640)
|
// always has the same name, append log entries to prevent overwriting
|
||||||
|
// previous log data.
|
||||||
|
filePointer, err := os.OpenFile(newFilePath, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0o640)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// New file, new 'bytes' tracker, new creation time :) :)
|
// New file, new bytes tracker, new creation time :)
|
||||||
l.fileInfo = filePointer
|
l.fileInfo = filePointer
|
||||||
l.lastCreated = createTime
|
l.lastCreated = now()
|
||||||
l.bytesWritten = 0
|
l.bytesWritten = 0
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -109,6 +109,9 @@ func (l *LogFile) rotate() error {
|
||||||
if err := l.fileInfo.Close(); err != nil {
|
if err := l.fileInfo.Close(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if err := l.renameCurrentFile(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
if err := l.pruneFiles(); err != nil {
|
if err := l.pruneFiles(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -148,3 +151,13 @@ func removeFiles(files []string) (err error) {
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (l *LogFile) renameCurrentFile() error {
|
||||||
|
fileNamePattern := l.fileNamePattern()
|
||||||
|
createTime := now()
|
||||||
|
currentFilePath := filepath.Join(l.logPath, l.fileName)
|
||||||
|
oldFileName := fmt.Sprintf(fileNamePattern, strconv.FormatInt(createTime.UnixNano(), 10))
|
||||||
|
oldFilePath := filepath.Join(l.logPath, oldFileName)
|
||||||
|
|
||||||
|
return os.Rename(currentFilePath, oldFilePath)
|
||||||
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
log "github.com/hashicorp/go-hclog"
|
"github.com/hashicorp/go-hclog"
|
||||||
"github.com/hashicorp/go-multierror"
|
"github.com/hashicorp/go-multierror"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -32,7 +32,7 @@ type LogConfig struct {
|
||||||
Name string
|
Name string
|
||||||
|
|
||||||
// LogLevel is the minimum level to be logged.
|
// LogLevel is the minimum level to be logged.
|
||||||
LogLevel log.Level
|
LogLevel hclog.Level
|
||||||
|
|
||||||
// LogFormat is the log format to use, supported formats are 'standard' and 'json'.
|
// LogFormat is the log format to use, supported formats are 'standard' and 'json'.
|
||||||
LogFormat LogFormat
|
LogFormat LogFormat
|
||||||
|
@ -48,10 +48,27 @@ type LogConfig struct {
|
||||||
|
|
||||||
// LogRotateMaxFiles is the maximum number of past archived log files to keep
|
// LogRotateMaxFiles is the maximum number of past archived log files to keep
|
||||||
LogRotateMaxFiles int
|
LogRotateMaxFiles int
|
||||||
|
|
||||||
|
// DefaultFileName should be set to the value to be used if the LogFilePath
|
||||||
|
// ends in a path separator such as '/var/log/'
|
||||||
|
// Examples of the default name are as follows: 'vault', 'agent' or 'proxy.
|
||||||
|
// The creator of this struct *must* ensure that it is assigned before doing
|
||||||
|
// anything with LogConfig!
|
||||||
|
DefaultFileName string
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewLogConfig should be used to initialize the LogConfig struct.
|
||||||
|
func NewLogConfig(defaultFileName string) (*LogConfig, error) {
|
||||||
|
defaultFileName = strings.TrimSpace(defaultFileName)
|
||||||
|
if defaultFileName == "" {
|
||||||
|
return nil, errors.New("default file name is required")
|
||||||
|
}
|
||||||
|
|
||||||
|
return &LogConfig{DefaultFileName: defaultFileName}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *LogConfig) isLevelInvalid() bool {
|
func (c *LogConfig) isLevelInvalid() bool {
|
||||||
return c.LogLevel == log.NoLevel || c.LogLevel == log.Off || c.LogLevel.String() == "unknown"
|
return c.LogLevel == hclog.NoLevel || c.LogLevel == hclog.Off || c.LogLevel.String() == "unknown"
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *LogConfig) isFormatJson() bool {
|
func (c *LogConfig) isFormatJson() bool {
|
||||||
|
@ -104,7 +121,7 @@ func parseFullPath(fullPath string) (directory, fileName string, err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Setup creates a new logger with the specified configuration and writer
|
// Setup creates a new logger with the specified configuration and writer
|
||||||
func Setup(config *LogConfig, w io.Writer) (log.InterceptLogger, error) {
|
func Setup(config *LogConfig, w io.Writer) (hclog.InterceptLogger, error) {
|
||||||
// Validate the log level
|
// Validate the log level
|
||||||
if config.isLevelInvalid() {
|
if config.isLevelInvalid() {
|
||||||
return nil, fmt.Errorf("invalid log level: %v", config.LogLevel)
|
return nil, fmt.Errorf("invalid log level: %v", config.LogLevel)
|
||||||
|
@ -121,7 +138,9 @@ func Setup(config *LogConfig, w io.Writer) (log.InterceptLogger, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
if fileName == "" {
|
||||||
|
fileName = fmt.Sprintf("%s.log", config.DefaultFileName)
|
||||||
|
}
|
||||||
if config.LogRotateDuration == 0 {
|
if config.LogRotateDuration == 0 {
|
||||||
config.LogRotateDuration = defaultRotateDuration
|
config.LogRotateDuration = defaultRotateDuration
|
||||||
}
|
}
|
||||||
|
@ -142,7 +161,7 @@ func Setup(config *LogConfig, w io.Writer) (log.InterceptLogger, error) {
|
||||||
writers = append(writers, logFile)
|
writers = append(writers, logFile)
|
||||||
}
|
}
|
||||||
|
|
||||||
logger := log.NewInterceptLogger(&log.LoggerOptions{
|
logger := hclog.NewInterceptLogger(&hclog.LoggerOptions{
|
||||||
Name: config.Name,
|
Name: config.Name,
|
||||||
Level: config.LogLevel,
|
Level: config.LogLevel,
|
||||||
IndependentLevels: true,
|
IndependentLevels: true,
|
||||||
|
@ -169,21 +188,21 @@ func ParseLogFormat(format string) (LogFormat, error) {
|
||||||
|
|
||||||
// ParseLogLevel returns the hclog.Level that corresponds with the provided level string.
|
// ParseLogLevel returns the hclog.Level that corresponds with the provided level string.
|
||||||
// This differs hclog.LevelFromString in that it supports additional level strings.
|
// This differs hclog.LevelFromString in that it supports additional level strings.
|
||||||
func ParseLogLevel(logLevel string) (log.Level, error) {
|
func ParseLogLevel(logLevel string) (hclog.Level, error) {
|
||||||
var result log.Level
|
var result hclog.Level
|
||||||
logLevel = strings.ToLower(strings.TrimSpace(logLevel))
|
logLevel = strings.ToLower(strings.TrimSpace(logLevel))
|
||||||
|
|
||||||
switch logLevel {
|
switch logLevel {
|
||||||
case "trace":
|
case "trace":
|
||||||
result = log.Trace
|
result = hclog.Trace
|
||||||
case "debug":
|
case "debug":
|
||||||
result = log.Debug
|
result = hclog.Debug
|
||||||
case "notice", "info", "":
|
case "notice", "info", "":
|
||||||
result = log.Info
|
result = hclog.Info
|
||||||
case "warn", "warning":
|
case "warn", "warning":
|
||||||
result = log.Warn
|
result = hclog.Warn
|
||||||
case "err", "error":
|
case "err", "error":
|
||||||
result = log.Error
|
result = hclog.Error
|
||||||
default:
|
default:
|
||||||
return -1, errors.New(fmt.Sprintf("unknown log level: %s", logLevel))
|
return -1, errors.New(fmt.Sprintf("unknown log level: %s", logLevel))
|
||||||
}
|
}
|
||||||
|
@ -192,11 +211,11 @@ func ParseLogLevel(logLevel string) (log.Level, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// TranslateLoggerLevel returns the string that corresponds with logging level of the hclog.Logger.
|
// TranslateLoggerLevel returns the string that corresponds with logging level of the hclog.Logger.
|
||||||
func TranslateLoggerLevel(logger log.Logger) (string, error) {
|
func TranslateLoggerLevel(logger hclog.Logger) (string, error) {
|
||||||
logLevel := logger.GetLevel()
|
logLevel := logger.GetLevel()
|
||||||
|
|
||||||
switch logLevel {
|
switch logLevel {
|
||||||
case log.Trace, log.Debug, log.Info, log.Warn, log.Error:
|
case hclog.Trace, hclog.Debug, hclog.Info, hclog.Warn, hclog.Error:
|
||||||
return logLevel.String(), nil
|
return logLevel.String(), nil
|
||||||
default:
|
default:
|
||||||
return "", fmt.Errorf("unknown log level")
|
return "", fmt.Errorf("unknown log level")
|
||||||
|
|
|
@ -8,15 +8,17 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"os"
|
"os"
|
||||||
|
"path/filepath"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
log "github.com/hashicorp/go-hclog"
|
"github.com/hashicorp/go-hclog"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestLogger_SetupBasic(t *testing.T) {
|
func TestLogger_SetupBasic(t *testing.T) {
|
||||||
cfg := &LogConfig{Name: "test-system", LogLevel: log.Info}
|
cfg := newTestLogConfig(t)
|
||||||
|
cfg.LogLevel = hclog.Info
|
||||||
|
|
||||||
logger, err := Setup(cfg, nil)
|
logger, err := Setup(cfg, nil)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
@ -26,16 +28,15 @@ func TestLogger_SetupBasic(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestLogger_SetupInvalidLogLevel(t *testing.T) {
|
func TestLogger_SetupInvalidLogLevel(t *testing.T) {
|
||||||
cfg := &LogConfig{}
|
cfg := newTestLogConfig(t)
|
||||||
|
|
||||||
_, err := Setup(cfg, nil)
|
_, err := Setup(cfg, nil)
|
||||||
assert.Containsf(t, err.Error(), "invalid log level", "expected error %s", err)
|
assert.Containsf(t, err.Error(), "invalid log level", "expected error %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestLogger_SetupLoggerErrorLevel(t *testing.T) {
|
func TestLogger_SetupLoggerErrorLevel(t *testing.T) {
|
||||||
cfg := &LogConfig{
|
cfg := newTestLogConfig(t)
|
||||||
LogLevel: log.Error,
|
cfg.LogLevel = hclog.Error
|
||||||
}
|
|
||||||
|
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
|
|
||||||
|
@ -48,15 +49,16 @@ func TestLogger_SetupLoggerErrorLevel(t *testing.T) {
|
||||||
|
|
||||||
output := buf.String()
|
output := buf.String()
|
||||||
|
|
||||||
require.Contains(t, output, "[ERROR] test error msg")
|
require.Contains(t, output, "[ERROR] test-system: test error msg")
|
||||||
require.NotContains(t, output, "[INFO] test info msg")
|
require.NotContains(t, output, "[INFO] test-system: test info msg")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestLogger_SetupLoggerDebugLevel(t *testing.T) {
|
func TestLogger_SetupLoggerDebugLevel(t *testing.T) {
|
||||||
cfg := LogConfig{LogLevel: log.Debug}
|
cfg := newTestLogConfig(t)
|
||||||
|
cfg.LogLevel = hclog.Debug
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
|
|
||||||
logger, err := Setup(&cfg, &buf)
|
logger, err := Setup(cfg, &buf)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NotNil(t, logger)
|
require.NotNil(t, logger)
|
||||||
|
|
||||||
|
@ -65,15 +67,14 @@ func TestLogger_SetupLoggerDebugLevel(t *testing.T) {
|
||||||
|
|
||||||
output := buf.String()
|
output := buf.String()
|
||||||
|
|
||||||
require.Contains(t, output, "[INFO] test info msg")
|
require.Contains(t, output, "[INFO] test-system: test info msg")
|
||||||
require.Contains(t, output, "[DEBUG] test debug msg")
|
require.Contains(t, output, "[DEBUG] test-system: test debug msg")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestLogger_SetupLoggerWithName(t *testing.T) {
|
func TestLogger_SetupLoggerWithoutName(t *testing.T) {
|
||||||
cfg := &LogConfig{
|
cfg := newTestLogConfig(t)
|
||||||
LogLevel: log.Debug,
|
cfg.Name = ""
|
||||||
Name: "test-system",
|
cfg.LogLevel = hclog.Info
|
||||||
}
|
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
|
|
||||||
logger, err := Setup(cfg, &buf)
|
logger, err := Setup(cfg, &buf)
|
||||||
|
@ -82,15 +83,13 @@ func TestLogger_SetupLoggerWithName(t *testing.T) {
|
||||||
|
|
||||||
logger.Warn("test warn msg")
|
logger.Warn("test warn msg")
|
||||||
|
|
||||||
require.Contains(t, buf.String(), "[WARN] test-system: test warn msg")
|
require.Contains(t, buf.String(), "[WARN] test warn msg")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestLogger_SetupLoggerWithJSON(t *testing.T) {
|
func TestLogger_SetupLoggerWithJSON(t *testing.T) {
|
||||||
cfg := &LogConfig{
|
cfg := newTestLogConfig(t)
|
||||||
LogLevel: log.Debug,
|
cfg.LogLevel = hclog.Debug
|
||||||
LogFormat: JSONFormat,
|
cfg.LogFormat = JSONFormat
|
||||||
Name: "test-system",
|
|
||||||
}
|
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
|
|
||||||
logger, err := Setup(cfg, &buf)
|
logger, err := Setup(cfg, &buf)
|
||||||
|
@ -108,13 +107,68 @@ func TestLogger_SetupLoggerWithJSON(t *testing.T) {
|
||||||
require.Equal(t, jsonOutput["@message"], "test warn msg")
|
require.Equal(t, jsonOutput["@message"], "test warn msg")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestLogger_SetupLoggerWithValidLogPathMissingFileName(t *testing.T) {
|
||||||
|
tmpDir := t.TempDir()
|
||||||
|
cfg := newTestLogConfig(t)
|
||||||
|
cfg.LogLevel = hclog.Info
|
||||||
|
cfg.LogFilePath = tmpDir + "/" // add the trailing slash to the temp dir
|
||||||
|
var buf bytes.Buffer
|
||||||
|
|
||||||
|
logger, err := Setup(cfg, &buf)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotNil(t, logger)
|
||||||
|
|
||||||
|
logger.Info("juan?")
|
||||||
|
|
||||||
|
m, err := filepath.Glob(cfg.LogFilePath + "*")
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Truef(t, len(m) == 1, "no files were found")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLogger_SetupLoggerWithValidLogPathFileName(t *testing.T) {
|
||||||
|
tmpDir := t.TempDir()
|
||||||
|
cfg := newTestLogConfig(t)
|
||||||
|
cfg.LogLevel = hclog.Info
|
||||||
|
cfg.LogFilePath = filepath.Join(tmpDir, "juan.log")
|
||||||
|
var buf bytes.Buffer
|
||||||
|
|
||||||
|
logger, err := Setup(cfg, &buf)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotNil(t, logger)
|
||||||
|
|
||||||
|
logger.Info("juan?")
|
||||||
|
f, err := os.Stat(cfg.LogFilePath)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotNil(t, f)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLogger_SetupLoggerWithValidLogPathFileNameRotate(t *testing.T) {
|
||||||
|
tmpDir := t.TempDir()
|
||||||
|
cfg := newTestLogConfig(t)
|
||||||
|
cfg.LogLevel = hclog.Info
|
||||||
|
cfg.LogFilePath = filepath.Join(tmpDir, "juan.log")
|
||||||
|
cfg.LogRotateBytes = 1 // set a tiny number of bytes to force rotation
|
||||||
|
var buf bytes.Buffer
|
||||||
|
|
||||||
|
logger, err := Setup(cfg, &buf)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotNil(t, logger)
|
||||||
|
|
||||||
|
logger.Info("juan?")
|
||||||
|
logger.Info("john?")
|
||||||
|
f, err := os.Stat(cfg.LogFilePath)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotNil(t, f)
|
||||||
|
m, err := filepath.Glob(tmpDir + "/juan-*") // look for juan-{timestamp}.log
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Truef(t, len(m) == 1, "no files were found")
|
||||||
|
}
|
||||||
|
|
||||||
func TestLogger_SetupLoggerWithValidLogPath(t *testing.T) {
|
func TestLogger_SetupLoggerWithValidLogPath(t *testing.T) {
|
||||||
tmpDir := t.TempDir()
|
tmpDir := t.TempDir()
|
||||||
|
cfg := newTestLogConfig(t)
|
||||||
cfg := &LogConfig{
|
cfg.LogLevel = hclog.Info
|
||||||
LogLevel: log.Info,
|
cfg.LogFilePath = tmpDir + "/" // add the trailing slash to the temp dir
|
||||||
LogFilePath: tmpDir, //+ "/",
|
|
||||||
}
|
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
|
|
||||||
logger, err := Setup(cfg, &buf)
|
logger, err := Setup(cfg, &buf)
|
||||||
|
@ -123,10 +177,10 @@ func TestLogger_SetupLoggerWithValidLogPath(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestLogger_SetupLoggerWithInValidLogPath(t *testing.T) {
|
func TestLogger_SetupLoggerWithInValidLogPath(t *testing.T) {
|
||||||
cfg := &LogConfig{
|
cfg := newTestLogConfig(t)
|
||||||
LogLevel: log.Info,
|
cfg.LogLevel = hclog.Info
|
||||||
LogFilePath: "nonexistentdir/",
|
cfg.LogLevel = hclog.Info
|
||||||
}
|
cfg.LogFilePath = "nonexistentdir/"
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
|
|
||||||
logger, err := Setup(cfg, &buf)
|
logger, err := Setup(cfg, &buf)
|
||||||
|
@ -142,10 +196,9 @@ func TestLogger_SetupLoggerWithInValidLogPathPermission(t *testing.T) {
|
||||||
assert.NoError(t, err, "unexpected error testing with invalid log path permission")
|
assert.NoError(t, err, "unexpected error testing with invalid log path permission")
|
||||||
defer os.RemoveAll(tmpDir)
|
defer os.RemoveAll(tmpDir)
|
||||||
|
|
||||||
cfg := &LogConfig{
|
cfg := newTestLogConfig(t)
|
||||||
LogLevel: log.Info,
|
cfg.LogLevel = hclog.Info
|
||||||
LogFilePath: tmpDir + "/",
|
cfg.LogFilePath = tmpDir + "/"
|
||||||
}
|
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
|
|
||||||
logger, err := Setup(cfg, &buf)
|
logger, err := Setup(cfg, &buf)
|
||||||
|
@ -188,10 +241,10 @@ func TestLogger_SetupLoggerWithInvalidLogFilePath(t *testing.T) {
|
||||||
for name, tc := range cases {
|
for name, tc := range cases {
|
||||||
name := name
|
name := name
|
||||||
tc := tc
|
tc := tc
|
||||||
cfg := &LogConfig{
|
cfg := newTestLogConfig(t)
|
||||||
LogLevel: log.Info,
|
cfg.LogLevel = hclog.Info
|
||||||
LogFilePath: tc.path,
|
cfg.LogFilePath = tc.path
|
||||||
}
|
|
||||||
_, err := Setup(cfg, &bytes.Buffer{})
|
_, err := Setup(cfg, &bytes.Buffer{})
|
||||||
assert.Error(t, err, "%s: expected error due to *", name)
|
assert.Error(t, err, "%s: expected error due to *", name)
|
||||||
assert.Contains(t, err.Error(), tc.message, "%s: error message does not match: %s", name, err.Error())
|
assert.Contains(t, err.Error(), tc.message, "%s: error message does not match: %s", name, err.Error())
|
||||||
|
@ -199,26 +252,34 @@ func TestLogger_SetupLoggerWithInvalidLogFilePath(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestLogger_ChangeLogLevels(t *testing.T) {
|
func TestLogger_ChangeLogLevels(t *testing.T) {
|
||||||
cfg := &LogConfig{
|
cfg := newTestLogConfig(t)
|
||||||
LogLevel: log.Debug,
|
cfg.LogLevel = hclog.Debug
|
||||||
Name: "test-system",
|
|
||||||
}
|
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
|
|
||||||
logger, err := Setup(cfg, &buf)
|
logger, err := Setup(cfg, &buf)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NotNil(t, logger)
|
require.NotNil(t, logger)
|
||||||
|
|
||||||
assert.Equal(t, log.Debug, logger.GetLevel())
|
assert.Equal(t, hclog.Debug, logger.GetLevel())
|
||||||
|
|
||||||
// Create new named loggers from the base logger and change the levels
|
// Create new named loggers from the base logger and change the levels
|
||||||
logger2 := logger.Named("test2")
|
logger2 := logger.Named("test2")
|
||||||
logger3 := logger.Named("test3")
|
logger3 := logger.Named("test3")
|
||||||
|
|
||||||
logger2.SetLevel(log.Info)
|
logger2.SetLevel(hclog.Info)
|
||||||
logger3.SetLevel(log.Error)
|
logger3.SetLevel(hclog.Error)
|
||||||
|
|
||||||
assert.Equal(t, log.Debug, logger.GetLevel())
|
assert.Equal(t, hclog.Debug, logger.GetLevel())
|
||||||
assert.Equal(t, log.Info, logger2.GetLevel())
|
assert.Equal(t, hclog.Info, logger2.GetLevel())
|
||||||
assert.Equal(t, log.Error, logger3.GetLevel())
|
assert.Equal(t, hclog.Error, logger3.GetLevel())
|
||||||
|
}
|
||||||
|
|
||||||
|
func newTestLogConfig(t *testing.T) *LogConfig {
|
||||||
|
t.Helper()
|
||||||
|
|
||||||
|
cfg, err := NewLogConfig("test")
|
||||||
|
require.NoError(t, err)
|
||||||
|
cfg.Name = "test-system"
|
||||||
|
|
||||||
|
return cfg
|
||||||
}
|
}
|
||||||
|
|
|
@ -83,14 +83,17 @@ See the [caching](/vault/docs/agent-and-proxy/agent/caching#api) page for detail
|
||||||
are `standard` and `json`. This can also be specified via the
|
are `standard` and `json`. This can also be specified via the
|
||||||
`VAULT_LOG_FORMAT` environment variable.
|
`VAULT_LOG_FORMAT` environment variable.
|
||||||
|
|
||||||
- `-log-file` ((#\_log_file)) - writes all the Vault agent log messages
|
- `-log-file` ((#\_log_file)) - the absolute path where Vault Agent should save
|
||||||
to a file. This value is used as a prefix for the log file name. The current timestamp
|
log messages. Paths that end with a path separator use the default file name,
|
||||||
is appended to the file name. If the value ends in a path separator, `vault-agent`
|
`agent.log`. Paths that do not end with a file extension use the default
|
||||||
will be appended to the value. If the file name is missing an extension, `.log`
|
`.log` extension. If the log file rotates, Vault Agent appends the current
|
||||||
is appended. For example, setting `log-file` to `/var/log/` would result in a log
|
timestamp to the file name at the time of rotation. For example:
|
||||||
file path of `/var/log/vault-agent-{timestamp}.log`. `log-file` can be combined with
|
|
||||||
[`-log-rotate-bytes`](#_log_rotate_bytes) and [`-log-rotate-duration`](#_log_rotate_duration)
|
`log-file` | Full log file | Rotated log file
|
||||||
for a fine-grained log rotation experience.
|
---------- | ------------- | ----------------
|
||||||
|
`/var/log` | `/var/log/agent.log` | `/var/log/agent-{timestamp}.log`
|
||||||
|
`/var/log/my-diary` | `/var/log/my-diary.log` | `/var/log/my-diary-{timestamp}.log`
|
||||||
|
`/var/log/my-diary.txt` | `/var/log/my-diary.txt` | `/var/log/my-diary-{timestamp}.txt`
|
||||||
|
|
||||||
- `-log-rotate-bytes` ((#\_log_rotate_bytes)) - to specify the number of
|
- `-log-rotate-bytes` ((#\_log_rotate_bytes)) - to specify the number of
|
||||||
bytes that should be written to a log before it needs to be rotated. Unless specified,
|
bytes that should be written to a log before it needs to be rotated. Unless specified,
|
||||||
|
|
|
@ -75,14 +75,17 @@ also be specified via the `VAULT_LOG_LEVEL` environment variable.
|
||||||
are `standard` and `json`. This can also be specified via the
|
are `standard` and `json`. This can also be specified via the
|
||||||
`VAULT_LOG_FORMAT` environment variable.
|
`VAULT_LOG_FORMAT` environment variable.
|
||||||
|
|
||||||
- `-log-file` ((#\_log_file)) - writes all the Vault proxy log messages
|
- `-log-file` ((#\_log_file)) - the absolute path where Vault Proxy should save
|
||||||
to a file. This value is used as a prefix for the log file name. The current timestamp
|
log messages. Paths that end with a path separator use the default file name,
|
||||||
is appended to the file name. If the value ends in a path separator, `vault-proxy`
|
`proxy.log`. Paths that do not end with a file extension use the default
|
||||||
will be appended to the value. If the file name is missing an extension, `.log`
|
`.log` extension. If the log file rotates, Vault Proxy appends the current
|
||||||
is appended. For example, setting `log-file` to `/var/log/` would result in a log
|
timestamp to the file name at the time of rotation. For example:
|
||||||
file path of `/var/log/vault-proxy-{timestamp}.log`. `log-file` can be combined with
|
|
||||||
[`-log-rotate-bytes`](#_log_rotate_bytes) and [`-log-rotate-duration`](#_log_rotate_duration)
|
`log-file` | Full log file | Rotated log file
|
||||||
for a fine-grained log rotation experience.
|
---------- | ------------- | ----------------
|
||||||
|
`/var/log` | `/var/log/proxy.log` | `/var/log/proxy-{timestamp}.log`
|
||||||
|
`/var/log/my-diary` | `/var/log/my-diary.log` | `/var/log/my-diary-{timestamp}.log`
|
||||||
|
`/var/log/my-diary.txt` | `/var/log/my-diary.txt` | `/var/log/my-diary-{timestamp}.txt`
|
||||||
|
|
||||||
- `-log-rotate-bytes` ((#\_log_rotate_bytes)) - to specify the number of
|
- `-log-rotate-bytes` ((#\_log_rotate_bytes)) - to specify the number of
|
||||||
bytes that should be written to a log before it needs to be rotated. Unless specified,
|
bytes that should be written to a log before it needs to be rotated. Unless specified,
|
||||||
|
|
|
@ -60,15 +60,18 @@ flags](/vault/docs/commands) included on all commands.
|
||||||
are `standard` and `json`. This can also be specified via the
|
are `standard` and `json`. This can also be specified via the
|
||||||
`VAULT_LOG_FORMAT` environment variable.
|
`VAULT_LOG_FORMAT` environment variable.
|
||||||
|
|
||||||
- `-log-file` ((#\_log_file)) - writes all the Vault log messages
|
- `-log-file` ((#\_log_file)) - the absolute path where Vault should save log
|
||||||
to a file. This value is used as a prefix for the log file name. The current timestamp
|
messages in addition to other, existing outputs like journald / stdout. Paths
|
||||||
is appended to the file name. If the value ends in a path separator, `vault`
|
that end with a path separator use the default file name, `vault.log`. Paths
|
||||||
will be appended to the value. If the file name is missing an extension, `.log`
|
that do not end with a file extension use the default `.log` extension. If the
|
||||||
is appended. For example, setting `log-file` to `/var/log/` would result in a log
|
log file rotates, Vault appends the current timestamp to the file name
|
||||||
file path of `/var/log/vault-{timestamp}.log`. `log-file` can be combined with
|
at the time of rotation. For example:
|
||||||
[`-log-rotate-bytes`](#_log_rotate_bytes) and [`-log-rotate-duration`](#_log_rotate_duration)
|
|
||||||
for a fine-grained log rotation experience. This output operates in addition to existing
|
`log-file` | Full log file | Rotated log file
|
||||||
outputs, meaning logs will continue to be written to journald / stdout (where appropriate).
|
---------- | ------------- | ----------------
|
||||||
|
`/var/log` | `/var/log/vault.log` | `/var/log/vault-{timestamp}.log`
|
||||||
|
`/var/log/my-diary` | `/var/log/my-diary.log` | `/var/log/my-diary-{timestamp}.log`
|
||||||
|
`/var/log/my-diary.txt` | `/var/log/my-diary.txt` | `/var/log/my-diary-{timestamp}.txt`
|
||||||
|
|
||||||
- `-log-rotate-bytes` ((#\_log_rotate_bytes)) - to specify the number of
|
- `-log-rotate-bytes` ((#\_log_rotate_bytes)) - to specify the number of
|
||||||
bytes that should be written to a log before it needs to be rotated. Unless specified,
|
bytes that should be written to a log before it needs to be rotated. Unless specified,
|
||||||
|
|
Loading…
Reference in New Issue