Skip to content

Commit

Permalink
feat: 日志记录功能
Browse files Browse the repository at this point in the history
  • Loading branch information
HelloWRC committed Sep 30, 2024
1 parent 04970a6 commit 865b48b
Show file tree
Hide file tree
Showing 7 changed files with 195 additions and 4 deletions.
8 changes: 5 additions & 3 deletions ClassIsland/App.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,8 @@ public partial class App : AppBase, IAppHost
public static readonly string AppDataFolderPath =
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "ClassIsland");

public static readonly string AppLogFolderPath = "./Logs";

public static readonly string AppConfigPath = "./Config";

public static readonly string AppCacheFolderPath = "./Cache";
Expand Down Expand Up @@ -286,8 +288,6 @@ private async void App_OnStartup(object sender, StartupEventArgs e)
services.AddSingleton<DiagnosticService>();
services.AddSingleton<IManagementService, ManagementService>();
services.AddSingleton<AppLogService>();
services.AddSingleton<ILoggerProvider, SentryLoggerProvider>();
services.AddSingleton<ILoggerProvider, AppLoggerProvider>();
services.AddSingleton<IComponentsService, ComponentsService>();
services.AddSingleton<ILessonsService, LessonsService>();
services.AddSingleton<IUriNavigationService, UriNavigationService>();
Expand Down Expand Up @@ -381,11 +381,13 @@ private async void App_OnStartup(object sender, StartupEventArgs e)
o.InitializeSdk = false;
o.MinimumBreadcrumbLevel = LogLevel.Information;
});
// TODO: 添加写入本地log文件
#if DEBUG
builder.SetMinimumLevel(LogLevel.Trace);
#endif
});
services.AddSingleton<ILoggerProvider, SentryLoggerProvider>();
services.AddSingleton<ILoggerProvider, AppLoggerProvider>();
services.AddSingleton<ILoggerProvider, FileLoggerProvider>();
// AttachedSettings
services.AddAttachedSettingsControl<AfterSchoolNotificationAttachedSettingsControl>();
services.AddAttachedSettingsControl<ClassNotificationAttachedSettingsControl>();
Expand Down
18 changes: 18 additions & 0 deletions ClassIsland/Helpers/GZipHelper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
using System.IO;
using System.IO.Compression;

namespace ClassIsland.Helpers;

public static class GZipHelper
{
public static void CompressFileAndDelete(string path)
{
using var originalFileStream = File.Open(path, FileMode.Open);
using var compressedFileStream = File.Create(path + ".gz");
using var compressor = new GZipStream(compressedFileStream, CompressionMode.Compress);
originalFileStream.CopyTo(compressor);
compressor.Close();
originalFileStream.Close();
File.Delete(path);
}
}
3 changes: 2 additions & 1 deletion ClassIsland/Services/FileFolderService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ public class FileFolderService(SettingsService settingsService, ILogger<FileFold
PluginService.PluginsRootPath,
PluginService.PluginConfigsFolderPath,
PluginService.PluginsIndexPath,
"./Backups"
"./Backups",
App.AppLogFolderPath
};

public static void CreateFolders()
Expand Down
28 changes: 28 additions & 0 deletions ClassIsland/Services/Logging/FileLogger.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
using System;
using System.Windows.Forms;
using Microsoft.Extensions.Logging;
using static System.Windows.Forms.VisualStyles.VisualStyleElement.TaskbarClock;

namespace ClassIsland.Services.Logging;

public class FileLogger(FileLoggerProvider provider, string categoryName) : ILogger
{
private FileLoggerProvider Provider { get; } = provider;
private string CategoryName { get; } = categoryName;

public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func<TState, Exception?, string> formatter)
{
var message = formatter(state, exception) + (exception != null ? "\n" + exception : "");
Provider.WriteLog($"{DateTime.Now}|{logLevel}|{CategoryName}|{message}");
}

public bool IsEnabled(LogLevel logLevel)
{
return false;
}

public IDisposable? BeginScope<TState>(TState state) where TState : notnull
{
return null;
}
}
113 changes: 113 additions & 0 deletions ClassIsland/Services/Logging/FileLoggerProvider.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Shapes;
using ClassIsland.Helpers;
using Microsoft.Extensions.Logging;
using Path = System.IO.Path;

namespace ClassIsland.Services.Logging;

