Skip to content

Commit

Permalink
Define ILogGroup to control progressive logs removing in same group.
Browse files Browse the repository at this point in the history
  • Loading branch information
hamster620 committed Aug 18, 2024
1 parent e0af9e0 commit ab98dbe
Show file tree
Hide file tree
Showing 4 changed files with 127 additions and 12 deletions.
17 changes: 17 additions & 0 deletions ULogViewer/Logs/ILogGroup.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
using System;
using CarinaStudio.Threading;

namespace CarinaStudio.ULogViewer.Logs;

/// <summary>
/// Group of logs.
/// </summary>
public interface ILogGroup: IThreadDependent
{
/// <summary>
/// Schedule to trigger progressive logs removing.
/// </summary>
/// <param name="triggerAction">Function to be called to trigger logs removing.</param>
/// <returns><see cref="IDisposable"/> represents scheduled or on going progressive logs removing.</returns>
IDisposable ScheduleProgressiveLogsRemoving(Func<bool> triggerAction);
}
37 changes: 34 additions & 3 deletions ULogViewer/Logs/LogReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ class LogReader : BaseDisposable, IApplicationObject, INotifyPropertyChanged
readonly SingleThreadSynchronizationContext pendingLogsSyncContext = new();
LogReadingPrecondition precondition;
bool printTraceLogs;
IDisposable? progressiveLogsClearingToken;
string? rawLogLevelPropertyName;
readonly IDictionary<string, LogLevel> readOnlyLogLevelMap;
readonly TaskFactory readingTaskFactory;
Expand All @@ -75,9 +76,10 @@ class LogReader : BaseDisposable, IApplicationObject, INotifyPropertyChanged
/// <summary>
/// Initialize new <see cref="LogReader"/> instance.
/// </summary>
/// <param name="group"><see cref="ILogGroup"/> the reader belongs to.</param>
/// <param name="dataSource"><see cref="ILogDataSource"/> to read log data from.</param>
/// <param name="readingTaskFactory"><see cref="TaskFactory"/> to perform logs reading tasks.</param>
public LogReader(ILogDataSource dataSource, TaskFactory readingTaskFactory)
public LogReader(ILogGroup? group, ILogDataSource dataSource, TaskFactory readingTaskFactory)
{
// check thread
dataSource.VerifyAccess();
Expand All @@ -87,6 +89,7 @@ public LogReader(ILogDataSource dataSource, TaskFactory readingTaskFactory)
this.DataSource = dataSource;
this.Id = nextId++;
this.Logger = dataSource.Application.LoggerFactory.CreateLogger($"{this.GetType().Name}-{this.Id}");
this.LogGroup = group;
this.Logs = new ReadOnlyObservableList<Log>(this.logs);
this.printTraceLogs = this.Application.IsDebugMode;
this.readingTaskFactory = readingTaskFactory;
Expand Down Expand Up @@ -226,10 +229,31 @@ public void ClearLogs(bool progressive = false)

// start clearing logs
if (progressive)
this.clearLogChunkAction.Schedule();
{
if (this.LogGroup != null)
{
this.Logger.LogDebug("Schedule progressive logs clearing");
this.progressiveLogsClearingToken = this.LogGroup.ScheduleProgressiveLogsRemoving(() =>
{
if (this.state == LogReaderState.ClearingLogs)
{
this.Logger.LogDebug("Start progressive logs clearing");
this.clearLogChunkAction.Schedule();
return true;
}
return false;
});
}
else
{
this.Logger.LogDebug("Start progressive logs clearing");
this.clearLogChunkAction.Schedule();
}
}
else
{
this.clearLogChunkAction.Cancel();
this.progressiveLogsClearingToken = this.progressiveLogsClearingToken.DisposeAndReturnNull();
this.logs.Clear();
if (this.Application.Settings.GetValueOrDefault(SettingKeys.MemoryUsagePolicy) != MemoryUsagePolicy.BetterPerformance)
this.logs.TrimExcess();
Expand Down Expand Up @@ -410,6 +434,12 @@ private set
}


/// <summary>
/// Get <see cref="ILogGroup"/> the reader belongs to.
/// </summary>
public ILogGroup? LogGroup { get; }


/// <summary>
/// Get or set mode of matching raw log lines by patterns.
/// </summary>
Expand Down Expand Up @@ -500,7 +530,7 @@ public IDictionary<string, LogLevel> LogLevelMap
this.VerifyAccess();
if (this.state != LogReaderState.Preparing)
throw new InvalidOperationException($"Cannot change {nameof(LogLevelMap)} when state is {this.state}.");
if (this.logLevelMap.SequenceEqual(value))
if (this.logLevelMap.Equals(value))
return;
this.logLevelMap.Clear();
foreach (var pair in value)
Expand Down Expand Up @@ -613,6 +643,7 @@ void OnLogsClearingCompleted()
if (this.state != LogReaderState.ClearingLogs)
return;
this.logsReadingCacheMemorySize = 0;
this.progressiveLogsClearingToken = this.progressiveLogsClearingToken.DisposeAndReturnNull();
if (this.isRestarting)
{
this.Logger.LogWarning("Logs cleared, start reading logs");
Expand Down
83 changes: 75 additions & 8 deletions ULogViewer/ViewModels/DisplayableLogGroup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ namespace CarinaStudio.ULogViewer.ViewModels
/// <summary>
/// Group of <see cref="DisplayableLog"/>.
/// </summary>
partial class DisplayableLogGroup : BaseDisposable, IApplicationObject
partial class DisplayableLogGroup : BaseDisposable, IApplicationObject, ILogGroup
{
/// <summary>
/// Maximum number of log reader can be added to each group.
Expand All @@ -33,18 +33,37 @@ partial class DisplayableLogGroup : BaseDisposable, IApplicationObject


// Control block of log reader.
class LogReaderInfo
class LogReaderInfo(LogReader reader, byte localId)
{
// Fields.
public int DisplayableLogCount;
public readonly byte LocalId;
public readonly LogReader LogReader;
public readonly byte LocalId = localId;
public readonly LogReader LogReader = reader;
}


// Constructor.
public LogReaderInfo(LogReader reader, byte localId)
// Token of progressive logs removing.
class ProgressiveLogsRemovingToken(DisplayableLogGroup group, Func<bool> triggerAction): BaseDisposable
{
// Dispose.
protected override void Dispose(bool disposing)
{
this.LocalId = localId;
this.LogReader = reader;
if (disposing)
group.CancelProgressiveLogsRemoving(this);
}

// Whether logs removing was triggered or not.
public bool IsTriggered { get; private set; }

// Trigger logs removing.
public bool Trigger()
{
if (triggerAction())
{
IsTriggered = true;
return true;
}
return false;
}
}

Expand All @@ -64,6 +83,7 @@ public LogReaderInfo(LogReader reader, byte localId)


// Fields.
ProgressiveLogsRemovingToken? activeProgressiveLogsRemovingToken;
IList<Regex> activeTextFilters = Array.Empty<Regex>();
readonly Dictionary<DisplayableLogAnalysisResultType, IImage> analysisResultIndicatorIcons = new();
readonly Dictionary<string, IBrush> colorIndicatorBrushes = new();
Expand All @@ -80,11 +100,13 @@ public LogReaderInfo(LogReader reader, byte localId)
readonly object memorySizeLock = new();
readonly Random random = new();
readonly Queue<Color> recentlyUsedColorIndicatorColors = new(RecentlyUsedColorIndicatorColorCount);
readonly List<ProgressiveLogsRemovingToken> scheduledProgressiveLogsRemovingTokens = new();
int? selectedProcessId;
int? selectedThreadId;
readonly Stopwatch stopwatch = new();
IBrush? textHighlightingBackground;
IBrush? textHighlightingForeground;
readonly ScheduledAction triggerProgressiveLogsRemovingAction;
readonly ScheduledAction updateLevelMapAction;
readonly ScheduledAction updateTextHighlightingDefSetAction;

Expand Down Expand Up @@ -123,6 +145,24 @@ public DisplayableLogGroup(LogProfile profile)
this.UpdateLevelMapForDisplaying();

// setup actions
this.triggerProgressiveLogsRemovingAction = new(() =>
{
if (this.activeProgressiveLogsRemovingToken != null)
return;
while (this.scheduledProgressiveLogsRemovingTokens.IsNotEmpty())
{
var token = this.scheduledProgressiveLogsRemovingTokens[0];
this.scheduledProgressiveLogsRemovingTokens.RemoveAt(0);
if (token.Trigger())
{
this.activeProgressiveLogsRemovingToken = token;
this.logger.LogDebug("Progressive logs removing triggered, pending: {count}", this.scheduledProgressiveLogsRemovingTokens.Count);
break;
}
}
if (this.activeProgressiveLogsRemovingToken == null && this.scheduledProgressiveLogsRemovingTokens.IsEmpty())
this.logger.LogDebug("All progressive logs removing completed");
});
this.updateTextHighlightingDefSetAction = new(() =>
{
var definitions = this.TextHighlightingDefinitionSet.TokenDefinitions;
Expand Down Expand Up @@ -277,6 +317,21 @@ public IList<Regex> ActiveTextFilters
/// Get <see cref="IULogViewerApplication"/> instance.
/// </summary>
public IULogViewerApplication Application { get; }


// Cancel scheduled or on going progressive logs removing.
void CancelProgressiveLogsRemoving(ProgressiveLogsRemovingToken token)
{
this.VerifyAccess();
if (this.activeProgressiveLogsRemovingToken == token)
{
this.logger.LogDebug("Complete current progressive logs removing");
this.activeProgressiveLogsRemovingToken = null;
this.triggerProgressiveLogsRemovingAction.Schedule();
}
else if (this.scheduledProgressiveLogsRemovingTokens.Remove(token))
this.logger.LogDebug("Cancel scheduled progressive logs removing, pending: {count}", this.scheduledProgressiveLogsRemovingTokens.Count);
}


// Check state of Extra* log properties.
Expand Down Expand Up @@ -803,6 +858,18 @@ public void RemoveAnalysisResults(IDisplayableLogAnalyzer<DisplayableLogAnalysis
log = log.Next;
}
}


// Schedule progressive logs removing.
IDisposable ILogGroup.ScheduleProgressiveLogsRemoving(Func<bool> triggerAction)
{
this.VerifyAccess();
var token = new ProgressiveLogsRemovingToken(this, triggerAction);
this.scheduledProgressiveLogsRemovingTokens.Add(token);
this.logger.LogDebug("Schedule progressive logs removing, pending: {count}", this.scheduledProgressiveLogsRemovingTokens.Count);
this.triggerProgressiveLogsRemovingAction.Schedule();
return token;
}


/// <summary>
Expand Down
2 changes: 1 addition & 1 deletion ULogViewer/ViewModels/Session.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2137,7 +2137,7 @@ bool CreateLogReader(ILogDataSource dataSource, LogReadingPrecondition precondit
: defaultLogsReadingTaskFactory;

// create log reader
var logReader = new LogReader(dataSource, readingTaskFactory).Also(it =>
var logReader = new LogReader(this.displayableLogGroup, dataSource, readingTaskFactory).Also(it =>
{
if (profile.IsContinuousReading)
it.UpdateInterval = this.ContinuousLogReadingUpdateInterval;
Expand Down

0 comments on commit ab98dbe

Please sign in to comment.