Skip to content

Commit

Permalink
Added help menu option to view debug log file
Browse files Browse the repository at this point in the history
  • Loading branch information
jschick04 authored and bill-long committed Dec 2, 2024
1 parent 29b429e commit 389ee48
Show file tree
Hide file tree
Showing 9 changed files with 163 additions and 18 deletions.
4 changes: 4 additions & 0 deletions src/EventLogExpert.Eventing/Helpers/ITraceLogger.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,9 @@ namespace EventLogExpert.Eventing.Helpers;

public interface ITraceLogger
{
Task ClearAsync();

IAsyncEnumerable<string> LoadAsync();

void Trace(string message, LogLevel level = LogLevel.Information);
}
84 changes: 66 additions & 18 deletions src/EventLogExpert.UI/Services/DebugLogService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,44 +2,99 @@
// // Licensed under the MIT License.

using EventLogExpert.Eventing.Helpers;
using EventLogExpert.UI.Interfaces;
using EventLogExpert.UI.Options;
using EventLogExpert.UI.Store.Settings;
using Fluxor;
using Microsoft.Extensions.Logging;
using System.Diagnostics;

namespace EventLogExpert.UI.Services;

public class DebugLogService : ITraceLogger
public sealed class DebugLogService : ITraceLogger
{
private static readonly long _maxLogSize = 10 * 1024 * 1024;
private const long MaxLogSize = 10 * 1024 * 1024;
private static readonly ReaderWriterLockSlim s_loggingFileLock = new();

private readonly FileLocationOptions _fileLocationOptions;
private readonly LogLevel _loggingLevel;
private readonly IState<SettingsState> _settingsState;

public DebugLogService(FileLocationOptions fileLocationOptions, IPreferencesProvider preferencesProvider)
public DebugLogService(FileLocationOptions fileLocationOptions, IState<SettingsState> settingsState)
{
_loggingLevel = preferencesProvider.LogLevelPreference;
_fileLocationOptions = fileLocationOptions;
_settingsState = settingsState;

InitTracing();
}

public async Task ClearAsync()
{
s_loggingFileLock.EnterWriteLock();

try
{
await File.WriteAllTextAsync(_fileLocationOptions.LoggingPath, string.Empty);
}
finally
{
s_loggingFileLock.ExitWriteLock();
}
}

public async IAsyncEnumerable<string> LoadAsync()
{
s_loggingFileLock.EnterReadLock();

try
{
await foreach (var line in File.ReadLinesAsync(_fileLocationOptions.LoggingPath))
{
yield return line;
}
}
finally
{
s_loggingFileLock.ExitReadLock();
}
}

public void Trace(string message, LogLevel level = LogLevel.Information)
{
if (level < _settingsState.Value.Config.LogLevel) { return; }

string output = $"[{DateTime.Now:o}] [{Environment.CurrentManagedThreadId}] [{level}] {message}";

s_loggingFileLock.EnterWriteLock();

try
{
using StreamWriter writer = File.AppendText(_fileLocationOptions.LoggingPath);

writer.WriteLine(output);
}
finally
{
s_loggingFileLock.ExitWriteLock();
}

#if DEBUG
Debug.WriteLine(output);
#endif
}

private void InitTracing()
{
// Set up tracing to a file
var fileInfo = new FileInfo(_fileLocationOptions.LoggingPath);

if (fileInfo.Exists && fileInfo.Length > _maxLogSize)
if (fileInfo is { Exists: true, Length: > MaxLogSize })
{
fileInfo.Delete();
}

System.Diagnostics.Trace.Listeners.Add(new TextWriterTraceListener(_fileLocationOptions.LoggingPath, "myListener"));
System.Diagnostics.Trace.AutoFlush = true;

// Disabling first chance exception logging unless LogLevel is at Trace level
// since it is noisy and is logging double information for exceptions that are being handled.
// This also saves any potential performance hit for when we aren't worried about tracking first chance exceptions.
if (_loggingLevel > LogLevel.Trace) { return; }
if (_settingsState.Value.Config.LogLevel > LogLevel.Trace) { return; }

var firstChanceSemaphore = new SemaphoreSlim(1);

Expand All @@ -59,11 +114,4 @@ private void InitTracing()
}
};
}

