Improved logging
This commit is contained in:
@@ -20,8 +20,9 @@ internal sealed class BotSessionLogger : IDisposable
|
|||||||
public string SessionId { get; } = Guid.NewGuid().ToString("N", CultureInfo.InvariantCulture);
|
public string SessionId { get; } = Guid.NewGuid().ToString("N", CultureInfo.InvariantCulture);
|
||||||
public string DirectoryPath { get; }
|
public string DirectoryPath { get; }
|
||||||
public string EventsPath { get; }
|
public string EventsPath { get; }
|
||||||
public string SummaryPath { get; }
|
public string SummaryCsvPath { get; }
|
||||||
public string LatestSymlinkPath { get; }
|
public string LatestSymlinkPath { get; }
|
||||||
|
public string LatestSummarySymlinkPath { get; }
|
||||||
|
|
||||||
public BotSessionLogger()
|
public BotSessionLogger()
|
||||||
{
|
{
|
||||||
@@ -31,12 +32,13 @@ internal sealed class BotSessionLogger : IDisposable
|
|||||||
|
|
||||||
var stamp = DateTimeOffset.UtcNow.ToString("yyyyMMdd_HHmmss", CultureInfo.InvariantCulture);
|
var stamp = DateTimeOffset.UtcNow.ToString("yyyyMMdd_HHmmss", CultureInfo.InvariantCulture);
|
||||||
EventsPath = Path.Combine(DirectoryPath, $"bot_{stamp}_{SessionId}.events.csv");
|
EventsPath = Path.Combine(DirectoryPath, $"bot_{stamp}_{SessionId}.events.csv");
|
||||||
SummaryPath = Path.Combine(DirectoryPath, $"bot_{stamp}_{SessionId}.summary.txt");
|
SummaryCsvPath = Path.Combine(DirectoryPath, $"bot_{stamp}_{SessionId}.summary.csv");
|
||||||
LatestSymlinkPath = Path.Combine(DirectoryPath, "latest.log");
|
LatestSymlinkPath = Path.Combine(DirectoryPath, "latest.log.csv");
|
||||||
|
LatestSummarySymlinkPath = Path.Combine(DirectoryPath, "latest-summary.log.csv");
|
||||||
|
|
||||||
_eventsWriter = new StreamWriter(EventsPath, append: false, Encoding.UTF8) { AutoFlush = true };
|
_eventsWriter = new StreamWriter(EventsPath, append: false, Encoding.UTF8) { AutoFlush = true };
|
||||||
_eventsWriter.WriteLine("timestamp_utc,event,label,executed,hp,max_hp,kills,deaths,pos_x,pos_y,pressure,details");
|
_eventsWriter.WriteLine("timestamp_utc,event,label,executed,hp,max_hp,kills,deaths,pos_x,pos_y,pressure,details");
|
||||||
UpdateLatestSymlink();
|
UpdateLatestSymlink(LatestSymlinkPath, EventsPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void LogDecision(
|
public void LogDecision(
|
||||||
@@ -175,7 +177,31 @@ internal sealed class BotSessionLogger : IDisposable
|
|||||||
lines.Add($" {attempt.Key}: attempts={attempt.Value}, success={success}, rate={rate:0.000}");
|
lines.Add($" {attempt.Key}: attempts={attempt.Value}, success={success}, rate={rate:0.000}");
|
||||||
}
|
}
|
||||||
|
|
||||||
File.WriteAllLines(SummaryPath, lines, Encoding.UTF8);
|
using (var csvWriter = new StreamWriter(SummaryCsvPath, append: false, Encoding.UTF8))
|
||||||
|
{
|
||||||
|
csvWriter.WriteLine("type,key,value");
|
||||||
|
csvWriter.WriteLine($"{Csv("metric")},{Csv("session")},{Csv(SessionId)}");
|
||||||
|
csvWriter.WriteLine($"{Csv("metric")},{Csv("started_utc")},{Csv(_startedAt.ToString("O", CultureInfo.InvariantCulture))}");
|
||||||
|
csvWriter.WriteLine($"{Csv("metric")},{Csv("ended_utc")},{Csv(DateTimeOffset.UtcNow.ToString("O", CultureInfo.InvariantCulture))}");
|
||||||
|
csvWriter.WriteLine($"{Csv("metric")},{Csv("duration_minutes")},{Csv(minutes.ToString("0.00", CultureInfo.InvariantCulture))}");
|
||||||
|
csvWriter.WriteLine($"{Csv("metric")},{Csv("kills")},{Csv(finalKills.ToString(CultureInfo.InvariantCulture))}");
|
||||||
|
csvWriter.WriteLine($"{Csv("metric")},{Csv("deaths")},{Csv(finalDeaths.ToString(CultureInfo.InvariantCulture))}");
|
||||||
|
csvWriter.WriteLine($"{Csv("metric")},{Csv("kd")},{Csv(kd.ToString("0.000", CultureInfo.InvariantCulture))}");
|
||||||
|
csvWriter.WriteLine($"{Csv("metric")},{Csv("kills_per_min")},{Csv((finalKills / minutes).ToString("0.000", CultureInfo.InvariantCulture))}");
|
||||||
|
csvWriter.WriteLine($"{Csv("metric")},{Csv("deaths_per_min")},{Csv((finalDeaths / minutes).ToString("0.000", CultureInfo.InvariantCulture))}");
|
||||||
|
csvWriter.WriteLine($"{Csv("metric")},{Csv("final_hp")},{Csv($"{finalHp:0.00}/{finalMaxHp:0.00}")}");
|
||||||
|
|
||||||
|
foreach (var attempt in _actionAttempts.OrderBy(x => x.Key))
|
||||||
|
{
|
||||||
|
_actionSuccess.TryGetValue(attempt.Key, out var success);
|
||||||
|
var rate = attempt.Value == 0 ? 0 : (double)success / attempt.Value;
|
||||||
|
csvWriter.WriteLine($"{Csv("action")},{Csv(attempt.Key + ".attempts")},{Csv(attempt.Value.ToString(CultureInfo.InvariantCulture))}");
|
||||||
|
csvWriter.WriteLine($"{Csv("action")},{Csv(attempt.Key + ".success")},{Csv(success.ToString(CultureInfo.InvariantCulture))}");
|
||||||
|
csvWriter.WriteLine($"{Csv("action")},{Csv(attempt.Key + ".rate")},{Csv(rate.ToString("0.000", CultureInfo.InvariantCulture))}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
UpdateLatestSymlink(LatestSummarySymlinkPath, SummaryCsvPath);
|
||||||
|
|
||||||
_eventsWriter?.Dispose();
|
_eventsWriter?.Dispose();
|
||||||
_eventsWriter = null;
|
_eventsWriter = null;
|
||||||
@@ -200,16 +226,16 @@ internal sealed class BotSessionLogger : IDisposable
|
|||||||
return $"\"{safe}\"";
|
return $"\"{safe}\"";
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateLatestSymlink()
|
private static void UpdateLatestSymlink(string symlinkPath, string targetPath)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (File.Exists(LatestSymlinkPath) || Directory.Exists(LatestSymlinkPath))
|
if (File.Exists(symlinkPath) || Directory.Exists(symlinkPath))
|
||||||
{
|
{
|
||||||
File.Delete(LatestSymlinkPath);
|
File.Delete(symlinkPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
File.CreateSymbolicLink(LatestSymlinkPath, EventsPath);
|
File.CreateSymbolicLink(symlinkPath, targetPath);
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
@@ -219,3 +245,6 @@ internal sealed class BotSessionLogger : IDisposable
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -169,7 +169,7 @@ public partial class MainWindow : Window
|
|||||||
{
|
{
|
||||||
_sessionLogger.LogEvent("session-stop", "Bot session stopping");
|
_sessionLogger.LogEvent("session-stop", "Bot session stopping");
|
||||||
_sessionLogger.WriteSummaryAndDispose(_currentHealth, _maxHealth, _kills, _deaths);
|
_sessionLogger.WriteSummaryAndDispose(_currentHealth, _maxHealth, _kills, _deaths);
|
||||||
AppendLog($"Summary written: {_sessionLogger.SummaryPath}");
|
AppendLog($"Summary CSV written: {_sessionLogger.SummaryCsvPath}");
|
||||||
_sessionLogger = null;
|
_sessionLogger = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -35,7 +35,8 @@ dotnet run --project /home/tikaiz/RiderProjects/digitalDojo/DDApp/DDApplication/
|
|||||||
- The strategy is heuristic and tunable; it is designed for high kill throughput while respecting API cooldowns.
|
- The strategy is heuristic and tunable; it is designed for high kill throughput while respecting API cooldowns.
|
||||||
- Session logs are written to `~/.local/share/DDApplication/logs` on Linux:
|
- Session logs are written to `~/.local/share/DDApplication/logs` on Linux:
|
||||||
- `*.events.csv` contains timestamped telemetry, decisions, and events
|
- `*.events.csv` contains timestamped telemetry, decisions, and events
|
||||||
- `*.summary.txt` contains aggregate K/D, kills/min, deaths/min, and action success rates
|
- `*.summary.csv` contains machine-readable summary metrics and action rates
|
||||||
|
- `latest-summary.log.csv` is a symlink that auto-points to the newest `*.summary.csv`
|
||||||
- `latest.log` is a symlink that auto-points to the newest `*.events.csv` session log
|
- `latest.log` is a symlink that auto-points to the newest `*.events.csv` session log
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user