From 4960c5cb5d093f8972c941ebb93cbdf603bd593a Mon Sep 17 00:00:00 2001 From: Houmgaor Date: Fri, 6 Feb 2026 13:02:38 +0100 Subject: [PATCH] chore: apply gofmt formatting --- config/config.go | 22 ++++----- network/mhfpacket/mhfpacket.go | 3 +- network/mhfpacket/msg_mhf_packets_test.go | 6 +-- network/mhfpacket/msg_parse_test.go | 14 +++--- .../handlers_achievement_test.go | 4 +- server/channelserver/handlers_simple_test.go | 1 - server/channelserver/sys_channel_server.go | 32 ++++++------- server/channelserver/sys_session.go | 42 ++++++++-------- server/channelserver/sys_stage.go | 8 ++-- tools/loganalyzer/connections.go | 39 +++++++-------- tools/loganalyzer/errors.go | 19 ++++---- tools/loganalyzer/filter.go | 14 +++--- tools/loganalyzer/main.go | 9 ++-- tools/loganalyzer/parser.go | 48 ++++++++++--------- tools/loganalyzer/stats.go | 33 ++++++------- tools/loganalyzer/tail.go | 13 ++--- 16 files changed, 159 insertions(+), 148 deletions(-) diff --git a/config/config.go b/config/config.go index 231185ca8..9f6edec38 100644 --- a/config/config.go +++ b/config/config.go @@ -127,17 +127,17 @@ type SaveDumpOptions struct { // GameplayOptions has various gameplay modifiers type GameplayOptions struct { - FeaturedWeapons int // Number of Active Feature weapons to generate daily - MaximumNP int // Maximum number of NP held by a player - MaximumRP uint16 // Maximum number of RP held by a player - MaximumFP uint32 // Maximum number of Festa Points held by a player - DisableLoginBoost bool // Disables the Login Boost system - DisableBoostTime bool // Disables the daily NetCafe Boost Time - BoostTimeDuration int // The number of minutes NetCafe Boost Time lasts for - ClanMealDuration int // Seconds that a Clan Meal can be activated for after cooking - ClanMemberLimits [][]uint8 // Array of maximum Clan Members -> [[Rank, Members], ...] - BonusQuestAllowance uint32 // Number of Bonus Point Quests to allow daily - DailyQuestAllowance uint32 // Number of Daily Quests to allow daily + FeaturedWeapons int // Number of Active Feature weapons to generate daily + MaximumNP int // Maximum number of NP held by a player + MaximumRP uint16 // Maximum number of RP held by a player + MaximumFP uint32 // Maximum number of Festa Points held by a player + DisableLoginBoost bool // Disables the Login Boost system + DisableBoostTime bool // Disables the daily NetCafe Boost Time + BoostTimeDuration int // The number of minutes NetCafe Boost Time lasts for + ClanMealDuration int // Seconds that a Clan Meal can be activated for after cooking + ClanMemberLimits [][]uint8 // Array of maximum Clan Members -> [[Rank, Members], ...] + BonusQuestAllowance uint32 // Number of Bonus Point Quests to allow daily + DailyQuestAllowance uint32 // Number of Daily Quests to allow daily } // Logging holds the logging configuration. diff --git a/network/mhfpacket/mhfpacket.go b/network/mhfpacket/mhfpacket.go index 21fcb5e57..dafbf9f81 100644 --- a/network/mhfpacket/mhfpacket.go +++ b/network/mhfpacket/mhfpacket.go @@ -9,7 +9,8 @@ // Packet Structure: // // MHF packets follow this wire format: -// [2 bytes: Opcode][N bytes: Packet-specific data][2 bytes: Footer 0x00 0x10] +// +// [2 bytes: Opcode][N bytes: Packet-specific data][2 bytes: Footer 0x00 0x10] // // Each packet type defines its own structure matching the binary format expected // by the Monster Hunter Frontier client. diff --git a/network/mhfpacket/msg_mhf_packets_test.go b/network/mhfpacket/msg_mhf_packets_test.go index db719ef13..a666d1797 100644 --- a/network/mhfpacket/msg_mhf_packets_test.go +++ b/network/mhfpacket/msg_mhf_packets_test.go @@ -514,9 +514,9 @@ func TestMsgMhfUpdateEtcPointOpcode(t *testing.T) { // TestAchievementPacketParse tests simple achievement packet parsing func TestAchievementPacketParse(t *testing.T) { bf := byteframe.NewByteFrame() - bf.WriteUint8(5) // AchievementID - bf.WriteUint16(100) // Unk1 - bf.WriteUint16(200) // Unk2 + bf.WriteUint8(5) // AchievementID + bf.WriteUint16(100) // Unk1 + bf.WriteUint16(200) // Unk2 bf.Seek(0, io.SeekStart) pkt := &MsgMhfAddAchievement{} diff --git a/network/mhfpacket/msg_parse_test.go b/network/mhfpacket/msg_parse_test.go index 29050701c..071bc9e95 100644 --- a/network/mhfpacket/msg_parse_test.go +++ b/network/mhfpacket/msg_parse_test.go @@ -36,9 +36,9 @@ func TestMsgMhfGetAchievementDetailedParse(t *testing.T) { // TestMsgMhfAddAchievementDetailedParse tests MsgMhfAddAchievement parsing func TestMsgMhfAddAchievementDetailedParse(t *testing.T) { bf := byteframe.NewByteFrame() - bf.WriteUint8(42) // AchievementID - bf.WriteUint16(12345) // Unk1 - bf.WriteUint16(0xFFFF) // Unk2 - max value + bf.WriteUint8(42) // AchievementID + bf.WriteUint16(12345) // Unk1 + bf.WriteUint16(0xFFFF) // Unk2 - max value bf.Seek(0, io.SeekStart) pkt := &MsgMhfAddAchievement{} @@ -61,12 +61,12 @@ func TestMsgMhfAddAchievementDetailedParse(t *testing.T) { // TestMsgSysCastBinaryDetailedParse tests MsgSysCastBinary parsing with various payloads func TestMsgSysCastBinaryDetailedParse(t *testing.T) { tests := []struct { - name string - unk0 uint16 - unk1 uint16 + name string + unk0 uint16 + unk1 uint16 broadcastType uint8 messageType uint8 - payload []byte + payload []byte }{ {"empty payload", 0, 0, 1, 2, []byte{}}, {"typical payload", 100, 200, 0x10, 0x20, []byte{0x01, 0x02, 0x03}}, diff --git a/server/channelserver/handlers_achievement_test.go b/server/channelserver/handlers_achievement_test.go index 151b2bb75..992e64a7d 100644 --- a/server/channelserver/handlers_achievement_test.go +++ b/server/channelserver/handlers_achievement_test.go @@ -139,8 +139,8 @@ func TestGetAchData_ValueAccumulation(t *testing.T) { func TestGetAchData_NextValueByLevel(t *testing.T) { tests := []struct { - level uint8 - wantNext uint16 + level uint8 + wantNext uint16 approxScore int32 }{ {0, 5, 0}, diff --git a/server/channelserver/handlers_simple_test.go b/server/channelserver/handlers_simple_test.go index 5f922046d..0347c7213 100644 --- a/server/channelserver/handlers_simple_test.go +++ b/server/channelserver/handlers_simple_test.go @@ -311,4 +311,3 @@ func TestEmptyHandlers_NoDb(t *testing.T) { }) } } - diff --git a/server/channelserver/sys_channel_server.go b/server/channelserver/sys_channel_server.go index efbf9684e..b5a6cfb54 100644 --- a/server/channelserver/sys_channel_server.go +++ b/server/channelserver/sys_channel_server.go @@ -44,13 +44,13 @@ import ( // Config holds configuration parameters for creating a new channel server. type Config struct { - ID uint16 // Channel server ID (unique identifier) - Logger *zap.Logger // Logger instance for this channel server - DB *sqlx.DB // Database connection pool + ID uint16 // Channel server ID (unique identifier) + Logger *zap.Logger // Logger instance for this channel server + DB *sqlx.DB // Database connection pool DiscordBot *discordbot.DiscordBot // Optional Discord bot for chat integration - ErupeConfig *config.Config // Global Erupe configuration - Name string // Display name for the server (shown in broadcasts) - Enable bool // Whether this server is enabled + ErupeConfig *config.Config // Global Erupe configuration + Name string // Display name for the server (shown in broadcasts) + Enable bool // Whether this server is enabled } // userBinaryPartID is a composite key for identifying a specific part of a user's binary data. @@ -86,15 +86,15 @@ type Server struct { erupeConfig *config.Config // Global configuration // Connection management - acceptConns chan net.Conn // Channel for new accepted connections - deleteConns chan net.Conn // Channel for connections to be cleaned up - sessions map[net.Conn]*Session // Active sessions keyed by connection - listener net.Listener // TCP listener (created when Server.Start is called) - isShuttingDown bool // Shutdown flag to stop goroutines gracefully + acceptConns chan net.Conn // Channel for new accepted connections + deleteConns chan net.Conn // Channel for connections to be cleaned up + sessions map[net.Conn]*Session // Active sessions keyed by connection + listener net.Listener // TCP listener (created when Server.Start is called) + isShuttingDown bool // Shutdown flag to stop goroutines gracefully // Stage (game room) management - stagesLock sync.RWMutex // Protects stages map (RWMutex for concurrent reads) - stages map[string]*Stage // Active stages keyed by stage ID string + stagesLock sync.RWMutex // Protects stages map (RWMutex for concurrent reads) + stages map[string]*Stage // Active stages keyed by stage ID string // Localization dict map[string]string // Language string mappings for server messages @@ -105,9 +105,9 @@ type Server struct { userBinaryParts map[userBinaryPartID][]byte // Chunked binary data by character // Semaphore (multiplayer coordination) management - semaphoreLock sync.RWMutex // Protects semaphore map and semaphoreIndex - semaphore map[string]*Semaphore // Active semaphores keyed by semaphore ID - semaphoreIndex uint32 // Auto-incrementing ID for new semaphores (starts at 7) + semaphoreLock sync.RWMutex // Protects semaphore map and semaphoreIndex + semaphore map[string]*Semaphore // Active semaphores keyed by semaphore ID + semaphoreIndex uint32 // Auto-incrementing ID for new semaphores (starts at 7) // Optional integrations discordBot *discordbot.DiscordBot // Discord bot for chat relay (nil if disabled) diff --git a/server/channelserver/sys_session.go b/server/channelserver/sys_session.go index 1c202b56c..0d5beed61 100644 --- a/server/channelserver/sys_session.go +++ b/server/channelserver/sys_session.go @@ -48,32 +48,32 @@ type Session struct { sync.Mutex // Protects session state during concurrent handler execution // Core connection and logging - logger *zap.Logger // Logger with connection address - server *Server // Parent server reference - rawConn net.Conn // Underlying TCP connection - cryptConn *network.CryptConn // Encrypted connection wrapper - sendPackets chan packet // Outbound packet queue (buffered, size 20) - clientContext *clientctx.ClientContext // Client version and capabilities - lastPacket time.Time // Timestamp of last received packet (for timeout detection) + logger *zap.Logger // Logger with connection address + server *Server // Parent server reference + rawConn net.Conn // Underlying TCP connection + cryptConn *network.CryptConn // Encrypted connection wrapper + sendPackets chan packet // Outbound packet queue (buffered, size 20) + clientContext *clientctx.ClientContext // Client version and capabilities + lastPacket time.Time // Timestamp of last received packet (for timeout detection) // Stage (game area) state - userEnteredStage bool // Whether player has entered any stage during this session - stageID string // Current stage ID string (e.g., "sl1Ns200p0a0u0") - stage *Stage // Pointer to current stage object - reservationStage *Stage // Stage reserved for quest (used by unreserve packet) - stagePass string // Temporary password storage for password-protected stages + userEnteredStage bool // Whether player has entered any stage during this session + stageID string // Current stage ID string (e.g., "sl1Ns200p0a0u0") + stage *Stage // Pointer to current stage object + reservationStage *Stage // Stage reserved for quest (used by unreserve packet) + stagePass string // Temporary password storage for password-protected stages stageMoveStack *stringstack.StringStack // Navigation history for "back" functionality // Player identity and state - charID uint32 // Character ID for this session - Name string // Character name (for debugging/logging) - prevGuildID uint32 // Last guild ID queried (cached for InfoGuild) - token string // Authentication token from sign server - logKey []byte // Logging encryption key - sessionStart int64 // Session start timestamp (Unix time) - courses []mhfcourse.Course // Active Monster Hunter courses (buffs/subscriptions) - kqf []byte // Key Quest Flags (quest progress tracking) - kqfOverride bool // Whether KQF is being overridden + charID uint32 // Character ID for this session + Name string // Character name (for debugging/logging) + prevGuildID uint32 // Last guild ID queried (cached for InfoGuild) + token string // Authentication token from sign server + logKey []byte // Logging encryption key + sessionStart int64 // Session start timestamp (Unix time) + courses []mhfcourse.Course // Active Monster Hunter courses (buffs/subscriptions) + kqf []byte // Key Quest Flags (quest progress tracking) + kqfOverride bool // Whether KQF is being overridden // Quest/event coordination semaphore *Semaphore // Semaphore for quest/event participation (if in a coordinated activity) diff --git a/server/channelserver/sys_stage.go b/server/channelserver/sys_stage.go index 60e05e1af..84829347b 100644 --- a/server/channelserver/sys_stage.go +++ b/server/channelserver/sys_stage.go @@ -13,10 +13,10 @@ import ( // other players in the same stage. Each object has an owner, position, and // unique ID for client-server synchronization. type Object struct { - sync.RWMutex // Protects object state during updates - id uint32 // Unique object ID (see NextObjectID for ID generation) - ownerCharID uint32 // Character ID of the player who placed this object - x, y, z float32 // 3D position coordinates + sync.RWMutex // Protects object state during updates + id uint32 // Unique object ID (see NextObjectID for ID generation) + ownerCharID uint32 // Character ID of the player who placed this object + x, y, z float32 // 3D position coordinates } // stageBinaryKey is a composite key for identifying a specific piece of stage binary data. diff --git a/tools/loganalyzer/connections.go b/tools/loganalyzer/connections.go index d32400faa..232f1274b 100644 --- a/tools/loganalyzer/connections.go +++ b/tools/loganalyzer/connections.go @@ -14,16 +14,16 @@ import ( // A session is identified by the combination of channel and IP:port, tracking // all activities from when a player connects until they disconnect. type PlayerSession struct { - Name string // Player name - IPPort string // Client IP address and port (e.g., "192.168.1.1:12345") - Channel string // Server channel (e.g., "channel-4") - FirstSeen time.Time // Timestamp of first activity - LastSeen time.Time // Timestamp of last activity - Activities []string // List of player activities - Stages []string // List of stage changes - Objects []string // List of objects broadcast by this player - Errors int // Number of errors encountered during session - SaveCount int // Number of save operations performed + Name string // Player name + IPPort string // Client IP address and port (e.g., "192.168.1.1:12345") + Channel string // Server channel (e.g., "channel-4") + FirstSeen time.Time // Timestamp of first activity + LastSeen time.Time // Timestamp of last activity + Activities []string // List of player activities + Stages []string // List of stage changes + Objects []string // List of objects broadcast by this player + Errors int // Number of errors encountered during session + SaveCount int // Number of save operations performed } // ConnectionStats aggregates statistics about player connections across all sessions. @@ -31,12 +31,12 @@ type PlayerSession struct { // This structure tracks high-level metrics useful for understanding server usage // patterns, peak times, and common connection issues. type ConnectionStats struct { - TotalConnections int // Total number of player sessions - UniqueIPs map[string]int // IP addresses to connection count + TotalConnections int // Total number of player sessions + UniqueIPs map[string]int // IP addresses to connection count UniquePlayers map[string]bool // Set of unique player names - ConnectionsPerDay map[string]int // Date to connection count - ChannelDistribution map[string]int // Channel to connection count - DisconnectReasons map[string]int // Disconnect reason to count + ConnectionsPerDay map[string]int // Date to connection count + ChannelDistribution map[string]int // Channel to connection count + DisconnectReasons map[string]int // Disconnect reason to count } // runConnections implements the connections command for analyzing player connection patterns. @@ -61,9 +61,10 @@ type ConnectionStats struct { // - v: Verbose output including objects and stage changes // // Examples: -// runConnections([]string{"-stats"}) -// runConnections([]string{"-sessions", "-v"}) -// runConnections([]string{"-player", "Sarah", "-sessions"}) +// +// runConnections([]string{"-stats"}) +// runConnections([]string{"-sessions", "-v"}) +// runConnections([]string{"-player", "Sarah", "-sessions"}) func runConnections(args []string) { fs := flag.NewFlagSet("connections", flag.ExitOnError) @@ -160,7 +161,7 @@ func runConnections(args []string) { // Track disconnections if strings.Contains(entry.Message, "Error on ReadPacket, exiting recv loop") || - strings.Contains(entry.Message, "Error reading packet") { + strings.Contains(entry.Message, "Error reading packet") { sessionKey := extractSessionKey(entry.Logger) if session, exists := sessions[sessionKey]; exists { session.Errors++ diff --git a/tools/loganalyzer/errors.go b/tools/loganalyzer/errors.go index 4392b9779..bff292f5c 100644 --- a/tools/loganalyzer/errors.go +++ b/tools/loganalyzer/errors.go @@ -13,12 +13,12 @@ import ( // Errors can be grouped by message, caller, or logger to identify patterns // and recurring issues in the logs. type ErrorGroup struct { - Message string // Primary message for this error group - Count int // Total number of occurrences - FirstSeen string // Timestamp of first occurrence - LastSeen string // Timestamp of last occurrence - Examples []*LogEntry // Sample log entries (limited by the limit flag) - Callers map[string]int // Map of caller locations to occurrence counts + Message string // Primary message for this error group + Count int // Total number of occurrences + FirstSeen string // Timestamp of first occurrence + LastSeen string // Timestamp of last occurrence + Examples []*LogEntry // Sample log entries (limited by the limit flag) + Callers map[string]int // Map of caller locations to occurrence counts } // runErrors implements the errors command for extracting and analyzing errors. @@ -44,9 +44,10 @@ type ErrorGroup struct { // - detailed: Show detailed information including examples and extra data // // Examples: -// runErrors([]string{"-summary"}) -// runErrors([]string{"-detailed", "-stack"}) -// runErrors([]string{"-group", "caller", "-limit", "20"}) +// +// runErrors([]string{"-summary"}) +// runErrors([]string{"-detailed", "-stack"}) +// runErrors([]string{"-group", "caller", "-limit", "20"}) func runErrors(args []string) { fs := flag.NewFlagSet("errors", flag.ExitOnError) diff --git a/tools/loganalyzer/filter.go b/tools/loganalyzer/filter.go index ed48f057a..0c3c01eb2 100644 --- a/tools/loganalyzer/filter.go +++ b/tools/loganalyzer/filter.go @@ -23,9 +23,10 @@ import ( // All filters are combined with AND logic. // // Examples: -// runFilter([]string{"-level", "error"}) -// runFilter([]string{"-since", "1h", "-logger", "channel-4*"}) -// runFilter([]string{"-msg", "connection reset", "-count"}) +// +// runFilter([]string{"-level", "error"}) +// runFilter([]string{"-since", "1h", "-logger", "channel-4*"}) +// runFilter([]string{"-msg", "connection reset", "-count"}) func runFilter(args []string) { fs := flag.NewFlagSet("filter", flag.ExitOnError) @@ -137,9 +138,10 @@ func runFilter(args []string) { // - true if the string matches the pattern, false otherwise // // Examples: -// matchWildcard("channel-4", "channel-*") // returns true -// matchWildcard("main.channel-4.error", "*channel-4*") // returns true -// matchWildcard("test", "foo*") // returns false +// +// matchWildcard("channel-4", "channel-*") // returns true +// matchWildcard("main.channel-4.error", "*channel-4*") // returns true +// matchWildcard("test", "foo*") // returns false func matchWildcard(s, pattern string) bool { if pattern == "*" { return true diff --git a/tools/loganalyzer/main.go b/tools/loganalyzer/main.go index 6328f6bda..20074f309 100644 --- a/tools/loganalyzer/main.go +++ b/tools/loganalyzer/main.go @@ -16,10 +16,11 @@ import ( // - tail: Follow logs in real-time (like tail -f) // // Usage: -// loganalyzer [options] -// loganalyzer filter -level error -since 1h -// loganalyzer errors -summary -// loganalyzer stats -detailed +// +// loganalyzer [options] +// loganalyzer filter -level error -since 1h +// loganalyzer errors -summary +// loganalyzer stats -detailed func main() { flag.Usage = func() { fmt.Fprintf(os.Stderr, "Erupe Log Analyzer - Suite of tools to analyze erupe.log files\n\n") diff --git a/tools/loganalyzer/parser.go b/tools/loganalyzer/parser.go index 67953fc61..6231c5395 100644 --- a/tools/loganalyzer/parser.go +++ b/tools/loganalyzer/parser.go @@ -17,8 +17,8 @@ import ( // LogEntry represents a parsed log entry from either JSON or timestamp-based format. // // The parser supports two log formats: -// 1. JSON format: {"level":"info","ts":1762989571.547817,"logger":"main","msg":"Starting"} -// 2. Timestamp format: 2025-11-12T23:19:31.546Z INFO commands Command Help: Enabled +// 1. JSON format: {"level":"info","ts":1762989571.547817,"logger":"main","msg":"Starting"} +// 2. Timestamp format: 2025-11-12T23:19:31.546Z INFO commands Command Help: Enabled type LogEntry struct { Raw string // Original log line Level string // Log level: info, warn, error, fatal @@ -50,11 +50,12 @@ type LogEntry struct { // - An error if the file cannot be opened or read // // Example: -// entries, err := ParseLogFile("erupe.log") -// if err != nil { -// log.Fatal(err) -// } -// fmt.Printf("Parsed %d entries\n", len(entries)) +// +// entries, err := ParseLogFile("erupe.log") +// if err != nil { +// log.Fatal(err) +// } +// fmt.Printf("Parsed %d entries\n", len(entries)) func ParseLogFile(filename string) ([]*LogEntry, error) { file, err := os.Open(filename) if err != nil { @@ -92,9 +93,9 @@ func ParseLogFile(filename string) ([]*LogEntry, error) { // ParseLogLine parses a single log line into a LogEntry. // // This function attempts to parse the line in the following order: -// 1. JSON format: Lines starting with '{' are parsed as JSON objects -// 2. Timestamp format: Tab-delimited lines with RFC3339 timestamps -// 3. Unknown format: Lines that don't match either format are marked as "unknown" level +// 1. JSON format: Lines starting with '{' are parsed as JSON objects +// 2. Timestamp format: Tab-delimited lines with RFC3339 timestamps +// 3. Unknown format: Lines that don't match either format are marked as "unknown" level // // For JSON logs, all standard fields (level, ts, logger, caller, msg, error, stacktrace) // are extracted, and any additional fields are stored in ExtraData. @@ -106,8 +107,9 @@ func ParseLogFile(filename string) ([]*LogEntry, error) { // - A LogEntry pointer containing the parsed data, or nil if the line is invalid // // Example: -// entry := ParseLogLine(`{"level":"info","ts":1762989571.547817,"msg":"Starting"}`) -// fmt.Println(entry.Level, entry.Message) +// +// entry := ParseLogLine(`{"level":"info","ts":1762989571.547817,"msg":"Starting"}`) +// fmt.Println(entry.Level, entry.Message) func ParseLogLine(line string) *LogEntry { entry := &LogEntry{ Raw: line, @@ -152,7 +154,7 @@ func ParseLogLine(line string) *LogEntry { // Store any extra fields for k, v := range jsonData { if k != "level" && k != "ts" && k != "logger" && k != "caller" && - k != "msg" && k != "error" && k != "stacktrace" { + k != "msg" && k != "error" && k != "stacktrace" { entry.ExtraData[k] = v } } @@ -201,12 +203,13 @@ func ParseLogLine(line string) *LogEntry { // - An error if the file cannot be opened, read, or if the callback returns an error // // Example: -// err := StreamLogFile("erupe.log", func(entry *LogEntry) error { -// if entry.Level == "error" { -// fmt.Println(entry.Message) -// } -// return nil -// }) +// +// err := StreamLogFile("erupe.log", func(entry *LogEntry) error { +// if entry.Level == "error" { +// fmt.Println(entry.Message) +// } +// return nil +// }) func StreamLogFile(filename string, callback func(*LogEntry) error) error { file, err := os.Open(filename) if err != nil { @@ -259,9 +262,10 @@ func StreamLogFile(filename string, callback func(*LogEntry) error) error { // - A formatted string representation of the log entry // // Example: -// formatted := FormatLogEntry(entry, true) -// fmt.Println(formatted) -// // Output: 2025-11-12 23:19:31.546 INFO [main] Starting Erupe +// +// formatted := FormatLogEntry(entry, true) +// fmt.Println(formatted) +// // Output: 2025-11-12 23:19:31.546 INFO [main] Starting Erupe func FormatLogEntry(entry *LogEntry, colorize bool) string { var sb strings.Builder diff --git a/tools/loganalyzer/stats.go b/tools/loganalyzer/stats.go index 1a3b5899f..cbc8bc8b0 100644 --- a/tools/loganalyzer/stats.go +++ b/tools/loganalyzer/stats.go @@ -15,19 +15,19 @@ import ( // message types, and server operations to provide insights into server behavior // and activity patterns. type LogStats struct { - TotalEntries int // Total number of log entries - EntriesByLevel map[string]int // Log level to count - EntriesByLogger map[string]int // Logger name to count - EntriesByDay map[string]int // Date string to count - EntriesByHour map[int]int // Hour (0-23) to count - TopMessages map[string]int // Message text to count - FirstEntry time.Time // Timestamp of first entry - LastEntry time.Time // Timestamp of last entry - SaveOperations int // Count of save operations - ObjectBroadcasts int // Count of object broadcasts - StageChanges int // Count of stage changes - TerminalLogs int // Count of terminal log entries - UniqueCallers map[string]bool // Set of unique caller locations + TotalEntries int // Total number of log entries + EntriesByLevel map[string]int // Log level to count + EntriesByLogger map[string]int // Logger name to count + EntriesByDay map[string]int // Date string to count + EntriesByHour map[int]int // Hour (0-23) to count + TopMessages map[string]int // Message text to count + FirstEntry time.Time // Timestamp of first entry + LastEntry time.Time // Timestamp of last entry + SaveOperations int // Count of save operations + ObjectBroadcasts int // Count of object broadcasts + StageChanges int // Count of stage changes + TerminalLogs int // Count of terminal log entries + UniqueCallers map[string]bool // Set of unique caller locations } // runStats implements the stats command for generating comprehensive log statistics. @@ -49,9 +49,10 @@ type LogStats struct { // - detailed: Show detailed statistics including temporal patterns and top messages // // Examples: -// runStats([]string{}) // Basic statistics -// runStats([]string{"-detailed"}) // Full statistics with temporal analysis -// runStats([]string{"-detailed", "-top", "20"}) // Show top 20 items +// +// runStats([]string{}) // Basic statistics +// runStats([]string{"-detailed"}) // Full statistics with temporal analysis +// runStats([]string{"-detailed", "-top", "20"}) // Show top 20 items func runStats(args []string) { fs := flag.NewFlagSet("stats", flag.ExitOnError) diff --git a/tools/loganalyzer/tail.go b/tools/loganalyzer/tail.go index 9ca944c89..321f1c176 100644 --- a/tools/loganalyzer/tail.go +++ b/tools/loganalyzer/tail.go @@ -15,8 +15,8 @@ import ( // useful for real-time monitoring of server activity. // // The command operates in two phases: -// 1. Initial display: Shows the last N matching entries from the file -// 2. Follow mode: Continuously monitors for new lines and displays them as they appear +// 1. Initial display: Shows the last N matching entries from the file +// 2. Follow mode: Continuously monitors for new lines and displays them as they appear // // Both phases support filtering by log level and colorized output. // @@ -30,10 +30,11 @@ import ( // The follow mode polls the file every 100ms for new content. Use Ctrl+C to stop. // // Examples: -// runTail([]string{}) // Show last 10 lines and follow -// runTail([]string{"-n", "50"}) // Show last 50 lines and follow -// runTail([]string{"-level", "error"}) // Only show errors -// runTail([]string{"-follow=false", "-n", "20"}) // Just show last 20 lines, don't follow +// +// runTail([]string{}) // Show last 10 lines and follow +// runTail([]string{"-n", "50"}) // Show last 50 lines and follow +// runTail([]string{"-level", "error"}) // Only show errors +// runTail([]string{"-follow=false", "-n", "20"}) // Just show last 20 lines, don't follow func runTail(args []string) { fs := flag.NewFlagSet("tail", flag.ExitOnError)