public void Trace(string message, LogLevel level = LogLevel.Information)
{
if (level < _loggingLevel) { return; }

System.Diagnostics.Trace.WriteLine($"[{DateTime.Now:o}] [{Environment.CurrentManagedThreadId}] [{level}] {message}");
}
}
2 changes: 2 additions & 0 deletions src/EventLogExpert.UI/Store/Settings/SettingsAction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ public sealed record LoadSettings;

public sealed record LoadSettingsCompleted(SettingsModel Config, IList<string> DisabledDatabases);

public sealed record OpenDebugLog;

public sealed record OpenMenu;

public sealed record Save(SettingsModel Settings);
Expand Down
1 change: 1 addition & 0 deletions src/EventLogExpert/MainPage.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@
<MenuFlyoutItem Text="Submit an Issue" Clicked="SubmitAnIssue_Clicked" />
<MenuFlyoutItem Text="Check for Updates" Clicked="CheckForUpdates_Clicked" />
<MenuFlyoutItem Text="Release Notes" Clicked="ReleaseNotes_Clicked" />
<MenuFlyoutItem Text="View Logs" Clicked="ViewLogs_Clicked" />
</MenuBarItem>
</ContentPage.MenuBarItems>

Expand Down
3 changes: 3 additions & 0 deletions src/EventLogExpert/MainPage.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -469,6 +469,9 @@ private async void SubmitAnIssue_Clicked(object sender, EventArgs e)
private void ViewFilterGroups_Clicked(object? sender, EventArgs e) =>
_fluxorDispatcher.Dispatch(new FilterGroupAction.OpenMenu());

private void ViewLogs_Clicked(object? sender, EventArgs e) =>
_fluxorDispatcher.Dispatch(new SettingsAction.OpenDebugLog());

private void ViewRecentFilters_Clicked(object sender, EventArgs e) =>
_fluxorDispatcher.Dispatch(new FilterCacheAction.OpenMenu());
}
28 changes: 28 additions & 0 deletions src/EventLogExpert/Shared/Components/DebugLogModal.razor
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
@inherits Base.BaseModal

<dialog id="debugLogDialog" @ref="ElementReference">
<div class="dialog-group">
<div class="flex-column-scroll">
@if (_data.Any())
{
@foreach(var line in _data)
{
<text>@line</text><br />
}
}
else
{
<text>Log is Empty...</text>
}
</div>

<div class="footer-group">
<div>
<button class="button" @onclick="Refresh">Refresh</button>
<button class="button" @onclick="Clear">Clear</button>
</div>

<button class="button" @onclick="Close">Exit</button>
</div>
</div>
</dialog>
50 changes: 50 additions & 0 deletions src/EventLogExpert/Shared/Components/DebugLogModal.razor.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// // Copyright (c) Microsoft Corporation.
// // Licensed under the MIT License.

using EventLogExpert.Eventing.Helpers;
using EventLogExpert.UI.Store.Settings;
using Microsoft.AspNetCore.Components;

namespace EventLogExpert.Shared.Components;

public partial class DebugLogModal
{
private readonly List<string> _data = [];

[Inject] private ITraceLogger TraceLogger { get; set; } = null!;

protected internal override async Task Open()
{
await Refresh();

await base.Open();
}

protected override void OnInitialized()
{
SubscribeToAction<SettingsAction.OpenDebugLog>(action => Open().AndForget());

base.OnInitialized();
}

private async Task Clear()
{
_data.Clear();

await TraceLogger.ClearAsync();

StateHasChanged();
}

private async Task Refresh()
{
_data.Clear();

await foreach (var line in TraceLogger.LoadAsync())
{
_data.Add(line);
}

StateHasChanged();
}
}
8 changes: 8 additions & 0 deletions src/EventLogExpert/Shared/Components/DebugLogModal.razor.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
dialog {
height: 60%;
min-width: 50rem;
color: var(--clr-lightblue);

border-color: var(--clr-statusbar);
background-color: var(--background-dark);
}
1 change: 1 addition & 0 deletions src/EventLogExpert/Shared/MainLayout.razor
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
<SettingsModal />
<FilterCacheModal />
<FilterGroupModal />
<DebugLogModal />

<TableColumnMenu />
<ContextMenu />
Expand Down

0 comments on commit 389ee48

Please sign in to comment.