Ahmedramadan24's picture
Add plugins/SilkroadBot.Plugin.Logger/LoggerPlugin.cs
70481ba verified
using SilkroadBot.Plugins.SDK.Attributes;
using SilkroadBot.Plugins.SDK.Interfaces;
using SilkroadBot.Plugins.SDK.Models;
namespace SilkroadBot.Plugin.Logger;
/// <summary>
/// Logger plugin - comprehensive logging of all game events to file.
/// Supports multiple log formats, rotation, and filtering.
/// </summary>
[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();
}
/// <summary>
/// Log a game event.
/// </summary>
public void LogEvent(string category, string message, LogLevel level = LogLevel.Information)
{
WriteLog(level.ToString().ToUpper()[..4], category, message);
}
/// <summary>
/// Log a packet.
/// </summary>
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
}