mirror of
https://github.com/goatcorp/Dalamud.git
synced 2025-12-31 21:03:43 +01:00
Limit console log lines held in memory (#1683)
* Add AG.Collections.RollingList * Use RollingList for logs + Adaption changes * Create Dalamud.Utility.ThrowHelper * Create Dalamud.Utility.RollingList * ConsoleWindow: Remove dependency * Remove NuGet Dependency * Add Log Lines Limit configuration * Use Log Lines Limit configuration and handle changes * Make log lines limit configurable
This commit is contained in:
parent
e6c97f0f18
commit
0651c643b1
4 changed files with 375 additions and 15 deletions
|
|
@ -6,6 +6,7 @@ using System.Numerics;
|
|||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading;
|
||||
|
||||
using Dalamud.Configuration.Internal;
|
||||
using Dalamud.Game.Command;
|
||||
|
|
@ -28,7 +29,11 @@ namespace Dalamud.Interface.Internal.Windows;
|
|||
/// </summary>
|
||||
internal class ConsoleWindow : Window, IDisposable
|
||||
{
|
||||
private readonly List<LogEntry> logText = new();
|
||||
private const int LogLinesMinimum = 100;
|
||||
private const int LogLinesMaximum = 1000000;
|
||||
|
||||
private readonly RollingList<LogEntry> logText;
|
||||
private volatile int newRolledLines;
|
||||
private readonly object renderLock = new();
|
||||
|
||||
private readonly List<string> history = new();
|
||||
|
|
@ -42,12 +47,14 @@ internal class ConsoleWindow : Window, IDisposable
|
|||
private string pluginFilter = string.Empty;
|
||||
|
||||
private bool filterShowUncaughtExceptions;
|
||||
private bool settingsPopupWasOpen;
|
||||
private bool showFilterToolbar;
|
||||
private bool clearLog;
|
||||
private bool copyLog;
|
||||
private bool copyMode;
|
||||
private bool killGameArmed;
|
||||
private bool autoScroll;
|
||||
private int logLinesLimit;
|
||||
private bool autoOpen;
|
||||
private bool regexError;
|
||||
|
||||
|
|
@ -74,9 +81,17 @@ internal class ConsoleWindow : Window, IDisposable
|
|||
};
|
||||
|
||||
this.RespectCloseHotkey = false;
|
||||
|
||||
this.logLinesLimit = configuration.LogLinesLimit;
|
||||
|
||||
var limit = Math.Max(LogLinesMinimum, this.logLinesLimit);
|
||||
this.logText = new(limit);
|
||||
this.FilteredLogEntries = new(limit);
|
||||
|
||||
configuration.DalamudConfigurationSaved += this.OnDalamudConfigurationSaved;
|
||||
}
|
||||
|
||||
private List<LogEntry> FilteredLogEntries { get; set; } = new();
|
||||
private RollingList<LogEntry> FilteredLogEntries { get; set; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void OnOpen()
|
||||
|
|
@ -91,6 +106,7 @@ internal class ConsoleWindow : Window, IDisposable
|
|||
public void Dispose()
|
||||
{
|
||||
SerilogEventSink.Instance.LogLine -= this.OnLogLine;
|
||||
Service<DalamudConfiguration>.Get().DalamudConfigurationSaved -= this.OnDalamudConfigurationSaved;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -180,6 +196,9 @@ internal class ConsoleWindow : Window, IDisposable
|
|||
var dividerOffset = ImGui.CalcTextSize("00:00:00.000 | AAA ").X + (ImGui.CalcTextSize(" ").X / 2);
|
||||
var cursorLogLine = ImGui.CalcTextSize("00:00:00.000 | AAA | ").X;
|
||||
|
||||
var lastLinePosY = 0.0f;
|
||||
var logLineHeight = 0.0f;
|
||||
|
||||
lock (this.renderLock)
|
||||
{
|
||||
clipper.Begin(this.FilteredLogEntries.Count);
|
||||
|
|
@ -187,7 +206,8 @@ internal class ConsoleWindow : Window, IDisposable
|
|||
{
|
||||
for (var i = clipper.DisplayStart; i < clipper.DisplayEnd; i++)
|
||||
{
|
||||
var line = this.FilteredLogEntries[i];
|
||||
var index = Math.Max(i - this.newRolledLines, 0); // Prevents flicker effect. Also workaround to avoid negative indexes.
|
||||
var line = this.FilteredLogEntries[index];
|
||||
|
||||
if (!line.IsMultiline && !this.copyLog)
|
||||
ImGui.Separator();
|
||||
|
|
@ -228,6 +248,10 @@ internal class ConsoleWindow : Window, IDisposable
|
|||
|
||||
ImGui.SetCursorPosX(cursorLogLine);
|
||||
ImGui.TextUnformatted(line.Line);
|
||||
|
||||
var currentLinePosY = ImGui.GetCursorPosY();
|
||||
logLineHeight = currentLinePosY - lastLinePosY;
|
||||
lastLinePosY = currentLinePosY;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -239,6 +263,12 @@ internal class ConsoleWindow : Window, IDisposable
|
|||
|
||||
ImGui.PopStyleVar();
|
||||
|
||||
var newRolledLinesCount = Interlocked.Exchange(ref this.newRolledLines, 0);
|
||||
if (!this.autoScroll || ImGui.GetScrollY() < ImGui.GetScrollMaxY())
|
||||
{
|
||||
ImGui.SetScrollY(ImGui.GetScrollY() - (logLineHeight * newRolledLinesCount));
|
||||
}
|
||||
|
||||
if (this.autoScroll && ImGui.GetScrollY() >= ImGui.GetScrollMaxY())
|
||||
{
|
||||
ImGui.SetScrollHereY(1.0f);
|
||||
|
|
@ -363,21 +393,21 @@ internal class ConsoleWindow : Window, IDisposable
|
|||
|
||||
ImGui.SameLine();
|
||||
|
||||
this.autoScroll = configuration.LogAutoScroll;
|
||||
if (this.DrawToggleButtonWithTooltip("auto_scroll", "Auto-scroll", FontAwesomeIcon.Sync, ref this.autoScroll))
|
||||
var settingsPopup = ImGui.BeginPopup("##console_settings");
|
||||
if (settingsPopup)
|
||||
{
|
||||
configuration.LogAutoScroll = !configuration.LogAutoScroll;
|
||||
configuration.QueueSave();
|
||||
this.DrawSettingsPopup(configuration);
|
||||
ImGui.EndPopup();
|
||||
}
|
||||
else if (this.settingsPopupWasOpen)
|
||||
{
|
||||
// Prevent side effects in case Apply wasn't clicked
|
||||
this.logLinesLimit = configuration.LogLinesLimit;
|
||||
}
|
||||
|
||||
ImGui.SameLine();
|
||||
this.settingsPopupWasOpen = settingsPopup;
|
||||
|
||||
this.autoOpen = configuration.LogOpenAtStartup;
|
||||
if (this.DrawToggleButtonWithTooltip("auto_open", "Open at startup", FontAwesomeIcon.WindowRestore, ref this.autoOpen))
|
||||
{
|
||||
configuration.LogOpenAtStartup = !configuration.LogOpenAtStartup;
|
||||
configuration.QueueSave();
|
||||
}
|
||||
if (this.DrawToggleButtonWithTooltip("show_settings", "Show settings", FontAwesomeIcon.List, ref settingsPopup)) ImGui.OpenPopup("##console_settings");
|
||||
|
||||
ImGui.SameLine();
|
||||
|
||||
|
|
@ -447,6 +477,33 @@ internal class ConsoleWindow : Window, IDisposable
|
|||
}
|
||||
}
|
||||
|
||||
private void DrawSettingsPopup(DalamudConfiguration configuration)
|
||||
{
|
||||
if (ImGui.Checkbox("Open at startup", ref this.autoOpen))
|
||||
{
|
||||
configuration.LogOpenAtStartup = this.autoOpen;
|
||||
configuration.QueueSave();
|
||||
}
|
||||
|
||||
if (ImGui.Checkbox("Auto-scroll", ref this.autoScroll))
|
||||
{
|
||||
configuration.LogAutoScroll = this.autoScroll;
|
||||
configuration.QueueSave();
|
||||
}
|
||||
|
||||
ImGui.TextUnformatted("Logs buffer");
|
||||
ImGui.SliderInt("lines", ref this.logLinesLimit, LogLinesMinimum, LogLinesMaximum);
|
||||
if (ImGui.Button("Apply"))
|
||||
{
|
||||
this.logLinesLimit = Math.Max(LogLinesMinimum, this.logLinesLimit);
|
||||
|
||||
configuration.LogLinesLimit = this.logLinesLimit;
|
||||
configuration.QueueSave();
|
||||
|
||||
ImGui.CloseCurrentPopup();
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawFilterToolbar()
|
||||
{
|
||||
if (!this.showFilterToolbar) return;
|
||||
|
|
@ -686,8 +743,12 @@ internal class ConsoleWindow : Window, IDisposable
|
|||
|
||||
this.logText.Add(entry);
|
||||
|
||||
var avoidScroll = this.FilteredLogEntries.Count == this.FilteredLogEntries.Size;
|
||||
if (this.IsFilterApplicable(entry))
|
||||
{
|
||||
this.FilteredLogEntries.Add(entry);
|
||||
if (avoidScroll) Interlocked.Increment(ref this.newRolledLines);
|
||||
}
|
||||
}
|
||||
|
||||
private bool IsFilterApplicable(LogEntry entry)
|
||||
|
|
@ -740,7 +801,7 @@ internal class ConsoleWindow : Window, IDisposable
|
|||
lock (this.renderLock)
|
||||
{
|
||||
this.regexError = false;
|
||||
this.FilteredLogEntries = this.logText.Where(this.IsFilterApplicable).ToList();
|
||||
this.FilteredLogEntries = new RollingList<LogEntry>(this.logText.Where(this.IsFilterApplicable), Math.Max(LogLinesMinimum, this.logLinesLimit));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -789,6 +850,14 @@ internal class ConsoleWindow : Window, IDisposable
|
|||
return result;
|
||||
}
|
||||
|
||||
private void OnDalamudConfigurationSaved(DalamudConfiguration dalamudConfiguration)
|
||||
{
|
||||
this.logLinesLimit = dalamudConfiguration.LogLinesLimit;
|
||||
var limit = Math.Max(LogLinesMinimum, this.logLinesLimit);
|
||||
this.logText.Size = limit;
|
||||
this.FilteredLogEntries.Size = limit;
|
||||
}
|
||||
|
||||
private class LogEntry
|
||||
{
|
||||
public string Line { get; init; } = string.Empty;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue