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:
hc-github-team-secure-vault-core 2023-12-01 07:33:09 -05:00 committed by GitHub
parent 062747a05d
commit 5efd02708e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 237 additions and 125 deletions

2
changelog/24297.txt Normal file
View File

@ -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.

View File

@ -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 {

View File

@ -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 {

View File

@ -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)
} }

View File

@ -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)
}

View File

@ -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")

View File

@ -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
} }

View File

@ -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,

View File

@ -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,

View File

@ -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,