AdGuardHome/internal/home/log.go
Stanislav Chzhen 8f1940f759 Pull request 2497: AGDNS-3306-rm-global-conf-filepath
Squashed commit of the following:

commit 6d50f74a25c8dcf2627bbb88674cca0ed7b2bbe0
Merge: aff0466ba 5c9fef62f
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date:   Thu Oct 23 18:46:46 2025 +0300

    Merge branch 'master' into AGDNS-3306-rm-global-conf-filepath

commit aff0466ba7
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date:   Tue Oct 21 10:17:59 2025 +0300

    home: fix tests

commit 8e2e1d871f
Merge: fe67680f7 feef4cd2a
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date:   Fri Oct 17 09:19:13 2025 +0300

    Merge branch 'master' into AGDNS-3306-rm-global-conf-filepath

commit fe67680f7b
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date:   Fri Oct 17 09:13:37 2025 +0300

    home: add todo

commit 6dc5635a7e
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date:   Wed Oct 15 19:43:37 2025 +0300

    home: add test cases

commit 233263bd5f
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date:   Wed Oct 15 10:22:41 2025 +0300

    home: add test

commit 354e13a60e
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date:   Fri Oct 10 23:07:21 2025 +0300

    home: imp logs

commit 8541861248
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date:   Wed Oct 8 15:36:50 2025 +0300

    home: rm global conf filepath
2025-10-23 18:59:44 +03:00

149 lines
3.5 KiB
Go

package home
import (
"cmp"
"context"
"fmt"
"log/slog"
"path/filepath"
"runtime"
"github.com/AdguardTeam/AdGuardHome/internal/aghos"
"github.com/AdguardTeam/golibs/log"
"github.com/AdguardTeam/golibs/logutil/slogutil"
yaml "go.yaml.in/yaml/v4"
"gopkg.in/natefinch/lumberjack.v2"
)
// configSyslog is used to indicate that syslog or eventlog (win) should be used
// for logger output.
const configSyslog = "syslog"
// newSlogLogger returns new [*slog.Logger] configured with the given settings.
// ls must not be nil.
func newSlogLogger(ls *logSettings) (l *slog.Logger) {
if !ls.Enabled {
return slogutil.NewDiscardLogger()
}
lvl := slog.LevelInfo
if ls.Verbose {
lvl = slog.LevelDebug
}
return slogutil.New(&slogutil.Config{
Format: slogutil.FormatAdGuardLegacy,
Level: lvl,
AddTimestamp: true,
})
}
// configureLogger configures logger level and output. ls must not be nil.
func configureLogger(ls *logSettings, workDir string) (err error) {
// Configure logger level.
if !ls.Enabled {
log.SetLevel(log.OFF)
} else if ls.Verbose {
log.SetLevel(log.DEBUG)
}
// Make sure that we see the microseconds in logs, as networking stuff can
// happen pretty quickly.
log.SetFlags(log.LstdFlags | log.Lmicroseconds)
// Write logs to stdout by default.
if ls.File == "" {
return nil
}
if ls.File == configSyslog {
// Use syslog where it is possible and eventlog on Windows.
err = aghos.ConfigureSyslog(serviceName)
if err != nil {
return fmt.Errorf("cannot initialize syslog: %w", err)
}
return nil
}
logFilePath := ls.File
if !filepath.IsAbs(logFilePath) {
logFilePath = filepath.Join(workDir, logFilePath)
}
log.SetOutput(&lumberjack.Logger{
Filename: logFilePath,
Compress: ls.Compress,
LocalTime: ls.LocalTime,
MaxBackups: ls.MaxBackups,
MaxSize: ls.MaxSize,
MaxAge: ls.MaxAge,
})
return err
}
// getLogSettings returns a log settings object properly initialized from opts.
// l must not be nil.
func getLogSettings(
ctx context.Context,
l *slog.Logger,
opts options,
workDir string,
confPath string,
) (ls *logSettings) {
configLogSettings := config.Log
ls = readLogSettings(ctx, l, workDir, confPath)
if ls == nil {
// Use default log settings.
ls = &configLogSettings
}
// Command-line arguments can override config settings.
if opts.verbose {
ls.Verbose = true
}
ls.File = cmp.Or(opts.logFile, ls.File)
if opts.runningAsService && ls.File == "" && runtime.GOOS == "windows" {
// When running as a Windows service, use eventlog by default if
// nothing else is configured. Otherwise, we'll lose the log output.
ls.File = configSyslog
}
return ls
}
// readLogSettings reads logging settings from the config file. We do it in a
// separate method in order to configure logger before the actual configuration
// is parsed and applied. l must not be nil.
func readLogSettings(
ctx context.Context,
l *slog.Logger,
workDir string,
confPath string,
) (ls *logSettings) {
// TODO(s.chzhen): Add a helper function that returns default parameters
// for this structure and for the global configuration structure [config].
conf := &configuration{
Log: logSettings{
// By default, it is true if the property does not exist.
Enabled: true,
},
}
yamlFile, err := readConfigFile(ctx, l, workDir, confPath)
if err != nil {
return nil
}
err = yaml.Unmarshal(yamlFile, conf)
if err != nil {
log.Error("Couldn't get logging settings from the configuration: %s", err)
}
return &conf.Log
}