Structured Logging System
Overview
Version 6.5.0 introduces a comprehensive structured logging system with GroupId support that replaces the previous simple message-based logging. This new system provides powerful search capabilities, better data organization, and detailed tracking of game events, user actions, and system events with group-aware context.
π― Key Features
Structured Data Storage
- LogType Enumeration: Categorized log entries for better filtering
- Player ID Tracking: Mandatory field linking events to specific users
- Game ID Association: Optional field for game-related events
- GroupId Support: Optional field for group-based event organization
- Opponent Tracking: For wins/losses, stores both winner and loser IDs
- Detailed Context: Rich field structure instead of simple text messages
Advanced Search Capabilities
- Type-based Filtering: Filter by specific log categories
- Player-based Search: Find all events for a specific player
- Game-based Search: View complete game history
- Group-based Search: Filter events by specific groups
- Date Range Filtering: Search within specific time periods
- Combined Filters: Multiple search criteria simultaneously
Enhanced Admin Interface
- Color-coded Log Types: Visual distinction between event types
- Structured Table Display: Organized columns for better readability
- Real-time Search: Instant filtering as you type
- User-friendly Names: Shows player names instead of just IDs
π LogType Enumeration
Player Actions
PlayerLogin = 1, // User successfully logs in
PlayerLogout = 2, // User logs out (session expires)
PlayerPinChange = 3 // User changes their PIN
Game Lifecycle
GameCreated = 10, // New game created
GameStarted = 11, // Game begins (both players joined)
GameEnded = 12, // Game finishes (win/loss/draw)
GameJoined = 13 // Player joins an existing game
Game Events
MoveMade = 20, // Player makes a move
TurnTimeout = 21, // Player exceeds move time limit
GameTimeout = 22 // Game exceeds total time limit
System Events
SystemStartup = 30, // Application starts
SystemShutdown = 31, // Application shuts down
Error = 32, // Error events
Warning = 33 // Warning events
Admin Actions
AdminAction = 40, // General admin actions
UserManagement = 41, // User creation/modification
SettingsChanged = 42 // Configuration changes
ποΈ Database Schema
New GameLog Structure
CREATE TABLE GameLogs (
Id INTEGER PRIMARY KEY AUTOINCREMENT,
Timestamp DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
LogType INTEGER NOT NULL, -- LogType enum value
PlayerId INTEGER NOT NULL, -- Who triggered the event
GameId INTEGER NULL, -- Related game (if applicable)
GroupId INTEGER NULL, -- Group association (if applicable)
OpponentPlayerId INTEGER NULL, -- For wins/losses
Details TEXT NULL -- Additional context
);
Migration Notes
- Backward Compatible: Old
Messagefield still works - Automatic Migration: New fields added to existing databases
- Data Preservation: Existing logs remain accessible
- Default Values: Sensible defaults for new fields
π Search Examples
Find All Player Activity
// Get all events for player ID 5
var logs = await GameLog.GetLogsByPlayerAsync(5);
Track Game History
// Get complete timeline for game 12345
var gameHistory = await GameLog.GetLogsByGameAsync(12345);
Filter by Event Type
// Get all game endings
var endings = await GameLog.GetLogsByTypeAsync(LogType.GameEnded);
Advanced Search
// Find all timeouts for player 3 in the last week
var timeouts = await GameLog.SearchLogsAsync(
playerId: 3,
logType: LogType.GameTimeout,
startDate: DateTime.UtcNow.AddDays(-7),
count: 50
);
π¨ Admin Interface Features
Visual Log Types
Each log type has a distinct color:
- π’ Green: Positive events (logins, game starts)
- π΄ Red: Negative events (errors, timeouts, game ends)
- π΅ Blue: Informational events (game creation, joins)
- π‘ Orange: Warnings and timeouts
- π£ Purple: Admin actions
Search Interface
- Type Dropdown: Select specific log categories
- Player ID Field: Search by player number
- Game ID Field: Search by game identifier
- Clear Button: Reset all filters instantly
- Refresh Button: Reload latest logs
Table Display
| Timestamp | Type | Player | Game | Details |
|---------------------|------------|-------------|------|-----------------------------|
| 2026-03-27 12:00:00 | GameStarted | Alice vs Bob| 1234 | Game started - Alice joined |
| 2026-03-27 12:05:00 | GameEnded | Alice vs Bob| 1234 | Winner: Alice, Loser: Bob |
| 2026-03-27 12:10:00 | PlayerLogin | Carol | - | Player Carol logged in |
π Code Implementation
Structured Logging Methods
// Player actions
await GameLog.LogPlayerActionAsync(LogType.PlayerLogin, userId, "Player logged in", null, null);
// Game events with GroupId
await GameLog.LogGameEventAsync(LogType.GameCreated, userId, gameId, "Game created", null, groupId);
// Wins with opponent tracking and GroupId
await GameLog.LogWinAsync(winnerId, loserId, gameId, "Winner: Alice, Loser: Bob", groupId);
// System events (no GroupId)
await GameLog.LogSystemEventAsync(LogType.Error, adminId, "System error occurred");
Enhanced Search Methods
// Search with GroupId filtering
var logs = await GameLog.SearchLogsAsync(
playerId: 5,
gameId: 12345,
groupId: 789, // NEW: Group-based filtering
logType: LogType.GameEnded,
count: 100
);
// Group-specific analysis
var groupLogs = await GameLog.SearchLogsAsync(groupId: targetGroupId);
Backward Compatibility
// Old method still works (treated as system event)
await GameLog.LogAsync("Simple message logging");
// New structured approach preferred
await GameLog.LogPlayerActionAsync(LogType.PlayerLogin, userId, "Player logged in");
π§ Integration Points
AuthService.cs
// Login events (no GroupId for user actions)
_ = _gameLog.LogPlayerActionAsync(LogType.PlayerLogin, user.Id, $"Player {user.Name} logged in", null, null);
DraftsService.cs
// Game creation with GroupId
_ = _gameLog.LogGameEventAsync(LogType.GameCreated, userId, gameId, "Game created", null, groupId);
// Game endings with winner/loser tracking and GroupId
_ = _gameLog.LogWinAsync(winnerUserId, loserUserId, gameId, details, game.GroupId);
// Player joining with GroupId
_ = _gameLog.LogGameEventAsync(LogType.GameJoined, userId, gameId, "Player joined", null, game.GroupId);
π― GroupId Features (V6.5.0)
Group-Aware Logging
- Context Association: Links events to specific groups
- Enhanced Search: Filter logs by GroupId
- Performance Analytics: Group-based activity tracking
- User Experience: Group names displayed in interfaces
GroupId Use Cases
// Group activity monitoring
var groupActivity = await GameLog.SearchLogsAsync(groupId: targetGroupId);
// Multi-group comparison
var allGroups = await GameLog.SearchLogsAsync();
var groupedByGroup = allLogs.GroupBy(x => x.GroupId);
// Group-specific troubleshooting
var groupTimeouts = await GameLog.SearchLogsAsync(
groupId: problemGroupId,
logType: LogType.GameTimeout
);
Admin Interface Enhancements
- Group Column: Shows group names instead of IDs
- Group Filtering: Search logs by specific groups
- Visual Consistency: Matches group naming throughout app
- Fallback Handling: Graceful display for missing groups
// System timeouts _ = _gameLog.LogSystemEventAsync(LogType.GameTimeout, 1, details, gameId);
### **Admin.razor**
```csharp
// Enhanced search interface
_logs = await GameLog.SearchLogsAsync(
playerId: _searchPlayerId,
gameId: gameId,
logType: logType,
count: _logCount
);
π Performance Benefits
Database Efficiency
- Indexed Fields: PlayerId, GameId, LogType, Timestamp
- Targeted Queries: Only retrieve needed data
- Reduced Payload: No more parsing text messages
- Scalable Design: Handles high-volume logging
Search Performance
- Fast Filtering: Database-level filtering
- Lazy Loading: Load only requested amounts
- Cached Results: User names cached for display
- Optimized Queries: Efficient SQL generation
π Use Cases
Debugging Game Issues
- Player Reports Problem: Search by player ID
- Game Investigation: Filter by specific game
- System Errors: Filter by error/warning types
- Performance Analysis: Look for timeout patterns
User Behavior Analysis
- Login Patterns: Track player activity over time
- Game Preferences: Most popular game types
- Session Duration: How long players stay active
- Peak Usage Times: Busiest periods
Security Monitoring
- Failed Logins: Monitor authentication attempts
- Admin Actions: Track configuration changes
- Suspicious Activity: Unusual player behavior
- System Health: Error and warning patterns
π Future Enhancements
Potential Improvements
- Real-time Notifications: Live log streaming
- Export Capabilities: Download log data as CSV/JSON
- Advanced Analytics: Charts and statistics
- Log Retention Policies: Automatic cleanup rules
- Integration with Monitoring: External logging services
Scalability Considerations
- Database Partitioning: Separate tables by time period
- Archive Strategy: Move old logs to cold storage
- Index Optimization: Additional performance indexes
- Caching Layer: Redis for frequent queries
π Migration Guide
For Existing Applications
- Deploy New Version: Automatic database migration
- Update Code: Replace old logging calls gradually
- Test Functionality: Verify search features work
- Train Admins: Show new interface features
For New Development
- Use Structured Methods: Prefer new logging API
- Plan Search Needs: Design with filtering in mind
- Consider Log Types: Choose appropriate LogType values
- Document Events: Maintain clear logging standards
π― Best Practices
Logging Guidelines
- Be Specific: Use detailed messages for context
- Use Correct Types: Choose appropriate LogType values
- Include Context: Add relevant IDs and details
- Log Consistently: Similar events should use similar patterns
Search Optimization
- Use Filters: Narrow results before loading
- Limit Results: Donβt load more data than needed
- Cache User Names: Avoid repeated database lookups
- Index Appropriately: Ensure search fields are indexed
Performance Considerations
- Async Logging: Donβt block main application flow
- Batch Operations: Group related log entries
- Error Handling: Ensure logging failures donβt crash app
- Monitor Performance: Track logging impact on system
Version: 6.5.0
Implemented: 2026-03-27
Type: Major Enhancement
Backward Compatible: β
Yes
Search Enabled: β
Yes
Admin Interface: β
Enhanced
GroupId Support: β
Yes
Group Names: β
Displayed