Skip to content

Commit

Permalink
add log sub config section
Browse files Browse the repository at this point in the history
  • Loading branch information
Yaiba committed Mar 3, 2025
1 parent e1a191d commit 6f4946b
Show file tree
Hide file tree
Showing 5 changed files with 70 additions and 49 deletions.
18 changes: 9 additions & 9 deletions app/node/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,20 +48,20 @@ type server struct {
}

func runNode(ctx context.Context, rootDir string, cfg *config.Config, autogen bool, dbOwner string) (err error) {
logOutputPaths := slices.Clone(cfg.LogOutput)
logOutputPaths := slices.Clone(cfg.Log.Output)
var logWriters []io.Writer
if idx := slices.Index(cfg.LogOutput, "stdout"); idx != -1 {
if idx := slices.Index(cfg.Log.Output, "stdout"); idx != -1 {
logWriters = append(logWriters, os.Stdout)
cfg.LogOutput = slices.Delete(cfg.LogOutput, idx, idx+1)
cfg.Log.Output = slices.Delete(cfg.Log.Output, idx, idx+1)
}
if idx := slices.Index(cfg.LogOutput, "stderr"); idx != -1 {
if idx := slices.Index(cfg.Log.Output, "stderr"); idx != -1 {
logWriters = append(logWriters, os.Stderr)
cfg.LogOutput = slices.Delete(cfg.LogOutput, idx, idx+1)
cfg.Log.Output = slices.Delete(cfg.Log.Output, idx, idx+1)
}

for _, logFile := range cfg.LogOutput {
for _, logFile := range cfg.Log.Output {
rootedLogFile := rootedPath(logFile, rootDir)
rot, err := log.NewRotatorWriter(rootedLogFile, cfg.LogFileRollSize, cfg.LogRetainMaxRolls)
rot, err := log.NewRotatorWriter(rootedLogFile, cfg.Log.FileRollSize, cfg.Log.RetainMaxRolls)
if err != nil {
return fmt.Errorf("failed to create log rotator: %w", err)
}
Expand All @@ -77,7 +77,7 @@ func runNode(ctx context.Context, rootDir string, cfg *config.Config, autogen bo
if len(logWriters) > 0 {
logWriter := io.MultiWriter(logWriters...)

logger = log.New(log.WithLevel(cfg.LogLevel), log.WithFormat(cfg.LogFormat),
logger = log.New(log.WithLevel(cfg.Log.Level), log.WithFormat(cfg.Log.Format),
log.WithName("KWILD"), log.WithWriter(logWriter))
// NOTE: level and name can be set independently for different systems
}
Expand Down Expand Up @@ -146,7 +146,7 @@ func runNode(ctx context.Context, rootDir string, cfg *config.Config, autogen bo

if !fileExists(tomlFile) {
logger.Infof("Writing config file to %s", tomlFile)
cfg.LogOutput = logOutputPaths // restore log output paths before writing toml file
cfg.Log.Output = logOutputPaths // restore log output paths before writing toml file
if err := cfg.SaveAs(tomlFile); err != nil {
return fmt.Errorf("failed to write config file: %w", err)
}
Expand Down
26 changes: 16 additions & 10 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -254,11 +254,13 @@ func DefaultGenesisConfig() *GenesisConfig {
// DefaultConfig generates an instance of the default config.
func DefaultConfig() *Config {
return &Config{
LogLevel: log.LevelInfo,
LogFormat: log.FormatUnstructured,
LogOutput: []string{"stdout", "kwild.log"},
LogFileRollSize: 10_000, // KB
LogRetainMaxRolls: 0, // retain all archived logs
Log: Logging{
Level: log.LevelInfo,
Format: log.FormatUnstructured,
Output: []string{"stdout", "kwild.log"},
FileRollSize: 10_000, // KB
RetainMaxRolls: 0, // retain all archived logs
},
Telemetry: Telemetry{
Enable: false,
OTLPEndpoint: "127.0.0.1:4318",
Expand Down Expand Up @@ -335,11 +337,7 @@ func DefaultConfig() *Config {

// Config is the node's config.
type Config struct {
LogLevel log.Level `toml:"log_level" comment:"log level\npossible values: 'debug', 'info', 'warn', and 'error'"`
LogFormat log.Format `toml:"log_format" comment:"log format\npossible values: 'json', 'text' (kv), and 'plain' (fmt-style)"`
LogOutput []string `toml:"log_output" comment:"output paths for the log"`
LogFileRollSize int64 `toml:"log_file_roll_size" comment:"threshold in KB at which the log file rolls over and archives the current one"`
LogRetainMaxRolls int `toml:"log_retain_max_rolls" comment:"retention limit on the number of archived log files to keep (0 meaning retain all)"`
Log Logging `toml:"log" comment:"logging configuration"`

ProfileMode string `toml:"profile_mode,commented" comment:"profile mode (http, cpu, mem, mutex, or block)"`
ProfileFile string `toml:"profile_file,commented" comment:"profile output file path (e.g. cpu.pprof)"`
Expand All @@ -366,6 +364,14 @@ type Config struct {
PGDumpPath string `toml:"pg_dump_path" comment:"path to the pg_dump binary for taking snapshots"`
}

type Logging struct {
Level log.Level `toml:"level" comment:"log level\npossible values: 'debug', 'info', 'warn', and 'error'"`
Format log.Format `toml:"format" comment:"log format\npossible values: 'json', 'text' (kv), and 'plain' (fmt-style)"`
Output []string `toml:"output" comment:"output paths for the log"`
FileRollSize int64 `toml:"file_roll_size" comment:"threshold in KB at which the log file rolls over and archives the current one"`
RetainMaxRolls int `toml:"retain_max_rolls" comment:"retention limit on the number of archived log files to keep (0 meaning retain all)"`
}

type Telemetry struct {
Enable bool `toml:"enable" comment:"enable telemetry"`
OTLPEndpoint string `toml:"otlp_endpoint" comment:"open telemetry protocol collector endpoint"` // "127.0.0.1:4318"
Expand Down
69 changes: 42 additions & 27 deletions config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,10 @@ func TestConfigSaveAndLoad(t *testing.T) {
{
name: "valid config",
config: Config{
LogLevel: log.LevelDebug,
LogFormat: log.FormatJSON,
Log: Logging{
Level: log.LevelDebug,
Format: log.FormatJSON,
},
P2P: PeerConfig{
ListenAddress: "0.0.0.0:6600",
Pex: false,
Expand All @@ -74,8 +76,10 @@ func TestConfigSaveAndLoad(t *testing.T) {
{
name: "empty config",
config: Config{
LogLevel: log.LevelInfo,
LogFormat: log.FormatUnstructured,
Log: Logging{
Level: log.LevelInfo,
Format: log.FormatUnstructured,
},
},
wantErr: false,
},
Expand All @@ -96,11 +100,11 @@ func TestConfigSaveAndLoad(t *testing.T) {
}

if !tt.wantErr {
if loaded.LogLevel != tt.config.LogLevel {
t.Errorf("LogLevel mismatch: got %v, want %v", loaded.LogLevel, tt.config.LogLevel)
if loaded.Log.Level != tt.config.Log.Level {
t.Errorf("LogLevel mismatch: got %v, want %v", loaded.Log.Level, tt.config.Log.Level)
}
if loaded.LogFormat != tt.config.LogFormat {
t.Errorf("LogFormat mismatch: got %v, want %v", loaded.LogFormat, tt.config.LogFormat)
if loaded.Log.Format != tt.config.Log.Format {
t.Errorf("LogFormat mismatch: got %v, want %v", loaded.Log.Format, tt.config.Log.Format)
}
if loaded.P2P.ListenAddress != tt.config.P2P.ListenAddress {
t.Errorf("P2P.ListenAddress mismatch: got %v, want %v", loaded.P2P.ListenAddress, tt.config.P2P.ListenAddress)
Expand Down Expand Up @@ -264,9 +268,10 @@ func TestDisallowUnknownFields(t *testing.T) {
{
name: "unknown field present",
input: `
log_level = "debug"
[log]
level = "debug"
unknown_field = "value"
log_format = "json"
format = "json"
`,
wantErr: true,
},
Expand All @@ -291,8 +296,9 @@ func TestDisallowUnknownFields(t *testing.T) {
{
name: "valid config no unknown fields",
input: `
log_level = "debug"
log_format = "json"
[log]
level = "debug"
format = "json"
[p2p]
listen = "0.0.0.0:6600"
`,
Expand Down Expand Up @@ -327,12 +333,15 @@ func TestConfigFromTOML(t *testing.T) {
{
name: "minimal valid config",
input: `
log_level = "info"
log_format = "plain"
[log]
level = "info"
format = "plain"
`,
want: Config{
LogLevel: log.LevelInfo,
LogFormat: log.FormatUnstructured,
Log: Logging{
Level: log.LevelInfo,
Format: log.FormatUnstructured,
},
},
wantErr: false,
},
Expand All @@ -345,23 +354,26 @@ func TestConfigFromTOML(t *testing.T) {
{
name: "invalid TOML syntax",
input: `
log_level = "debug"
log_format = ["invalid"
[log]
level = "debug"
format = ["invalid"
`,
wantErr: true,
},
{
name: "invalid log level value",
input: `
log_level = "invalid"
log_format = "json"
[log]
level = "invalid"
format = "json"
`,
wantErr: true,
},
{
name: "config with missing struct fields",
input: `
log_format = "json"
[log]
format = "json"
[p2p]
listen_address = "0.0.0.0:6600"
pex = true
Expand All @@ -380,8 +392,9 @@ func TestConfigFromTOML(t *testing.T) {
{
name: "full config with all fields and correct names",
input: `
log_level = "debug"
log_format = "json"
[log]
level = "debug"
format = "json"
[p2p]
listen = "0.0.0.0:6600"
pex = true
Expand All @@ -396,8 +409,10 @@ func TestConfigFromTOML(t *testing.T) {
max_connections = 20
`,
want: Config{
LogLevel: log.LevelDebug,
LogFormat: log.FormatJSON,
Log: Logging{
Level: log.LevelDebug,
Format: log.FormatJSON,
},
P2P: PeerConfig{
ListenAddress: "0.0.0.0:6600",
Pex: true,
Expand Down Expand Up @@ -444,8 +459,8 @@ func TestConfigFromTOML(t *testing.T) {
require.NoError(t, err)

if !tt.wantErr {
require.Equal(t, tt.want.LogLevel, cfg.LogLevel)
require.Equal(t, tt.want.LogFormat, cfg.LogFormat)
require.Equal(t, tt.want.Log.Level, cfg.Log.Level)
require.Equal(t, tt.want.Log.Format, cfg.Log.Format)
require.Equal(t, tt.want.P2P.ListenAddress, cfg.P2P.ListenAddress)
require.Equal(t, tt.want.P2P.Pex, cfg.P2P.Pex)
require.Equal(t, tt.want.P2P.BootNodes, cfg.P2P.BootNodes)
Expand Down
4 changes: 2 additions & 2 deletions contrib/docker/compose/kwil/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@ services:
start
--autogen
--root=/app/.kwild
--log-format=plain
--log-level=debug
--log.format=plain
--log.level=debug
--admin.listen=/tmp/kwild.socket
--rpc.listen=0.0.0.0:8484
--p2p.listen=0.0.0.0:6600
Expand Down
2 changes: 1 addition & 1 deletion test/setup/node-compose.yml.template
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
command: |
start
--root=/app/kwil
--log-format=plain
--log.format=plain
--admin.listen=/tmp/kwild.socket
--rpc.listen=0.0.0.0:8484
--p2p.listen=0.0.0.0:6600
Expand Down

0 comments on commit 6f4946b

Please sign in to comment.