public class FileLoggerProvider : ILoggerProvider
{
private readonly Stream? _logStream;
private readonly StreamWriter? _logWriter;

private readonly ConcurrentDictionary<string, FileLogger> _loggers = new();

private const int LogRetentionDays = 30;

private readonly object _lock = new object();

public static string GetLogFileName()
{
var n = 1;
var logs = GetLogs();
string filename;
do
{
filename = $"log-{DateTime.Now:yyyy-M-d-HH-mm-ss}-{n}.log";
n++;
} while (logs.Contains(filename));

return filename;
}

public FileLoggerProvider()
{
try
{
var logs = Directory.GetFiles(App.AppLogFolderPath);
var currentLogFile = GetLogFileName();
_logStream = File.Open(Path.Combine(App.AppLogFolderPath, currentLogFile), FileMode.Create, FileAccess.ReadWrite, FileShare.Read);
_logWriter = new StreamWriter(_logStream)
{
AutoFlush = true
};
_ = Task.Run(() => ProcessPreviousLogs(logs, currentLogFile));
}
catch (Exception e)
{
Console.WriteLine(e);
}
}

private static void ProcessPreviousLogs(string[] logs, string currentLogFile)
{
foreach (var i in logs.Where(x => Path.GetFileName(x) != currentLogFile && Path.GetExtension(x) == ".log"))
{
try
{
GZipHelper.CompressFileAndDelete(i);
}
catch (Exception e)
{
Console.WriteLine(e);
}
}

var now = DateTime.Now;
foreach (var i in logs.Where(x => (now - File.GetLastWriteTime(x)).TotalDays > LogRetentionDays &&
Path.GetFileName(x) != currentLogFile &&
(x.EndsWith(".log") || x.EndsWith(".log.gz"))))
{
try
{
File.Delete(i);
}
catch (Exception e)
{
Console.WriteLine(e);
}
}
}

private static List<string?> GetLogs()
{
return Directory.GetFiles(App.AppLogFolderPath).Select(Path.GetFileName).ToList();
}

internal void WriteLog(string log)
{
lock (_lock)
{
_logWriter?.WriteLine(log);
}
}

public void Dispose()
{
_logWriter?.Close();
_loggers.Clear();
GC.SuppressFinalize(this);
}

public ILogger CreateLogger(string categoryName)
{
return _loggers.GetOrAdd(categoryName, new FileLogger(this, categoryName));
}
}
9 changes: 9 additions & 0 deletions ClassIsland/Views/SettingsWindowNew.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
xmlns:componentModel="clr-namespace:System.ComponentModel;assembly=WindowsBase"
xmlns:converters1="clr-namespace:ClassIsland.Converters"
xmlns:services="clr-namespace:ClassIsland.Core.Services.Registry;assembly=ClassIsland.Core"
xmlns:commands="http://classisland.tech/schemas/xaml/core"
d:DataContext="{d:DesignInstance local:SettingsWindowNew}"
TextElement.Foreground="{DynamicResource MaterialDesignBody}"
Background="{DynamicResource MaterialDesignPaper}"
Expand Down Expand Up @@ -345,6 +346,14 @@
<MenuItem Icon="{materialDesign:PackIcon DatabaseExportOutline}"
Header="导出诊断数据"
Click="MenuItemExportDiagnosticInfo_OnClick"/>
<Separator/>
<MenuItem Icon="{materialDesign:PackIcon FolderTextOutline}"
Header="打开日志目录…"
Click="MenuItemOpenLogFolder_OnClick"/>
<MenuItem Icon="{materialDesign:PackIcon FolderOutline}"
Header="打开应用目录…"
Click="MenuItemOpenAppFolder_OnClick"/>

</StackPanel>

</StackPanel>
Expand Down
20 changes: 20 additions & 0 deletions ClassIsland/Views/SettingsWindowNew.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@
using ClassIsland.Services;
using CommonDialog = ClassIsland.Core.Controls.CommonDialog.CommonDialog;
using Sentry;
using System.IO;
using Path = System.IO.Path;

namespace ClassIsland.Views;

Expand Down Expand Up @@ -406,4 +408,22 @@ private void NavigationCollectionViewSource_OnFilter(object sender, FilterEventA
return;
}
}

private void MenuItemOpenLogFolder_OnClick(object sender, RoutedEventArgs e)
{
Process.Start(new ProcessStartInfo()
{
FileName = Path.GetFullPath(App.AppLogFolderPath) ?? "",
UseShellExecute = true
});
}

private void MenuItemOpenAppFolder_OnClick(object sender, RoutedEventArgs e)
{
Process.Start(new ProcessStartInfo()
{
FileName = Path.GetFullPath(".") ?? "",
UseShellExecute = true
});
}
}

0 comments on commit 865b48b

Please sign in to comment.