feat: add log-local-time flag for local timezone in logs
Add a --log-local-time flag that configures cloudflared to use local timezone for log timestamps instead of the default UTC. This helps users correlate logs with local system events and other services running in their timezone. The flag can also be set via the TUNNEL_LOG_LOCAL_TIME environment variable. Closes #1530
This commit is contained in:
parent
d7c62aed71
commit
10a654becb
|
|
@ -54,6 +54,12 @@ func ConfigureLoggingFlags(shouldHide bool) []cli.Flag {
|
||||||
EnvVars: []string{"TUNNEL_TRACE_OUTPUT"},
|
EnvVars: []string{"TUNNEL_TRACE_OUTPUT"},
|
||||||
Hidden: shouldHide,
|
Hidden: shouldHide,
|
||||||
}),
|
}),
|
||||||
|
altsrc.NewBoolFlag(&cli.BoolFlag{
|
||||||
|
Name: flags.LogLocalTime,
|
||||||
|
Usage: "Use local timezone for log timestamps instead of UTC.",
|
||||||
|
EnvVars: []string{"TUNNEL_LOG_LOCAL_TIME"},
|
||||||
|
Hidden: shouldHide,
|
||||||
|
}),
|
||||||
FlagLogOutput,
|
FlagLogOutput,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -143,6 +143,9 @@ const (
|
||||||
LogFormatOutputValueDefault = "default"
|
LogFormatOutputValueDefault = "default"
|
||||||
LogFormatOutputValueJSON = "json"
|
LogFormatOutputValueJSON = "json"
|
||||||
|
|
||||||
|
// LogLocalTime uses local timezone instead of UTC for log timestamps.
|
||||||
|
LogLocalTime = "log-local-time"
|
||||||
|
|
||||||
// TraceOutput is the command line flag to set the name of trace output file
|
// TraceOutput is the command line flag to set the name of trace output file
|
||||||
TraceOutput = "trace-output"
|
TraceOutput = "trace-output"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -115,6 +115,7 @@ var (
|
||||||
cfdflags.LogFile,
|
cfdflags.LogFile,
|
||||||
cfdflags.LogDirectory,
|
cfdflags.LogDirectory,
|
||||||
cfdflags.TraceOutput,
|
cfdflags.TraceOutput,
|
||||||
|
cfdflags.LogLocalTime,
|
||||||
cfdflags.ProxyDns,
|
cfdflags.ProxyDns,
|
||||||
"proxy-dns-port",
|
"proxy-dns-port",
|
||||||
"proxy-dns-address",
|
"proxy-dns-address",
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,16 @@ func utcNow() time.Time {
|
||||||
return time.Now().UTC()
|
return time.Now().UTC()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func localNow() time.Time {
|
||||||
|
return time.Now()
|
||||||
|
}
|
||||||
|
|
||||||
|
func configureTimestampFunc(useLocalTime bool) {
|
||||||
|
if useLocalTime {
|
||||||
|
zerolog.TimestampFunc = localNow
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func fallbackLogger(err error) *zerolog.Logger {
|
func fallbackLogger(err error) *zerolog.Logger {
|
||||||
failLog := fallbacklog.With().Logger()
|
failLog := fallbacklog.With().Logger()
|
||||||
fallbacklog.Error().Msgf("Falling back to a default logger due to logger setup failure: %s", err)
|
fallbacklog.Error().Msgf("Falling back to a default logger due to logger setup failure: %s", err)
|
||||||
|
|
@ -146,6 +156,8 @@ func createFromContext(
|
||||||
logDirectoryFlagName string,
|
logDirectoryFlagName string,
|
||||||
disableTerminal bool,
|
disableTerminal bool,
|
||||||
) *zerolog.Logger {
|
) *zerolog.Logger {
|
||||||
|
configureTimestampFunc(c.Bool(cfdflags.LogLocalTime))
|
||||||
|
|
||||||
logLevel := c.String(logLevelFlagName)
|
logLevel := c.String(logLevelFlagName)
|
||||||
logFile := c.String(cfdflags.LogFile)
|
logFile := c.String(cfdflags.LogFile)
|
||||||
logDirectory := c.String(logDirectoryFlagName)
|
logDirectory := c.String(logDirectoryFlagName)
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ package logger
|
||||||
import (
|
import (
|
||||||
"io"
|
"io"
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/rs/zerolog"
|
"github.com/rs/zerolog"
|
||||||
|
|
@ -130,3 +131,28 @@ func TestResilientMultiWriter_Management(t *testing.T) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestTimestampFunctions(t *testing.T) {
|
||||||
|
t.Run("utcNow returns UTC", func(t *testing.T) {
|
||||||
|
ts := utcNow()
|
||||||
|
_, offset := ts.Zone()
|
||||||
|
assert.Equal(t, 0, offset)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("localNow returns local timezone", func(t *testing.T) {
|
||||||
|
ts := localNow()
|
||||||
|
expected := time.Now()
|
||||||
|
_, expectedOffset := expected.Zone()
|
||||||
|
_, actualOffset := ts.Zone()
|
||||||
|
assert.Equal(t, expectedOffset, actualOffset)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("configureTimestampFunc sets local time when true", func(t *testing.T) {
|
||||||
|
configureTimestampFunc(true)
|
||||||
|
ts := zerolog.TimestampFunc()
|
||||||
|
expected := time.Now()
|
||||||
|
_, expectedOffset := expected.Zone()
|
||||||
|
_, actualOffset := ts.Zone()
|
||||||
|
assert.Equal(t, expectedOffset, actualOffset)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue