A:添加日志测试类和测试框架
This commit is contained in:
1 parent
efcdf01436
commit
67889796ed
5 files changed
+278
-1
No files matched your search
@@ -0,0 +1,28 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
|
||||||
|
<IsPackable>false</IsPackable>
|
||||||
|
<IsTestProject>true</IsTestProject>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="coverlet.collector" Version="6.0.0"/>
|
||||||
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0"/>
|
||||||
|
<PackageReference Include="NUnit" Version="3.14.0"/>
|
||||||
|
<PackageReference Include="NUnit.Analyzers" Version="3.9.0"/>
|
||||||
|
<PackageReference Include="NUnit3TestAdapter" Version="4.5.0"/>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Using Include="NUnit.Framework"/>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\Common\Common.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
@@ -0,0 +1,222 @@
|
|||||||
|
using Common.Logger;
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
|
using Serilog.Events;
|
||||||
|
|
||||||
|
namespace Common.Test.Logger;
|
||||||
|
|
||||||
|
public class LogTest
|
||||||
|
{
|
||||||
|
[Test]
|
||||||
|
public void Test1()
|
||||||
|
{
|
||||||
|
TaskTest();
|
||||||
|
Assert.Pass();
|
||||||
|
}
|
||||||
|
|
||||||
|
async void TaskTest()
|
||||||
|
{
|
||||||
|
// ===== 使用方式1: 使用默认配置 =====
|
||||||
|
using (var logger = new UniversalLogger())
|
||||||
|
{
|
||||||
|
logger.LogInformation("应用程序启动");
|
||||||
|
logger.LogWarning("这是一个警告消息");
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
throw new Exception("测试异常");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
logger.LogError(ex, "捕获到异常: {Message}", ex.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===== 使用方式2: 自定义配置 =====
|
||||||
|
var config = new LoggerConfig
|
||||||
|
{
|
||||||
|
EnableConsole = true,
|
||||||
|
EnableFile = true,
|
||||||
|
LogPath = "MyAppLogs",
|
||||||
|
MaxFileSizeMB = 2,
|
||||||
|
RetentionDays = 15,
|
||||||
|
CompressDaysThreshold = 2,
|
||||||
|
MinimumLevel = LogEventLevel.Debug,
|
||||||
|
UseJsonFormat = false
|
||||||
|
};
|
||||||
|
|
||||||
|
using (var logger = new UniversalLogger(config))
|
||||||
|
{
|
||||||
|
logger.LogDebug("调试信息");
|
||||||
|
logger.LogInformation("信息消息");
|
||||||
|
logger.LogWarning("警告消息");
|
||||||
|
logger.LogError("错误消息");
|
||||||
|
|
||||||
|
// 带上下文信息的日志
|
||||||
|
var context = new Dictionary<string, object>
|
||||||
|
{
|
||||||
|
["UserId"] = 12345,
|
||||||
|
["Action"] = "Login",
|
||||||
|
["IP"] = "192.168.1.100"
|
||||||
|
};
|
||||||
|
logger.LogWithContext(LogEventLevel.Information, "用户登录", context);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===== 使用方式3: 从配置文件读取 =====
|
||||||
|
var configuration = new ConfigurationBuilder()
|
||||||
|
.AddJsonFile("appsettings.json", optional: false)
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
using (var logger = UniversalLogger.FromConfiguration(configuration, "Logging"))
|
||||||
|
{
|
||||||
|
logger.LogInformation("从配置文件创建的日志记录器");
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===== 使用方式4: 静态日志记录器 =====
|
||||||
|
// 初始化静态日志记录器
|
||||||
|
Log.Initialize(config);
|
||||||
|
|
||||||
|
Log.Information("使用静态日志记录器");
|
||||||
|
Log.Warning("警告消息");
|
||||||
|
Log.Error("错误消息");
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("测试异常");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Log.Error(ex, "静态日志记录器捕获异常");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 手动执行维护任务
|
||||||
|
await Log.RunMaintenanceAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===== 扩展示例: 自定义日志级别和过滤器 =====
|
||||||
|
public static class LoggerExtensions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 记录性能日志
|
||||||
|
/// </summary>
|
||||||
|
public static void LogPerformance(this UniversalLogger logger, string operation, TimeSpan duration,
|
||||||
|
Dictionary<string, object> additionalData = null)
|
||||||
|
{
|
||||||
|
var context = new Dictionary<string, object>
|
||||||
|
{
|
||||||
|
["Operation"] = operation,
|
||||||
|
["Duration"] = duration.TotalMilliseconds,
|
||||||
|
["Category"] = "Performance"
|
||||||
|
};
|
||||||
|
|
||||||
|
if (additionalData != null)
|
||||||
|
{
|
||||||
|
foreach (var kvp in additionalData)
|
||||||
|
{
|
||||||
|
context[kvp.Key] = kvp.Value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.LogWithContext(LogEventLevel.Information, "性能监控: {Operation} 耗时 {Duration}ms", context);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 记录业务日志
|
||||||
|
/// </summary>
|
||||||
|
public static void LogBusiness(this UniversalLogger logger, string action, string entityType, object entityId,
|
||||||
|
Dictionary<string, object> details = null)
|
||||||
|
{
|
||||||
|
var context = new Dictionary<string, object>
|
||||||
|
{
|
||||||
|
["Action"] = action,
|
||||||
|
["EntityType"] = entityType,
|
||||||
|
["EntityId"] = entityId,
|
||||||
|
["Category"] = "Business"
|
||||||
|
};
|
||||||
|
|
||||||
|
if (details != null)
|
||||||
|
{
|
||||||
|
foreach (var kvp in details)
|
||||||
|
{
|
||||||
|
context[kvp.Key] = kvp.Value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.LogWithContext(LogEventLevel.Information, "业务操作: {Action} {EntityType} {EntityId}", context);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 记录安全日志
|
||||||
|
/// </summary>
|
||||||
|
public static void LogSecurity(this UniversalLogger logger, string eventType, string userId, string ipAddress,
|
||||||
|
bool success, string details = null)
|
||||||
|
{
|
||||||
|
var context = new Dictionary<string, object>
|
||||||
|
{
|
||||||
|
["EventType"] = eventType,
|
||||||
|
["UserId"] = userId,
|
||||||
|
["IpAddress"] = ipAddress,
|
||||||
|
["Success"] = success,
|
||||||
|
["Category"] = "Security"
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(details))
|
||||||
|
{
|
||||||
|
context["Details"] = details;
|
||||||
|
}
|
||||||
|
|
||||||
|
var level = success ? LogEventLevel.Information : LogEventLevel.Warning;
|
||||||
|
logger.LogWithContext(level, "安全事件: {EventType} 用户 {UserId} 来自 {IpAddress} {Result}",
|
||||||
|
context,
|
||||||
|
null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===== 使用扩展方法的示例 =====
|
||||||
|
public class ExtensionUsageExample
|
||||||
|
{
|
||||||
|
private readonly UniversalLogger _logger;
|
||||||
|
|
||||||
|
public ExtensionUsageExample()
|
||||||
|
{
|
||||||
|
_logger = new UniversalLogger();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task ProcessUserOrder(int userId, int orderId)
|
||||||
|
{
|
||||||
|
var stopwatch = System.Diagnostics.Stopwatch.StartNew();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// 记录业务日志
|
||||||
|
_logger.LogBusiness("ProcessOrder", "Order", orderId, new Dictionary<string, object>
|
||||||
|
{
|
||||||
|
["UserId"] = userId,
|
||||||
|
["Timestamp"] = DateTime.UtcNow
|
||||||
|
});
|
||||||
|
|
||||||
|
// 模拟业务处理
|
||||||
|
await Task.Delay(1000);
|
||||||
|
|
||||||
|
stopwatch.Stop();
|
||||||
|
|
||||||
|
// 记录性能日志
|
||||||
|
_logger.LogPerformance("ProcessUserOrder", stopwatch.Elapsed, new Dictionary<string, object>
|
||||||
|
{
|
||||||
|
["UserId"] = userId,
|
||||||
|
["OrderId"] = orderId
|
||||||
|
});
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, "处理订单时发生错误: OrderId={OrderId}, UserId={UserId}", orderId, userId);
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void HandleUserLogin(string userId, string ipAddress, bool success)
|
||||||
|
{
|
||||||
|
_logger.LogSecurity("Login", userId, ipAddress, success,
|
||||||
|
success ? "登录成功" : "登录失败");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
namespace Common.Test;
|
||||||
|
|
||||||
|
public class Tests
|
||||||
|
{
|
||||||
|
[SetUp]
|
||||||
|
public void Setup()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void Test1()
|
||||||
|
{
|
||||||
|
Assert.Pass();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -14,6 +14,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Common", "Common\Common.csp
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UI.Shared.Wpf", "UI.Shared.Wpf\UI.Shared.Wpf.csproj", "{8512B4F6-65F3-48EE-845F-09A1692BB901}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UI.Shared.Wpf", "UI.Shared.Wpf\UI.Shared.Wpf.csproj", "{8512B4F6-65F3-48EE-845F-09A1692BB901}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Common.Test", "Common.Test\Common.Test.csproj", "{B3F481C9-B351-449C-AE2B-CDEC29BD5DCC}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
@@ -48,5 +50,9 @@ Global
|
|||||||
{8512B4F6-65F3-48EE-845F-09A1692BB901}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{8512B4F6-65F3-48EE-845F-09A1692BB901}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{8512B4F6-65F3-48EE-845F-09A1692BB901}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{8512B4F6-65F3-48EE-845F-09A1692BB901}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{8512B4F6-65F3-48EE-845F-09A1692BB901}.Release|Any CPU.Build.0 = Release|Any CPU
|
{8512B4F6-65F3-48EE-845F-09A1692BB901}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{B3F481C9-B351-449C-AE2B-CDEC29BD5DCC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{B3F481C9-B351-449C-AE2B-CDEC29BD5DCC}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{B3F481C9-B351-449C-AE2B-CDEC29BD5DCC}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{B3F481C9-B351-449C-AE2B-CDEC29BD5DCC}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
EndGlobal
|
EndGlobal
|
||||||
@@ -9,4 +9,10 @@
|
|||||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AReadOnlyCollectionBase_002Ecs_002Fl_003AC_0021_003FUsers_003Fcharlatans_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F4c1fd115dbe5414db1b4da1de3e96c5819910_003F04_003Fcae9fe22_003FReadOnlyCollectionBase_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AReadOnlyCollectionBase_002Ecs_002Fl_003AC_0021_003FUsers_003Fcharlatans_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F4c1fd115dbe5414db1b4da1de3e96c5819910_003F04_003Fcae9fe22_003FReadOnlyCollectionBase_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ATimer_002Ecs_002Fl_003AC_0021_003FUsers_003Fcharlatans_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F211e6f3b24fa438a92f1815153647ce2c8f908_003Fa8_003F04476824_003FTimer_002Ecs_002Fz_003A2_002D1/@EntryIndexedValue">ForceIncluded</s:String>
|
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ATimer_002Ecs_002Fl_003AC_0021_003FUsers_003Fcharlatans_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F211e6f3b24fa438a92f1815153647ce2c8f908_003Fa8_003F04476824_003FTimer_002Ecs_002Fz_003A2_002D1/@EntryIndexedValue">ForceIncluded</s:String>
|
||||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ATimer_002Ecs_002Fl_003AC_0021_003FUsers_003Fcharlatans_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003Ffe2ae574758f4da99bb3bfcba69a0a40b6928_003F7f_003Fb5cb1e21_003FTimer_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ATimer_002Ecs_002Fl_003AC_0021_003FUsers_003Fcharlatans_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003Ffe2ae574758f4da99bb3bfcba69a0a40b6928_003F7f_003Fb5cb1e21_003FTimer_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AWebView2_002Ecs_002Fl_003AC_0021_003FUsers_003Fcharlatans_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F8aca2f2c90e1454c825fc8b69c53a97e14268_003F06_003F22dc0e77_003FWebView2_002Ecs/@EntryIndexedValue">ForceIncluded</s:String></wpf:ResourceDictionary>
|
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AWebView2_002Ecs_002Fl_003AC_0021_003FUsers_003Fcharlatans_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F8aca2f2c90e1454c825fc8b69c53a97e14268_003F06_003F22dc0e77_003FWebView2_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||||
|
<s:String x:Key="/Default/Environment/UnitTesting/UnitTestSessionStore/Sessions/=f4a8c497_002D43fb_002D4de1_002D9ffa_002D84076d7db2c5/@EntryIndexedValue"><SessionState ContinuousTestingMode="0" IsActive="True" Name="Test1" xmlns="urn:schemas-jetbrains-com:jetbrains-ut-session">
|
||||||
|
<TestAncestor>
|
||||||
|
<TestId>NUnit3x::B3F481C9-B351-449C-AE2B-CDEC29BD5DCC::net8.0::Common.Test.Tests.Test1</TestId>
|
||||||
|
<TestId>NUnit3x::B3F481C9-B351-449C-AE2B-CDEC29BD5DCC::net8.0::Common.Test.Logger.LogTest.Test1</TestId>
|
||||||
|
</TestAncestor>
|
||||||
|
</SessionState></s:String></wpf:ResourceDictionary>
|
||||||
Reference in new issue
Block a user