diff --git a/config.go b/config.go index 2bb24b1..ac0ddb1 100644 --- a/config.go +++ b/config.go @@ -12,7 +12,6 @@ import ( "time" "github.com/peterbourgon/ff/v3" - "github.com/sirupsen/logrus" ) var ( @@ -70,18 +69,19 @@ func setupAllowedNetworks() { for _, netstr := range splitstr(*allowedNetsStr, ' ') { baseIP, allowedNet, err := net.ParseCIDR(netstr) if err != nil { - log.WithField("netstr", netstr). - WithError(err). - Fatal("Invalid CIDR notation in allowed_nets") + log.Fatal(). + Str("netstr", netstr). + Err(err). + Msg("Invalid CIDR notation in allowed_nets") } // Reject any network specification where any host bits are set, // meaning the address refers to a host and not a network. if !allowedNet.IP.Equal(baseIP) { - log.WithFields(logrus.Fields{ - "given_net": netstr, - "proper_net": allowedNet, - }).Fatal("Invalid network in allowed_nets (host bits set)") + log.Fatal(). + Str("given_net", netstr). + Str("proper_net", allowedNet.String()). + Msg("Invalid network in allowed_nets (host bits set)") } allowedNets = append(allowedNets, allowedNet) @@ -94,30 +94,32 @@ func setupAllowedPatterns() { if *allowedSenderStr != "" { allowedSender, err = regexp.Compile(*allowedSenderStr) if err != nil { - log.WithField("allowed_sender", *allowedSenderStr). - WithError(err). - Fatal("allowed_sender pattern invalid") + log.Fatal(). + Str("allowed_sender", *allowedSenderStr). + Err(err). + Msg("allowed_sender pattern invalid") } } if *allowedRecipStr != "" { allowedRecipients, err = regexp.Compile(*allowedRecipStr) if err != nil { - log.WithField("allowed_recipients", *allowedRecipStr). - WithError(err). - Fatal("allowed_recipients pattern invalid") + log.Fatal(). + Str("allowed_recipients", *allowedRecipStr). + Err(err). + Msg("allowed_recipients pattern invalid") } } } func setupRemotes() { - logger := log.WithField("remotes", *remotesStr) + logger := log.With().Str("remotes", *remotesStr).Logger() if *remotesStr != "" { for _, remoteURL := range strings.Split(*remotesStr, " ") { r, err := ParseRemote(remoteURL) if err != nil { - logger.Fatal(fmt.Sprintf("error parsing url: '%s': %v", remoteURL, err)) + logger.Fatal().Msg(fmt.Sprintf("error parsing url: '%s': %v", remoteURL, err)) } remotes = append(remotes, r) @@ -148,8 +150,9 @@ func setupListeners() { pa := splitProto(listenAddr) if localAuthRequired() && pa.protocol == "" { - log.WithField("address", pa.address). - Fatal("Local authentication (via allowed_users file) " + + log.Fatal(). + Str("address", pa.address). + Msg("Local authentication (via allowed_users file) " + "not allowed with non-TLS listener") } @@ -162,35 +165,41 @@ func setupTimeouts() { readTimeout, err = time.ParseDuration(*readTimeoutStr) if err != nil { - log.WithField("read_timeout", *readTimeoutStr). - WithError(err). - Fatal("read_timeout duration string invalid") + log.Fatal(). + Str("read_timeout", *readTimeoutStr). + Err(err). + Msg("read_timeout duration string invalid") } if readTimeout.Seconds() < 1 { - log.WithField("read_timeout", *readTimeoutStr). - Fatal("read_timeout less than one second") + log.Fatal(). + Str("read_timeout", *readTimeoutStr). + Msg("read_timeout less than one second") } writeTimeout, err = time.ParseDuration(*writeTimeoutStr) if err != nil { - log.WithField("write_timeout", *writeTimeoutStr). - WithError(err). - Fatal("write_timeout duration string invalid") + log.Fatal(). + Str("write_timeout", *writeTimeoutStr). + Err(err). + Msg("write_timeout duration string invalid") } if writeTimeout.Seconds() < 1 { - log.WithField("write_timeout", *writeTimeoutStr). - Fatal("write_timeout less than one second") + log.Fatal(). + Str("write_timeout", *writeTimeoutStr). + Msg("write_timeout less than one second") } dataTimeout, err = time.ParseDuration(*dataTimeoutStr) if err != nil { - log.WithField("data_timeout", *dataTimeoutStr). - WithError(err). - Fatal("data_timeout duration string invalid") + log.Fatal(). + Str("data_timeout", *dataTimeoutStr). + Err(err). + Msg("data_timeout duration string invalid") } if dataTimeout.Seconds() < 1 { - log.WithField("data_timeout", *dataTimeoutStr). - Fatal("data_timeout less than one second") + log.Fatal(). + Str("data_timeout", *dataTimeoutStr). + Msg("data_timeout less than one second") } } @@ -226,7 +235,7 @@ func ConfigLoad() { } if *remotesStr == "" && *command == "" { - log.Warn("no remotes or command set; mail will not be forwarded!") + log.Warn().Msg("no remotes or command set; mail will not be forwarded!") } setupAllowedNetworks() diff --git a/go.mod b/go.mod index 2d7c0fe..9a459ce 100644 --- a/go.mod +++ b/go.mod @@ -1,19 +1,19 @@ module github.com/decke/smtprelay require ( + github.com/DeRuina/timberjack v1.3.3 github.com/chrj/smtpd v0.3.1 github.com/google/uuid v1.6.0 github.com/peterbourgon/ff/v3 v3.4.0 - github.com/sirupsen/logrus v1.9.3 + github.com/rs/zerolog v1.34.0 github.com/stretchr/testify v1.10.0 golang.org/x/crypto v0.40.0 ) require ( - github.com/davecgh/go-spew v1.1.1 // indirect - github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/mattn/go-colorable v0.1.14 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect golang.org/x/sys v0.34.0 // indirect - gopkg.in/yaml.v3 v3.0.1 // indirect ) go 1.24.3 diff --git a/go.sum b/go.sum index eeda34b..64f2f3e 100644 --- a/go.sum +++ b/go.sum @@ -1,27 +1,29 @@ +github.com/DeRuina/timberjack v1.3.3 h1:R+3oEvJP1wd8iYkGGsnq9e6pHGAXFqizPKReEMj0jvQ= +github.com/DeRuina/timberjack v1.3.3/go.mod h1:pbNOvT1AIUxBqiH/ytL9nNsKrHUrDGJdz7T23y79RRU= github.com/chrj/smtpd v0.3.1 h1:kogHFkbFdKaoH3bgZkqNC9uVtKYOFfM3uV3rroBdooE= github.com/chrj/smtpd v0.3.1/go.mod h1:JtABvV/LzvLmEIzy0NyDnrfMGOMd8wy5frAokwf6J9Q= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE= +github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/peterbourgon/ff/v3 v3.4.0 h1:QBvM/rizZM1cB0p0lGMdmR7HxZeI/ZrBWB4DqLkMUBc= github.com/peterbourgon/ff/v3 v3.4.0/go.mod h1:zjJVUhx+twciwfDl0zBcFzl4dW8axCRyXE/eKY9RztQ= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= -github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0= +github.com/rs/zerolog v1.34.0 h1:k43nTLIwcTVQAncfCw4KZ2VY6ukYoZaBPNOE8txlOeY= +github.com/rs/zerolog v1.34.0/go.mod h1:bJsvje4Z08ROH4Nhs5iH600c3IkWhwp44iRc54W6wYQ= github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= golang.org/x/crypto v0.40.0 h1:r4x+VvoG5Fm+eJcxMaY8CQM7Lb0l1lsmjGBQ6s8BfKM= golang.org/x/crypto v0.40.0/go.mod h1:Qr1vMER5WyS2dfPHAlsOj01wgLbsyWtFn/aY+5+ZdxY= -golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA= golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= -gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/logger.go b/logger.go index 5d47fc9..39d08b2 100644 --- a/logger.go +++ b/logger.go @@ -2,59 +2,84 @@ package main import ( "fmt" + "io" "os" + "strings" "time" - "github.com/sirupsen/logrus" + "github.com/DeRuina/timberjack" + "github.com/rs/zerolog" ) var ( - log *logrus.Logger + rotator *timberjack.Logger + log *zerolog.Logger ) func setupLogger() { - log = logrus.New() + zerolog.TimeFieldFormat = time.RFC3339 // Handle logfile + var writer io.Writer if *logFile == "" { - log.SetOutput(os.Stderr) + writer = os.Stderr } else { - writer, err := os.OpenFile(*logFile, os.O_CREATE|os.O_RDWR|os.O_APPEND, 0600) - if err != nil { - fmt.Printf("cannot open log file: %s\n", err) - os.Exit(1) + rotator = &timberjack.Logger{ + Filename: *logFile, + MaxSize: 10, // megabytes before rotation + MaxBackups: 3, + MaxAge: 30, // days + Compress: true, + BackupTimeFormat: "20060102150405", } - - log.SetOutput(writer) + writer = rotator } // Handle log_format switch *logFormat { case "json": - log.SetFormatter(&logrus.JSONFormatter{ - TimestampFormat: time.RFC3339Nano, - DisableHTMLEscape: true, - }) + // zerolog default is JSON case "plain": - log.SetFormatter(&logrus.TextFormatter{ - DisableTimestamp: true, - }) + writer = zerolog.ConsoleWriter{ + Out: writer, + NoColor: true, + TimeFormat: "", + FormatTimestamp: func(i interface{}) string { + return "" // avoid default time + }, + } case "", "default": - log.SetFormatter(&logrus.TextFormatter{ - FullTimestamp: true, - }) + writer = zerolog.ConsoleWriter{ + Out: writer, + NoColor: true, + TimeFormat: time.RFC3339, + } + case "pretty": + writer = zerolog.ConsoleWriter{ + Out: writer, + TimeFormat: time.RFC3339Nano, + } default: fmt.Fprintf(os.Stderr, "Invalid log_format: %s\n", *logFormat) os.Exit(1) } - // Handle log_level - level, err := logrus.ParseLevel(*logLevel) - if err != nil { - level = logrus.InfoLevel + l := zerolog.New(writer).With().Timestamp().Logger() + log = &l - log.WithField("given_level", *logLevel). - Warn("could not parse log level, defaulting to 'info'") + // Handle log_level + level, err := zerolog.ParseLevel(strings.ToLower(*logLevel)) + if err != nil { + level = zerolog.InfoLevel + log.Warn().Str("given_level", *logLevel). + Msg("could not parse log level, defaulting to 'info'") + } + zerolog.SetGlobalLevel(level) +} + +// Call this on shutdown if you want to close the rotator and stop timers cleanly +func closeLogger() { + if rotator != nil { + rotator.Close() } - log.SetLevel(level) } diff --git a/main.go b/main.go index 823fabc..c96be68 100644 --- a/main.go +++ b/main.go @@ -14,7 +14,6 @@ import ( "github.com/chrj/smtpd" "github.com/google/uuid" - "github.com/sirupsen/logrus" ) func connectionChecker(peer smtpd.Peer) error { @@ -32,9 +31,9 @@ func connectionChecker(peer smtpd.Peer) error { } } - log.WithFields(logrus.Fields{ - "ip": peerIP, - }).Warn("Connection refused from address outside of allowed_nets") + log.Warn(). + Str("ip", peerIP.String()). + Msg("Connection refused from address outside of allowed_nets") return smtpd.Error{Code: 421, Message: "Denied"} } @@ -87,19 +86,21 @@ func senderChecker(peer smtpd.Peer, addr string) error { user, err := AuthFetch(peer.Username) if err != nil { // Shouldn't happen: authChecker already validated username+password - log.WithFields(logrus.Fields{ - "peer": peer.Addr, - "username": peer.Username, - }).WithError(err).Warn("could not fetch auth user") + log.Warn(). + Str("peer", peer.Addr.String()). + Str("username", peer.Username). + Err(err). + Msg("could not fetch auth user") return smtpd.Error{Code: 451, Message: "Bad sender address"} } if !addrAllowed(addr, user.allowedAddresses) { - log.WithFields(logrus.Fields{ - "peer": peer.Addr, - "username": peer.Username, - "sender_address": addr, - }).Warn("sender address not allowed for authenticated user") + log.Warn(). + Str("peer", peer.Addr.String()). + Str("username", peer.Username). + Str("sender_address", addr). + Err(err). + Msg("sender address not allowed for authenticated user") return smtpd.Error{Code: 451, Message: "Bad sender address"} } } @@ -114,10 +115,10 @@ func senderChecker(peer smtpd.Peer, addr string) error { return nil } - log.WithFields(logrus.Fields{ - "sender_address": addr, - "peer": peer.Addr, - }).Warn("sender address not allowed by allowed_sender pattern") + log.Warn(). + Str("sender_address", addr). + Str("peer", peer.Addr.String()). + Msg("sender address not allowed by allowed_sender pattern") return smtpd.Error{Code: 451, Message: "Bad sender address"} } @@ -132,20 +133,21 @@ func recipientChecker(peer smtpd.Peer, addr string) error { return nil } - log.WithFields(logrus.Fields{ - "peer": peer.Addr, - "recipient_address": addr, - }).Warn("recipient address not allowed by allowed_recipients pattern") + log.Warn(). + Str("peer", peer.Addr.String()). + Str("recipient_address", addr). + Msg("recipient address not allowed by allowed_recipients pattern") return smtpd.Error{Code: 451, Message: "Bad recipient address"} } func authChecker(peer smtpd.Peer, username string, password string) error { err := AuthCheckPassword(username, password) if err != nil { - log.WithFields(logrus.Fields{ - "peer": peer.Addr, - "username": username, - }).WithError(err).Warn("auth error") + log.Warn(). + Str("peer", peer.Addr.String()). + Str("username", username). + Err(err). + Msg("auth error") return smtpd.Error{Code: 535, Message: "Authentication credentials invalid"} } return nil @@ -157,12 +159,12 @@ func mailHandler(peer smtpd.Peer, env smtpd.Envelope) error { peerIP = addr.IP.String() } - logger := log.WithFields(logrus.Fields{ - "from": env.Sender, - "to": env.Recipients, - "peer": peerIP, - "uuid": generateUUID(), - }) + logger := log.With(). + Str("from", env.Sender). + Strs("to", env.Recipients). + Str("peer", peerIP). + Str("uuid", generateUUID()). + Logger() var envRemotes []*Remote @@ -177,14 +179,14 @@ func mailHandler(peer smtpd.Peer, env smtpd.Envelope) error { } if len(envRemotes) == 0 && *command == "" { - logger.Warning("no remote_host or command set; discarding mail") + logger.Warn().Msg("no remote_host or command set; discarding mail") return smtpd.Error{Code: 554, Message: "There are no appropriate remote_host or command"} } env.AddReceivedLine(peer) if *command != "" { - cmdLogger := logger.WithField("command", *command) + cmdLogger := logger.With().Str("command", *command).Logger() var stdout bytes.Buffer var stderr bytes.Buffer @@ -205,16 +207,16 @@ func mailHandler(peer smtpd.Peer, env smtpd.Envelope) error { err := cmd.Run() if err != nil { - cmdLogger.WithError(err).Error(stderr.String()) + cmdLogger.Error().Err(err).Msg(stderr.String()) return smtpd.Error{Code: 554, Message: "External command failed"} } - cmdLogger.Info("pipe command successful: " + stdout.String()) + cmdLogger.Info().Msg("pipe command successful: " + stdout.String()) } for _, remote := range envRemotes { - logger = logger.WithField("host", remote.Addr) - logger.Info("delivering mail from peer using smarthost") + logger = logger.With().Str("host", remote.Addr).Logger() + logger.Info().Msg("delivering mail from peer using smarthost") err := SendMail( remote, @@ -229,21 +231,22 @@ func mailHandler(peer smtpd.Peer, env smtpd.Envelope) error { case *textproto.Error: smtpError = smtpd.Error{Code: err.Code, Message: err.Msg} - logger.WithFields(logrus.Fields{ - "err_code": err.Code, - "err_msg": err.Msg, - }).Error("delivery failed") + logger.Error(). + Int("err_code", err.Code). + Str("err_msg", err.Msg). + Msg("delivery failed") default: smtpError = smtpd.Error{Code: 421, Message: "Forwarding failed"} - logger.WithError(err). - Error("delivery failed") + logger.Error(). + Err(err). + Msg("delivery failed") } return smtpError } - logger.Debug("delivery successful") + logger.Debug().Msg("delivery successful") } return nil @@ -253,8 +256,9 @@ func generateUUID() string { uniqueID, err := uuid.NewRandom() if err != nil { - log.WithError(err). - Error("could not generate UUIDv4") + log.Error(). + Err(err). + Msg("could not generate UUIDv4") return "" } @@ -280,16 +284,17 @@ func getTLSConfig() *tls.Config { } if *localCert == "" || *localKey == "" { - log.WithFields(logrus.Fields{ - "cert_file": *localCert, - "key_file": *localKey, - }).Fatal("TLS certificate/key file not defined in config") + log.Fatal(). + Str("cert_file", *localCert). + Str("key_file", *localKey). + Msg("TLS certificate/key file not defined in config") } cert, err := tls.LoadX509KeyPair(*localCert, *localKey) if err != nil { - log.WithField("error", err). - Fatal("cannot load X509 keypair") + log.Fatal(). + Err(err). + Msg("cannot load X509 keypair") } return &tls.Config{ @@ -303,16 +308,18 @@ func getTLSConfig() *tls.Config { func main() { ConfigLoad() - log.WithField("version", appVersion). - Debug("starting smtprelay") + log.Debug(). + Str("version", appVersion). + Msg("starting smtprelay") // Load allowed users file if localAuthRequired() { err := AuthLoadFile(*allowedUsers) if err != nil { - log.WithField("file", *allowedUsers). - WithError(err). - Fatal("cannot load allowed users file") + log.Fatal(). + Str("file", *allowedUsers). + Err(err). + Msg("cannot load allowed users file") } } @@ -320,7 +327,7 @@ func main() { // Create a server for each desired listen address for _, listen := range listenAddrs { - logger := log.WithField("address", listen.address) + logger := log.With().Str("address", listen.address).Logger() server := &smtpd.Server{ Hostname: *hostName, @@ -346,29 +353,32 @@ func main() { switch listen.protocol { case "": - logger.Info("listening on address") + logger.Info().Msg("listening on address") lsnr, err = net.Listen("tcp", listen.address) case "starttls": server.TLSConfig = getTLSConfig() server.ForceTLS = *localForceTLS - logger.Info("listening on address (STARTTLS)") + logger.Info().Msg("listening on address (STARTTLS)") lsnr, err = net.Listen("tcp", listen.address) case "tls": server.TLSConfig = getTLSConfig() - logger.Info("listening on address (TLS)") + logger.Info().Msg("listening on address (TLS)") lsnr, err = tls.Listen("tcp", listen.address, server.TLSConfig) default: - logger.WithField("protocol", listen.protocol). - Fatal("unknown protocol in listen address") + logger.Fatal(). + Str("protocol", listen.protocol). + Msg("unknown protocol in listen address") } if err != nil { - logger.WithError(err).Fatal("error starting listener") + logger.Fatal(). + Err(err). + Msg("error starting listener") } servers = append(servers, server) @@ -381,27 +391,31 @@ func main() { // First close the listeners for _, server := range servers { - logger := log.WithField("address", server.Address()) - logger.Debug("Shutting down server") + logger := log.With().Str("address", server.Address().String()).Logger() + logger.Debug().Msg("Shutting down server") err := server.Shutdown(false) if err != nil { - logger.WithError(err). - Warning("Shutdown failed") + logger.Warn(). + Err(err). + Msg("Shutdown failed") } } // Then wait for the clients to exit for _, server := range servers { - logger := log.WithField("address", server.Address()) - logger.Debug("Waiting for server") + logger := log.With().Str("address", server.Address().String()).Logger() + logger.Debug().Msg("Waiting for server") err := server.Wait() if err != nil { - logger.WithError(err). - Warning("Wait failed") + logger.Warn(). + Err(err). + Msg("Wait failed") } } - log.Debug("done") + log.Debug().Msg("done") + + closeLogger() } func handleSignals() { @@ -410,6 +424,7 @@ func handleSignals() { signal.Notify(sigs, syscall.SIGINT, syscall.SIGQUIT, syscall.SIGTERM) sig := <-sigs - log.WithField("signal", sig). - Info("shutting down in response to received signal") + log.Info(). + Str("signal", sig.String()). + Msg("shutting down in response to received signal") }