55 "context"
66 "fmt"
77 "io/fs"
8+ "log"
89 "log/slog"
910 "net/http"
1011 "net/netip"
@@ -40,7 +41,6 @@ import (
4041 "github.com/AdguardTeam/dnsproxy/upstream"
4142 "github.com/AdguardTeam/golibs/errors"
4243 "github.com/AdguardTeam/golibs/hostsfile"
43- "github.com/AdguardTeam/golibs/log"
4444 "github.com/AdguardTeam/golibs/logutil/slogutil"
4545 "github.com/AdguardTeam/golibs/netutil"
4646 "github.com/AdguardTeam/golibs/netutil/httputil"
@@ -103,7 +103,7 @@ func Main(clientBuildFS fs.FS) {
103103
104104 // Configure log level and output.
105105 err = configureLogger (ls , workDir )
106- fatalOnError (err )
106+ fatalOnError (ctx , baseLogger , err )
107107
108108 // Print the first message after logger is configured.
109109 baseLogger .InfoContext (ctx , "starting adguard home" , "version" , version .Full ())
@@ -115,23 +115,23 @@ func Main(clientBuildFS fs.FS) {
115115 var glTokenFileRoot * os.Root
116116 if opts .glinetMode {
117117 glTokenFileRoot , err = os .OpenRoot ("/tmp/" )
118- fatalOnError (err )
118+ fatalOnError (ctx , baseLogger , err )
119119 }
120120
121121 done := make (chan struct {})
122122
123123 signals := make (chan os.Signal , 1 )
124124 signal .Notify (signals , syscall .SIGINT , syscall .SIGTERM , syscall .SIGHUP , syscall .SIGQUIT )
125125
126- pidFilePath := setPIDFilePath (opts )
126+ pidFilePath := setPIDFilePath (ctx , baseLogger , opts )
127127
128128 var (
129129 hc * aghnet.HostsContainer
130130 hcWatcher service.Interface = service.Empty {}
131131 )
132132 if ! opts .noEtcHosts {
133133 hc , hcWatcher , err = newHostsContainer (ctx , baseLogger )
134- fatalOnError (err )
134+ fatalOnError (ctx , baseLogger , err )
135135 }
136136
137137 sigHdlrLogger := baseLogger .With (slogutil .KeyPrefix , "signalhdlr" )
@@ -374,9 +374,9 @@ func initContextClients(
374374}
375375
376376// setPIDFilePath writes the PID value to a file and returns its path, if the
377- // PID file option is specified.
378- func setPIDFilePath (opts options ) (pidFilePath string ) {
379- if opts .pidFile != "" && ! opts .performUpdate && writePIDFile (opts .pidFile ) {
377+ // PID file option is specified. l must not be nil.
378+ func setPIDFilePath (ctx context. Context , l * slog. Logger , opts options ) (pidFilePath string ) {
379+ if opts .pidFile != "" && ! opts .performUpdate && writePIDFile (ctx , l , opts .pidFile ) {
380380 pidFilePath = opts .pidFile
381381 }
382382
@@ -756,9 +756,13 @@ func suggestedWebPort(ctx context.Context, l *slog.Logger) (p uint16) {
756756 return uint16 (v )
757757}
758758
759- func fatalOnError (err error ) {
759+ // fatalOnError logs err and exits with a failure exit code if err is not nil.
760+ // l must not be nil.
761+ func fatalOnError (ctx context.Context , l * slog.Logger , err error ) {
760762 if err != nil {
761- log .Fatal (err )
763+ l .ErrorContext (ctx , "fatal error" , slogutil .KeyError , err )
764+
765+ os .Exit (osutil .ExitCodeFailure )
762766 }
763767}
764768
@@ -791,7 +795,7 @@ func run(
791795 setupContext (ctx , baseLogger , opts , workDir , confPath , isFirstRun )
792796
793797 err := configureOS (ctx , baseLogger , config )
794- fatalOnError (err )
798+ fatalOnError (ctx , baseLogger , err )
795799
796800 // Clients package uses filtering package's static data
797801 // (filtering.BlockedSvcKnown()), so we have to initialize filtering static
@@ -806,10 +810,10 @@ func run(
806810 )
807811
808812 err = initContextClients (ctx , baseLogger , sigHdlr , confModifier , httpReg , workDir , hc )
809- fatalOnError (err )
813+ fatalOnError (ctx , baseLogger , err )
810814
811815 tlsMgr , err := initTLS (ctx , baseLogger , sigHdlr , confModifier , httpReg )
812- fatalOnError (err )
816+ fatalOnError (ctx , baseLogger , err )
813817
814818 err = setupDNSFilteringConf (
815819 ctx ,
@@ -821,19 +825,23 @@ func run(
821825 workDir ,
822826 hc ,
823827 )
824- fatalOnError (err )
828+ fatalOnError (ctx , baseLogger , err )
825829
826830 err = setupBindOpts (opts )
827- fatalOnError (err )
831+ fatalOnError (ctx , baseLogger , err )
828832
829833 upd , isCustomURL := initUpdate (ctx , baseLogger , opts , tlsMgr , isFirstRun , workDir , confPath )
830834
831835 dataDirPath := filepath .Join (workDir , dataDir )
832836 err = os .MkdirAll (dataDirPath , aghos .DefaultPermDir )
833- fatalOnError (errors .Annotate (err , "creating DNS data dir at %s: %w" , dataDirPath ))
837+ fatalOnError (
838+ ctx ,
839+ baseLogger ,
840+ errors .Annotate (err , "creating dns data dir at %q: %w" , dataDirPath ),
841+ )
834842
835843 auth , err := initUsers (ctx , baseLogger , workDir , mux , opts .glinetMode , glTokenFileRoot )
836- fatalOnError (err )
844+ fatalOnError (ctx , baseLogger , err )
837845
838846 confModifier .setAuth (auth )
839847
@@ -856,7 +864,7 @@ func run(
856864 }
857865
858866 web , err := newWeb (ctx , conf )
859- fatalOnError (err )
867+ fatalOnError (ctx , baseLogger , err )
860868
861869 mw .set (web )
862870
@@ -865,7 +873,7 @@ func run(
865873 tlsMgr .setWebAPI (web )
866874
867875 statsDir , querylogDir , err := checkStatsAndQuerylogDirs (config , workDir )
868- fatalOnError (err )
876+ fatalOnError (ctx , baseLogger , err )
869877
870878 if ! isFirstRun {
871879 runDNSServer (ctx , baseLogger , tlsMgr , confModifier , statsDir , querylogDir , httpReg , hc , web .conf .mux )
@@ -896,15 +904,15 @@ func runDNSServer(
896904 mux httputil.Router ,
897905) {
898906 err := initDNS (ctx , slogLogger , tlsMgr , confModifier , httpReg , statsDir , querylogDir , hc , mux )
899- fatalOnError (err )
907+ fatalOnError (ctx , slogLogger , err )
900908
901909 tlsMgr .start (ctx )
902910
903911 go func () {
904912 startErr := startDNSServer ()
905913 if startErr != nil {
906- closeDNSServer (ctx )
907- fatalOnError (startErr )
914+ closeDNSServer (ctx , slogLogger )
915+ fatalOnError (ctx , slogLogger , startErr )
908916 }
909917 }()
910918
@@ -977,7 +985,7 @@ func initUpdate(
977985 confPath string ,
978986) (upd * updater.Updater , isCustomURL bool ) {
979987 execPath , err := os .Executable ()
980- fatalOnError (errors .Annotate (err , "getting executable path: %w" ))
988+ fatalOnError (ctx , baseLogger , errors .Annotate (err , "getting executable path: %w" ))
981989
982990 updLogger := baseLogger .With (slogutil .KeyPrefix , "updater" )
983991 upd , isCustomURL = newUpdater (
@@ -996,7 +1004,7 @@ func initUpdate(
9961004 if ! isFirstRun {
9971005 // Save the updated config.
9981006 err = config .write (ctx , baseLogger , nil , nil , workDir , confPath )
999- fatalOnError (err )
1007+ fatalOnError (ctx , baseLogger , err )
10001008
10011009 if config .HTTPConfig .Pprof .Enabled {
10021010 startPprof (baseLogger , config .HTTPConfig .Pprof .Port )
@@ -1175,14 +1183,17 @@ func checkNetworkPermissions(ctx context.Context, l *slog.Logger) {
11751183 l .InfoContext (ctx , "adguard home can bind to port 53" )
11761184}
11771185
1178- // Write PID to a file
1179- func writePIDFile (fn string ) bool {
1186+ // writePIDFile writes the PID of the current process to the file at fn. l
1187+ // must not be nil.
1188+ func writePIDFile (ctx context.Context , l * slog.Logger , fn string ) (ok bool ) {
11801189 data := fmt .Sprintf ("%d" , os .Getpid ())
11811190 err := os .WriteFile (fn , []byte (data ), 0o644 )
11821191 if err != nil {
1183- log .Error ("Couldn't write PID to file %s: %v" , fn , err )
1192+ l .ErrorContext (ctx , "writing pid file" , "path" , fn , slogutil .KeyError , err )
1193+
11841194 return false
11851195 }
1196+
11861197 return true
11871198}
11881199
@@ -1238,7 +1249,7 @@ func initWorkingDir(opts options) (workDir string, err error) {
12381249func cleanup (ctx context.Context , l * slog.Logger , hc * aghnet.HostsContainer ) {
12391250 l .InfoContext (ctx , "stopping adguard home" )
12401251
1241- err := stopDNSServer (ctx )
1252+ err := stopDNSServer (ctx , l )
12421253 if err != nil {
12431254 l .ErrorContext (ctx , "stopping dns server" , slogutil .KeyError , err )
12441255 }
@@ -1276,10 +1287,13 @@ func exitWithError() {
12761287// loadCmdLineOpts reads command line arguments and initializes configuration
12771288// from them. If there is an error or an effect, loadCmdLineOpts processes them
12781289// and exits.
1290+ //
1291+ // TODO(m.kazantsev): Consider refactoring the logs so that it
1292+ // resembles AdGuard DNS CLI.
12791293func loadCmdLineOpts () (opts options ) {
12801294 opts , eff , err := parseCmdOpts (os .Args [0 ], os .Args [1 :])
12811295 if err != nil {
1282- log .Error ( "%s " , err )
1296+ log .Printf ( "error: %s \n " , err )
12831297 printHelp (os .Args [0 ])
12841298
12851299 exitWithError ()
@@ -1288,7 +1302,7 @@ func loadCmdLineOpts() (opts options) {
12881302 if eff != nil {
12891303 err = eff ()
12901304 if err != nil {
1291- log .Error ( "%s " , err )
1305+ log .Printf ( "error: %s \n " , err )
12921306 exitWithError ()
12931307 }
12941308
@@ -1417,7 +1431,7 @@ func cmdlineUpdate(
14171431 tlsMgr ,
14181432 agh.EmptyConfigModifier {},
14191433 )
1420- fatalOnError (err )
1434+ fatalOnError (ctx , l , err )
14211435
14221436 l .InfoContext (ctx , "performing update via cli" )
14231437
@@ -1435,7 +1449,7 @@ func cmdlineUpdate(
14351449 }
14361450
14371451 err = upd .Update (ctx , isFirstRun )
1438- fatalOnError (err )
1452+ fatalOnError (ctx , l , err )
14391453
14401454 err = restartService (ctx , l )
14411455 if err != nil {
0 commit comments