feat(ui): add current-launch logs tab

Add Live Chat and Logs tabs to the non-edit left panel. Expose a bounded process-local AppLog feed so the newest messages appear first without importing earlier startup.log contents or changing file logging.

Ref: https://obsproject.com/forum/resources/understanding-obs-studio-log.473
This commit is contained in:
2026-11-02 11:06:43 -08:00
parent 20f059422b
commit 9fa06c67c2
11 changed files with 305 additions and 77 deletions
+19 -1
View File
@@ -12,6 +12,7 @@ public static class AppLog
{
/// <summary>The cap for the live log file. Past this, it rolls to <c>startup.1.log</c>.</summary>
private const long DefaultMaxBytes = 5 * 1024 * 1024;
private const int CurrentLaunchEntryLimit = 500;
/// <summary>How many rolled copies to keep (startup.1.log, startup.2.log, …).</summary>
private const int RetainedFiles = 1;
@@ -20,6 +21,8 @@ public static class AppLog
InstanceProfile.DataRoot, "startup.log");
private static readonly object Gate = new();
private static readonly List<AppLogEntry> CurrentLaunchEntries = new();
private static long _nextSequence;
/// <summary>Test seam: point the log somewhere else. Null = the real profile's log.</summary>
internal static string? PathOverride { get; set; }
@@ -29,16 +32,29 @@ public static class AppLog
private static string LogPath => PathOverride ?? DefaultLogPath;
internal static IReadOnlyList<AppLogEntry> SnapshotCurrentLaunch()
{
lock (Gate)
return CurrentLaunchEntries.ToArray();
}
public static void Write(string message)
{
try
{
lock (Gate)
{
var entry = new AppLogEntry(
++_nextSequence,
$"{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff} {message}");
CurrentLaunchEntries.Add(entry);
if (CurrentLaunchEntries.Count > CurrentLaunchEntryLimit)
CurrentLaunchEntries.RemoveAt(0);
var path = LogPath;
Directory.CreateDirectory(Path.GetDirectoryName(path)!);
LogRotation.RollIfNeeded(path, MaxBytes, RetainedFiles);
File.AppendAllText(path, $"{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff} {message}{Environment.NewLine}");
File.AppendAllText(path, $"{entry.Text}{Environment.NewLine}");
}
}
catch
@@ -52,3 +68,5 @@ public static class AppLog
Write($"{message}: {exception}");
}
}
public sealed record AppLogEntry(long Sequence, string Text);