diff options
| author | Jeff Halter <868228+jhalter@users.noreply.github.com> | 2026-06-01 09:26:50 -0700 |
|---|---|---|
| committer | Jeff Halter <868228+jhalter@users.noreply.github.com> | 2026-06-01 09:26:50 -0700 |
| commit | c42c103ddb66028a085fb452102f73f8b27dcdcb (patch) | |
| tree | b7fe404a3a46916e082c80dce089d2258c4bc307 | |
| parent | 123d1a305bc68474034f5989362148508bdbf7f5 (diff) | |
Improve startup logging and logging consistency
Startup log:
- Add interface, port, and fileTransferPort fields to the "Hotline
server started" line so operators can see what the server bound to.
- Resolve an empty -interface flag to 0.0.0.0 for display.
Levels:
- Demote the two Redis startup messages (ban management, cleared online
users) from Info to Debug.
Consistency:
- Standardize the error field key to "err" (was "Err" in a few account
handlers) and lowercase "Account" -> "account".
- Standardize the remote-address key to "remoteAddr" (was "RemoteAddr").
- Replace fmt.Sprintf in the tracker-registration message and string
concatenation in the config-dir-init and ban-disconnect messages with
structured fields; use the standard "err" key.
- Give the two bare rLogger.Error(err.Error()) file-transfer calls a
descriptive message and an "err" field.
logger.go:
- Only attach the rotating lumberjack file writer when --log-file is set.
An empty Filename made lumberjack write to a temp file by default.
| -rw-r--r-- | cmd/mobius-hotline-server/main.go | 10 | ||||
| -rw-r--r-- | hotline/client_conn.go | 2 | ||||
| -rw-r--r-- | hotline/file_transfer.go | 4 | ||||
| -rw-r--r-- | hotline/server.go | 8 | ||||
| -rw-r--r-- | internal/mobius/api.go | 2 | ||||
| -rw-r--r-- | internal/mobius/logger.go | 19 | ||||
| -rw-r--r-- | internal/mobius/transaction_handlers.go | 12 |
7 files changed, 34 insertions, 23 deletions
diff --git a/cmd/mobius-hotline-server/main.go b/cmd/mobius-hotline-server/main.go index 8b9d54c..dced2c5 100644 --- a/cmd/mobius-hotline-server/main.go +++ b/cmd/mobius-hotline-server/main.go @@ -71,7 +71,7 @@ func main() { slogger.Error("Error copying config dir", "err", err) os.Exit(1) } - slogger.Info("Config dir initialized at " + *configDir) + slogger.Info("Config dir initialized", "config", *configDir) } else { slogger.Info("Existing config dir found. Skipping initialization.") } @@ -131,7 +131,7 @@ func main() { srv.Redis = redisClient srv.BanList = mobius.NewRedisBanMgr(redisClient, slogger) - slogger.Info("Using Redis for ban management", "addr", *redisAddr) + slogger.Debug("Using Redis for ban management", "addr", *redisAddr) } else { srv.BanList, err = mobius.NewBanFile(path.Join(*configDir, "Banlist.yaml")) if err != nil { @@ -215,7 +215,11 @@ func main() { } }() - slogger.Info("Hotline server started", "version", version, "config", *configDir) + boundInterface := *netInterface + if boundInterface == "" { + boundInterface = "0.0.0.0" + } + slogger.Info("Hotline server started", "version", version, "config", *configDir, "interface", boundInterface, "port", *basePort, "fileTransferPort", *basePort+1) if tlsConfig != nil { slogger.Info("TLS enabled", "port", *tlsPort, "fileTransferPort", *tlsPort+1) } diff --git a/hotline/client_conn.go b/hotline/client_conn.go index 9ca93a7..c17ef35 100644 --- a/hotline/client_conn.go +++ b/hotline/client_conn.go @@ -176,7 +176,7 @@ func (cc *ClientConn) Disconnect() { } if err := cc.Connection.Close(); err != nil { - cc.Server.Logger.Debug("error closing client connection", "RemoteAddr", cc.RemoteAddr) + cc.Server.Logger.Debug("error closing client connection", "remoteAddr", cc.RemoteAddr) } } diff --git a/hotline/file_transfer.go b/hotline/file_transfer.go index 98999f1..86e10eb 100644 --- a/hotline/file_transfer.go +++ b/hotline/file_transfer.go @@ -477,7 +477,7 @@ func DownloadFolderHandler(rwc io.ReadWriter, fullPath string, fileTransfer *Fil // Send file size to client if _, err := rwc.Write(hlFile.Ffo.TransferSize(dataOffset)); err != nil { - rLogger.Error(err.Error()) + rLogger.Error("Error sending file size", "err", err) return fmt.Errorf("error sending file size: %w", err) } @@ -625,7 +625,7 @@ func UploadFolderHandler(rwc io.ReadWriter, fullPath string, fileTransfer *FileT } if err := receiveFile(rwc, file, io.Discard, io.Discard, fileTransfer.bytesSentCounter); err != nil { - rLogger.Error(err.Error()) + rLogger.Error("Error receiving file", "err", err) } err = os.Rename(fullPath+"/"+fu.FormattedPath()+".incomplete", fullPath+"/"+fu.FormattedPath()) diff --git a/hotline/server.go b/hotline/server.go index 7bc6a4a..6ac68d8 100644 --- a/hotline/server.go +++ b/hotline/server.go @@ -309,16 +309,16 @@ func (s *Server) Serve(ctx context.Context, ln net.Listener) error { // Check if the rate limit is exceeded and close the connection if so. if !rl.Allow() { - s.Logger.Info("Rate limit exceeded", "RemoteAddr", conn.RemoteAddr()) + s.Logger.Info("Rate limit exceeded", "remoteAddr", conn.RemoteAddr()) _ = conn.Close() return } if err := s.handleNewConnection(connCtx, conn, conn.RemoteAddr().String()); err != nil { if err == io.EOF { - s.Logger.Info("Client disconnected", "RemoteAddr", conn.RemoteAddr()) + s.Logger.Info("Client disconnected", "remoteAddr", conn.RemoteAddr()) } else { - s.Logger.Error("Error serving request", "RemoteAddr", conn.RemoteAddr(), "err", err) + s.Logger.Error("Error serving request", "remoteAddr", conn.RemoteAddr(), "err", err) } } }() @@ -380,7 +380,7 @@ func (s *Server) registerWithAllTrackers() { tr.Password = parseTrackerPassword(t) if err := s.TrackerRegistrar.Register(t, tr); err != nil { - s.Logger.Error(fmt.Sprintf("Unable to register with tracker %v", t), "error", err) + s.Logger.Error("Unable to register with tracker", "tracker", t, "err", err) } } } diff --git a/internal/mobius/api.go b/internal/mobius/api.go index adc9072..a574bf8 100644 --- a/internal/mobius/api.go +++ b/internal/mobius/api.go @@ -85,7 +85,7 @@ func NewAPIServer(hlServer *hotline.Server, reloadFunc func(), logger *slog.Logg if err := hlServer.Redis.Del(context.Background(), hotline.RedisKeyOnline).Err(); err != nil { srv.logger.Warn("Failed to clear online users in Redis", "err", err) } else { - srv.logger.Info("Cleared online users in Redis on startup") + srv.logger.Debug("Cleared online users in Redis on startup") } } diff --git a/internal/mobius/logger.go b/internal/mobius/logger.go index 60d4f0d..2f67a71 100644 --- a/internal/mobius/logger.go +++ b/internal/mobius/logger.go @@ -22,14 +22,21 @@ var logLevels = map[string]slog.Level{ } func NewLogger(logLevel, logFile *string) *slog.Logger { + // Always log to stdout. Only add the rotating file writer when a log file path + // is configured; an empty Filename makes lumberjack write to a temp file. + var out io.Writer = os.Stdout + if *logFile != "" { + out = io.MultiWriter(os.Stdout, &lumberjack.Logger{ + Filename: *logFile, + MaxSize: logMaxSize, + MaxBackups: logMaxBackups, + MaxAge: logMaxAge, + }) + } + return slog.New( slog.NewTextHandler( - io.MultiWriter(os.Stdout, &lumberjack.Logger{ - Filename: *logFile, - MaxSize: logMaxSize, - MaxBackups: logMaxBackups, - MaxAge: logMaxAge, - }), + out, &slog.HandlerOptions{ Level: logLevels[*logLevel], ReplaceAttr: func(groups []string, a slog.Attr) slog.Attr { diff --git a/internal/mobius/transaction_handlers.go b/internal/mobius/transaction_handlers.go index b629be8..96b4f69 100644 --- a/internal/mobius/transaction_handlers.go +++ b/internal/mobius/transaction_handlers.go @@ -685,7 +685,7 @@ func HandleSetUser(cc *hotline.ClientConn, t *hotline.Transaction) (res []hotlin err := cc.Server.AccountManager.Update(*account, account.Login) if err != nil { - cc.Logger.Error("Error updating account", "Err", err) + cc.Logger.Error("Error updating account", "err", err) return cc.NewErrReply(t, ErrMsgUpdateAccount) } @@ -760,7 +760,7 @@ func HandleListUsers(cc *hotline.ClientConn, t *hotline.Transaction) (res []hotl for _, acc := range cc.Server.AccountManager.List() { b, err := io.ReadAll(&acc) if err != nil { - cc.Logger.Error("Error reading account", "Account", acc.Login, "Err", err) + cc.Logger.Error("Error reading account", "account", acc.Login, "err", err) continue } @@ -831,7 +831,7 @@ func HandleUpdateUser(cc *hotline.ClientConn, t *hotline.Transaction) (res []hot cc.Logger.Info("DeleteUser", "login", login) if err := cc.Server.AccountManager.Delete(login); err != nil { - cc.Logger.Error("Error deleting account", "Err", err) + cc.Logger.Error("Error deleting account", "err", err) return cc.NewErrReply(t, ErrMsgDeleteAccount) } @@ -1005,7 +1005,7 @@ func HandleDeleteUser(cc *hotline.ClientConn, t *hotline.Transaction) (res []hot login := t.GetField(hotline.FieldUserLogin).DecodeObfuscatedString() if err := cc.Server.AccountManager.Delete(login); err != nil { - cc.Logger.Error("Error deleting account", "Err", err) + cc.Logger.Error("Error deleting account", "err", err) return cc.NewErrReply(t, ErrMsgDeleteAccount) } @@ -1269,7 +1269,7 @@ func HandleDisconnectUser(cc *hotline.ClientConn, t *hotline.Transaction) (res [ switch options[1] { case 1: // send message: "You are temporarily banned on this server" - cc.Logger.Info("Disconnect & temporarily ban " + string(clientConn.UserName)) + cc.Logger.Info("Disconnect & temporarily ban user", "username", string(clientConn.UserName)) res = append(res, hotline.NewTransaction( hotline.TranServerMsg, @@ -1288,7 +1288,7 @@ func HandleDisconnectUser(cc *hotline.ClientConn, t *hotline.Transaction) (res [ } case 2: // send message: "You are permanently banned on this server" - cc.Logger.Info("Disconnect & ban " + string(clientConn.UserName)) + cc.Logger.Info("Disconnect & ban user", "username", string(clientConn.UserName)) res = append(res, hotline.NewTransaction( hotline.TranServerMsg, |