| using SilkroadBot.Plugins.SDK.Attributes; |
| using SilkroadBot.Plugins.SDK.Interfaces; |
| using SilkroadBot.Plugins.SDK.Models; |
|
|
| namespace SilkroadBot.Plugin.Logger; |
|
|
| |
| |
| |
| |
| [Plugin("logger", "Event Logger", "Logs all game events to file with rotation and filtering")] |
| public class LoggerPlugin : PluginBase |
| { |
| public override string Id => "logger"; |
| public override string Name => "Event Logger"; |
| public override Version Version => new(1, 0, 0); |
| public override string Author => "SilkroadBot Team"; |
| public override string Description => "Comprehensive game event logging with file rotation"; |
|
|
| private StreamWriter? _logWriter; |
| private string _logDirectory = "logs"; |
| private LogFormat _format = LogFormat.Text; |
| private readonly object _writeLock = new(); |
| private long _totalEntries; |
|
|
| public override async Task InitializeAsync(IPluginContext context) |
| { |
| await base.InitializeAsync(context); |
| |
| _logDirectory = context.Configuration.Get("logDirectory", "logs"); |
| _format = Enum.Parse<LogFormat>(context.Configuration.Get("format", "Text")); |
| |
| if (!Directory.Exists(_logDirectory)) |
| Directory.CreateDirectory(_logDirectory); |
| } |
|
|
| public override Task StartAsync(CancellationToken ct = default) |
| { |
| var fileName = $"bot_{DateTime.Now:yyyyMMdd_HHmmss}.log"; |
| var filePath = Path.Combine(_logDirectory, fileName); |
| _logWriter = new StreamWriter(filePath, append: true) { AutoFlush = true }; |
| |
| WriteLog("INFO", "Logger", "Logging started"); |
| return base.StartAsync(ct); |
| } |
|
|
| public override Task StopAsync() |
| { |
| WriteLog("INFO", "Logger", $"Logging stopped. Total entries: {_totalEntries}"); |
| _logWriter?.Dispose(); |
| _logWriter = null; |
| return base.StopAsync(); |
| } |
|
|
| |
| |
| |
| public void LogEvent(string category, string message, LogLevel level = LogLevel.Information) |
| { |
| WriteLog(level.ToString().ToUpper()[..4], category, message); |
| } |
|
|
| |
| |
| |
| public void LogPacket(string direction, ushort opcode, int size, byte[]? data = null) |
| { |
| var hex = data != null ? BitConverter.ToString(data[..Math.Min(32, data.Length)]).Replace("-", " ") : ""; |
| WriteLog("PKT", direction, $"0x{opcode:X4} [{size}B] {hex}"); |
| } |
|
|
| private void WriteLog(string level, string category, string message) |
| { |
| if (_logWriter == null) return; |
|
|
| lock (_writeLock) |
| { |
| var timestamp = DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm:ss.fff"); |
| var line = _format switch |
| { |
| LogFormat.Text => $"[{timestamp}] [{level}] [{category}] {message}", |
| LogFormat.Csv => $"\"{timestamp}\",\"{level}\",\"{category}\",\"{message.Replace("\"", "\"\"")}\"", |
| LogFormat.Json => System.Text.Json.JsonSerializer.Serialize(new { timestamp, level, category, message }), |
| _ => $"[{timestamp}] [{level}] {message}" |
| }; |
| |
| _logWriter.WriteLine(line); |
| _totalEntries++; |
| } |
| } |
|
|
| public override void Dispose() |
| { |
| _logWriter?.Dispose(); |
| base.Dispose(); |
| } |
| } |
|
|
| public enum LogFormat |
| { |
| Text, |
| Csv, |
| Json |
| } |
|
|