mirror of
https://github.com/Mezeporta/Erupe.git
synced 2026-03-22 07:32:32 +01:00
chore: apply gofmt formatting
This commit is contained in:
@@ -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++
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -16,10 +16,11 @@ import (
|
||||
// - tail: Follow logs in real-time (like tail -f)
|
||||
//
|
||||
// Usage:
|
||||
// loganalyzer <command> [options]
|
||||
// loganalyzer filter -level error -since 1h
|
||||
// loganalyzer errors -summary
|
||||
// loganalyzer stats -detailed
|
||||
//
|
||||
// loganalyzer <command> [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")
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user