RSDistributedLoggingLibrary 1.0.4
dotnet add package RSDistributedLoggingLibrary --version 1.0.4
NuGet\Install-Package RSDistributedLoggingLibrary -Version 1.0.4
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="RSDistributedLoggingLibrary" Version="1.0.4" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="RSDistributedLoggingLibrary" Version="1.0.4" />
<PackageReference Include="RSDistributedLoggingLibrary" />
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add RSDistributedLoggingLibrary --version 1.0.4
The NuGet Team does not provide support for this client. Please contact its maintainers for support.
#r "nuget: RSDistributedLoggingLibrary, 1.0.4"
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package RSDistributedLoggingLibrary@1.0.4
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=RSDistributedLoggingLibrary&version=1.0.4
#tool nuget:?package=RSDistributedLoggingLibrary&version=1.0.4
The NuGet Team does not provide support for this client. Please contact its maintainers for support.
RSDistributedLoggingLibrary - 分布式日志库
📋 目录
🌟 功能特点
- ✅ 程序员姓名记录 - 支持记录程序员姓名,用于Bug统计和责任追踪
- ✅ 美化日志格式 - 清晰易读的控制台和文件输出,包含图标和结构化显示
- ✅ 多种输出方式 - 支持文件、RabbitMQ、双重输出
- ✅ AOP切面编程 - 基于PostSharp的方法拦截日志
- ✅ 异步日志记录 - 支持异步日志记录,提高性能
- ✅ 丰富的异常类型 - 预定义多种业务异常类型
- ✅ JSON格式支持 - 同时支持美化格式和JSON格式
- ✅ 灵活配置 - 支持配置文件动态配置
🚀 快速开始
1. 安装NuGet包
Install-Package RSDistributedLoggingLibrary
2. 基础配置
appsettings.json 配置
{
"LogSettings": {
"LogLevel": "Info",
"LogOutput": "FileAndQueue",
"FilePath": "logs",
"DefaultDeveloperName": "张三",
"ProjectName": "我的项目",
"RabbitMQ": {
"Host": "localhost",
"Port": 5672,
"Username": "admin",
"Password": "admin123",
"QueueName": "rslog_queue",
"Exchange": "rslog_exchange",
"RoutingKey": "log_key",
"VirtualHost": "rslog"
}
}
}
初始化代码
using Microsoft.Extensions.Configuration;
using RSDistributedLoggingLibrary;
// 读取配置
var configuration = new ConfigurationBuilder()
.AddJsonFile("appsettings.json")
.Build();
var logConfig = configuration.GetSection("LogSettings").Get<LogConfiguration>();
LogStaticHelper.Initialize(logConfig);
📚 项目集成指南
ASP.NET Core Web API 项目
Program.cs
using Microsoft.Extensions.Configuration;
using RSDistributedLoggingLibrary;
var builder = WebApplication.CreateBuilder(args);
// 添加日志配置
var logConfig = builder.Configuration.GetSection("LogSettings").Get<LogConfiguration>();
LogStaticHelper.Initialize(logConfig);
builder.Services.AddControllers();
var app = builder.Build();
// 添加全局异常处理中间件
app.UseMiddleware<LoggingMiddleware>();
app.UseRouting();
app.MapControllers();
app.Run();
控制器中使用
[ApiController]
[Route("api/[controller]")]
public class OrderController : ControllerBase
{
private readonly Logger _logger;
public OrderController()
{
_logger = new Logger("李四", "电商系统");
}
[HttpPost]
[LogException] // AOP自动记录异常
public async Task<IActionResult> CreateOrder([FromBody] CreateOrderRequest request)
{
try
{
_logger.LogMessage("开始创建订单", "Info", "业务");
// 业务逻辑
var orderId = await ProcessOrder(request);
_logger.LogMessage($"订单创建成功,订单号:{orderId}", "Info", "业务");
return Ok(new { OrderId = orderId });
}
catch (ValidationException ex)
{
_logger.LogWarning(ex, "订单验证失败");
return BadRequest(ex.Message);
}
catch (BusinessException ex)
{
_logger.LogError(ex, "业务逻辑错误");
return StatusCode(500, "业务处理失败");
}
}
[ExecutionTimeLogger] // AOP自动记录执行时间
private async Task<string> ProcessOrder(CreateOrderRequest request)
{
// 模拟业务逻辑
if (string.IsNullOrEmpty(request.ProductId))
{
throw new ValidationException("产品ID不能为空", new[] { "ProductId" });
}
if (request.Quantity <= 0)
{
throw new BusinessException("订单数量必须大于0", "ORDER_QUANTITY_INVALID");
}
// 异步处理
await Task.Delay(100);
return Guid.NewGuid().ToString();
}
}
Windows Forms 项目
Form1.cs
using Microsoft.Extensions.Configuration;
using RSDistributedLoggingLibrary;
public partial class Form1 : Form
{
private readonly Logger _logger;
public Form1()
{
InitializeComponent();
InitializeLogging();
_logger = new Logger("王五", "桌面应用");
}
private void InitializeLogging()
{
var configuration = new ConfigurationBuilder()
.SetBasePath(Application.StartupPath)
.AddJsonFile("appsettings.json", optional: false)
.Build();
var logConfig = configuration.GetSection("LogSettings").Get<LogConfiguration>();
LogStaticHelper.Initialize(logConfig);
_logger.LogMessage("应用程序启动", "Info", "系统");
}
private async void btnSave_Click(object sender, EventArgs e)
{
try
{
_logger.LogMessage("用户点击保存按钮", "Info", "用户操作");
await SaveDataAsync();
_logger.LogMessage("数据保存成功", "Info", "业务");
MessageBox.Show("保存成功!");
}
catch (DatabaseException ex)
{
_logger.LogError(ex, "数据库保存失败");
MessageBox.Show("保存失败,请重试");
}
}
[LogException]
private async Task SaveDataAsync()
{
// 模拟数据保存
if (string.IsNullOrEmpty(txtName.Text))
{
throw new ValidationException("姓名不能为空", new[] { "Name" });
}
await Task.Delay(500); // 模拟异步操作
}
}
控制台应用项目
Program.cs
using Microsoft.Extensions.Configuration;
using RSDistributedLoggingLibrary;
class Program
{
private static Logger _logger;
static async Task Main(string[] args)
{
// 初始化日志系统
var configuration = new ConfigurationBuilder()
.SetBasePath(AppDomain.CurrentDomain.BaseDirectory)
.AddJsonFile("appsettings.json", optional: false)
.Build();
var logConfig = configuration.GetSection("LogSettings").Get<LogConfiguration>();
LogStaticHelper.Initialize(logConfig);
_logger = new Logger("赵六", "批处理系统");
try
{
_logger.LogMessage("批处理任务开始", "Info", "系统");
await ProcessBatchJob();
_logger.LogMessage("批处理任务完成", "Info", "系统");
}
catch (Exception ex)
{
_logger.LogError(ex, "批处理任务失败");
}
Console.WriteLine("按任意键退出...");
Console.ReadKey();
}
[ExecutionTimeLogger]
static async Task ProcessBatchJob()
{
for (int i = 1; i <= 10; i++)
{
try
{
_logger.LogMessage($"处理第 {i} 个任务", "Info", "业务");
// 模拟处理
await Task.Delay(100);
if (i == 7) // 模拟第7个任务失败
{
throw new BusinessException($"第 {i} 个任务处理失败", "TASK_FAILED");
}
}
catch (BusinessException ex)
{
_logger.LogWarning(ex, $"任务 {i} 处理异常,继续下一个");
}
}
}
}
🔧 使用方式详解
方式1:静态方法调用(兼容老代码)
// 基础异常记录
try
{
// 业务代码
}
catch (Exception ex)
{
// 不指定程序员姓名,使用配置文件默认值
LogStaticHelper.LogError(ex, "发生异常");
// 指定程序员姓名
LogStaticHelper.LogError(ex, "发生异常", "张三");
}
// 不同级别的日志
LogStaticHelper.LogDebug(exception, "调试信息", "开发者A");
LogStaticHelper.LogInfo(exception, "一般信息", "开发者B");
LogStaticHelper.LogWarning(exception, "警告信息", "开发者C");
LogStaticHelper.LogError(exception, "错误信息", "开发者D");
// 自定义消息日志
LogStaticHelper.LogMessage("用户登录成功", "Info", "业务", "李四");
LogStaticHelper.LogMessage("系统性能监控", "Warning", "性能", "王五");
方式2:Logger实例方式(推荐)
// 创建Logger实例
var logger = new Logger("张三", "电商系统");
// 记录异常
try
{
// 业务代码
}
catch (Exception ex)
{
logger.LogError(ex, "订单处理失败");
}
// 记录业务日志
logger.LogMessage("订单创建成功", "Info", "业务");
logger.LogMessage("库存不足警告", "Warning", "库存");
// 异步记录(推荐在高并发场景使用)
await logger.LogErrorAsync(ex, "异步异常处理");
await logger.LogMessageAsync("异步业务日志", "Info", "异步业务");
// 可以动态指定程序员姓名(覆盖构造函数中的默认值)
logger.LogError(ex, "特殊异常", "临时开发者");
方式3:AOP特性方式(自动记录)
[LogException] // 自动记录异常
[ExecutionTimeLogger] // 自动记录执行时间
public async Task<string> BusinessMethod(string param)
{
// 业务代码
// 如果发生异常,会自动记录日志
// 方法执行时间也会自动记录
await Task.Delay(100);
return "success";
}
// 只记录异常
[LogException]
public void ValidateData(string data)
{
if (string.IsNullOrEmpty(data))
{
throw new ValidationException("数据不能为空", new[] { "data" });
}
}
// 只记录执行时间
[ExecutionTimeLogger]
public void PerformanceMonitorMethod()
{
// 性能敏感的代码
Thread.Sleep(200);
}
💼 实际案例
案例1:电商订单系统
public class OrderService
{
private readonly Logger _logger;
public OrderService()
{
_logger = new Logger("电商开发组", "订单系统");
}
[LogException]
[ExecutionTimeLogger]
public async Task<OrderResult> CreateOrderAsync(CreateOrderRequest request)
{
_logger.LogMessage($"开始创建订单,用户ID:{request.UserId}", "Info", "订单");
try
{
// 1. 验证请求
ValidateOrderRequest(request);
// 2. 检查库存
await CheckInventoryAsync(request.Items);
// 3. 计算价格
var totalAmount = CalculateOrderAmount(request.Items);
_logger.LogMessage($"订单金额计算完成:{totalAmount}", "Info", "计算");
// 4. 创建订单
var orderId = await CreateOrderInDatabaseAsync(request, totalAmount);
// 5. 扣减库存
await ReduceInventoryAsync(request.Items);
_logger.LogMessage($"订单创建成功,订单号:{orderId}", "Info", "订单");
return new OrderResult { OrderId = orderId, Success = true };
}
catch (ValidationException ex)
{
_logger.LogWarning(ex, "订单验证失败");
throw;
}
catch (BusinessException ex)
{
_logger.LogError(ex, "订单业务逻辑错误");
throw;
}
catch (DatabaseException ex)
{
_logger.LogError(ex, "订单数据库操作失败");
throw new BusinessException("系统繁忙,请稍后重试", "SYSTEM_BUSY", ex);
}
}
private void ValidateOrderRequest(CreateOrderRequest request)
{
var errors = new List<string>();
if (string.IsNullOrEmpty(request.UserId))
errors.Add("用户ID不能为空");
if (request.Items == null || !request.Items.Any())
errors.Add("订单商品不能为空");
if (errors.Any())
{
throw new ValidationException("订单验证失败", errors);
}
}
private async Task CheckInventoryAsync(List<OrderItem> items)
{
foreach (var item in items)
{
try
{
var stock = await GetProductStockAsync(item.ProductId);
if (stock < item.Quantity)
{
throw new BusinessException($"商品 {item.ProductId} 库存不足", "INSUFFICIENT_STOCK");
}
}
catch (ExternalServiceException ex)
{
_logger.LogError(ex, $"检查商品 {item.ProductId} 库存时外部服务异常");
throw new BusinessException("库存服务暂时不可用", "INVENTORY_SERVICE_UNAVAILABLE", ex);
}
}
}
}
案例2:数据同步服务
public class DataSyncService
{
private readonly Logger _logger;
public DataSyncService()
{
_logger = new Logger("数据组", "同步服务");
}
[LogException]
public async Task StartSyncJobAsync()
{
_logger.LogMessage("数据同步任务开始", "Info", "同步");
try
{
var totalRecords = await GetTotalRecordsAsync();
_logger.LogMessage($"总共需要同步 {totalRecords} 条记录", "Info", "同步");
var batchSize = 1000;
var processedCount = 0;
var errorCount = 0;
for (int offset = 0; offset < totalRecords; offset += batchSize)
{
try
{
var records = await GetRecordsBatchAsync(offset, batchSize);
await ProcessBatchAsync(records);
processedCount += records.Count;
_logger.LogMessage($"已处理 {processedCount}/{totalRecords} 条记录", "Info", "进度");
}
catch (DatabaseException ex)
{
errorCount++;
_logger.LogError(ex, $"处理批次 {offset}-{offset + batchSize} 时数据库异常");
if (errorCount > 5)
{
throw new BusinessException("连续错误次数过多,停止同步", "TOO_MANY_ERRORS", ex);
}
}
catch (NetworkException ex)
{
_logger.LogWarning(ex, $"处理批次 {offset}-{offset + batchSize} 时网络异常,等待重试");
await Task.Delay(5000); // 等待5秒重试
offset -= batchSize; // 重试当前批次
}
}
_logger.LogMessage($"数据同步完成,成功:{processedCount},错误:{errorCount}", "Info", "同步");
}
catch (Exception ex)
{
_logger.LogError(ex, "数据同步任务失败");
throw;
}
}
[ExecutionTimeLogger]
private async Task ProcessBatchAsync(List<DataRecord> records)
{
foreach (var record in records)
{
try
{
await ProcessSingleRecordAsync(record);
}
catch (ValidationException ex)
{
_logger.LogWarning(ex, $"记录 {record.Id} 验证失败,跳过");
}
}
}
}
⚙️ 配置详解
LogOutput 选项
File
- 仅输出到文件,适合本地开发和小型应用RabbitMQ
- 仅输出到消息队列,适合云环境和微服务FileAndQueue
- 同时输出到文件和消息队列,适合生产环境
环境特定配置
开发环境 (appsettings.Development.json)
{
"LogSettings": {
"LogLevel": "Debug",
"LogOutput": "File",
"FilePath": "logs",
"DefaultDeveloperName": "开发者",
"ProjectName": "开发环境"
}
}
测试环境 (appsettings.Test.json)
{
"LogSettings": {
"LogLevel": "Info",
"LogOutput": "FileAndQueue",
"FilePath": "/var/logs/myapp",
"DefaultDeveloperName": "测试组",
"ProjectName": "测试环境",
"RabbitMQ": {
"Host": "test-rabbitmq.company.com",
"Port": 5672,
"Username": "test_user",
"Password": "test_password",
"QueueName": "test_logs",
"Exchange": "test_exchange",
"RoutingKey": "test_logs",
"VirtualHost": "test"
}
}
}
生产环境 (appsettings.Production.json)
{
"LogSettings": {
"LogLevel": "Warning",
"LogOutput": "RabbitMQ",
"DefaultDeveloperName": "生产系统",
"ProjectName": "生产环境",
"RabbitMQ": {
"Host": "prod-rabbitmq-cluster.company.com",
"Port": 5672,
"Username": "prod_logger",
"Password": "secure_password",
"QueueName": "production_logs",
"Exchange": "production_exchange",
"RoutingKey": "prod_logs",
"VirtualHost": "production"
}
}
}
📝 日志格式
美化格式(文件和控制台)
================================================================================
🔴 [ERROR] 2025-06-25 10:19:34
👤 开发者: 张三 📦 项目: 电商系统
🏷️ 类型: 异常 🔧 状态: 未处理
💬 消息: 订单处理失败
❌ 异常: 库存不足
🔍 类型: BusinessException
📋 代码: INSUFFICIENT_STOCK
🏗️ 程序集: OrderService
📚 堆栈跟踪:
at OrderService.CheckInventory() line 45
🔧 额外信息:
ProductId: P001
RequestedQuantity: 5
AvailableStock: 2
--------------------------------------------------------------------------------
JSON格式(RabbitMQ)
{
"Message": "订单处理失败",
"StatusCode": "INSUFFICIENT_STOCK",
"ExceptionMessage": "库存不足",
"ExceptionStackTrace": "...",
"ExceptionType": "BusinessException",
"AssemblyName": "OrderService",
"TimeStamp": "2025-06-25T02:19:34.123Z",
"DeveloperName": "张三",
"ProjectName": "电商系统",
"LogLevel": "Error",
"BugStatus": "未处理",
"LogType": "异常",
"CustomProperties": {
"ProductId": "P001",
"RequestedQuantity": 5,
"AvailableStock": 2
}
}
🎯 最佳实践
1. 程序员姓名规范
// ✅ 推荐:使用真实姓名
var logger = new Logger("张三", "订单系统");
// ✅ 推荐:使用团队名称
var logger = new Logger("后端开发组", "用户服务");
// ❌ 不推荐:使用代号或昵称
var logger = new Logger("coder001", "系统");
2. 异常处理层次
public class OrderController : ControllerBase
{
private readonly Logger _logger;
[HttpPost]
public async Task<IActionResult> CreateOrder([FromBody] CreateOrderRequest request)
{
try
{
// 业务逻辑
var result = await _orderService.CreateOrderAsync(request);
return Ok(result);
}
catch (ValidationException ex)
{
// 客户端错误,记录警告级别
_logger.LogWarning(ex, "订单验证失败");
return BadRequest(ex.Message);
}
catch (BusinessException ex)
{
// 业务错误,记录错误级别
_logger.LogError(ex, "订单业务逻辑失败");
return StatusCode(422, "业务处理失败");
}
catch (Exception ex)
{
// 系统错误,记录错误级别
_logger.LogError(ex, "订单系统异常");
return StatusCode(500, "系统错误");
}
}
}
3. 性能敏感场景
public class HighPerformanceService
{
private readonly Logger _logger;
// ✅ 推荐:使用异步日志
public async Task ProcessDataAsync(string data)
{
try
{
// 业务逻辑
await ProcessBusinessLogic(data);
}
catch (Exception ex)
{
// 异步记录,不阻塞主流程
_ = _logger.LogErrorAsync(ex, "数据处理失败");
throw;
}
}
// ✅ 推荐:批量处理时只记录关键日志
public async Task BatchProcessAsync(List<string> dataList)
{
_logger.LogMessage($"开始批量处理,共 {dataList.Count} 条", "Info", "批处理");
int successCount = 0;
int errorCount = 0;
foreach (var data in dataList)
{
try
{
await ProcessBusinessLogic(data);
successCount++;
}
catch (Exception ex)
{
errorCount++;
// 只记录错误,不记录每个成功的项
if (errorCount <= 10) // 限制错误日志数量
{
_ = _logger.LogErrorAsync(ex, $"处理数据失败: {data}");
}
}
}
_logger.LogMessage($"批量处理完成,成功:{successCount},失败:{errorCount}", "Info", "批处理");
}
}
4. 多环境配置
public class ConfigurationHelper
{
public static void InitializeLogging(IConfiguration configuration)
{
var environment = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");
var logConfig = configuration.GetSection("LogSettings").Get<LogConfiguration>();
// 根据环境调整配置
switch (environment)
{
case "Development":
logConfig.LogLevel = "Debug";
logConfig.LogOutput = "File";
break;
case "Production":
logConfig.LogLevel = "Warning";
logConfig.LogOutput = "RabbitMQ";
break;
default:
logConfig.LogOutput = "FileAndQueue";
break;
}
LogStaticHelper.Initialize(logConfig);
}
}
🛠️ 故障排除
常见问题
1. RabbitMQ连接失败
// 检查连接配置
var rabbitConfig = logConfig.RabbitMQ;
Console.WriteLine($"连接地址: {rabbitConfig.Host}:{rabbitConfig.Port}");
Console.WriteLine($"虚拟主机: {rabbitConfig.VirtualHost}");
Console.WriteLine($"队列名称: {rabbitConfig.QueueName}");
解决方案:
- 确认RabbitMQ服务正在运行
- 检查网络连接和防火墙设置
- 验证用户名密码和权限
- 确认虚拟主机存在
2. 文件日志写入失败
// 检查文件路径权限
var logPath = Path.Combine(logConfig.FilePath, $"log-{DateTime.Now:yyyy-MM-dd}.txt");
Console.WriteLine($"日志文件路径: {Path.GetFullPath(logPath)}");
// 测试目录创建权限
try
{
Directory.CreateDirectory(logConfig.FilePath);
Console.WriteLine("目录创建成功");
}
catch (Exception ex)
{
Console.WriteLine($"目录创建失败: {ex.Message}");
}
解决方案:
- 确保应用程序有文件夹写入权限
- 检查磁盘空间是否充足
- 验证路径格式是否正确
3. PostSharp AOP不工作
// 检查PostSharp是否正确安装
[LogException]
public void TestMethod()
{
throw new Exception("测试异常");
}
解决方案:
- 确认已安装PostSharp NuGet包
- 检查PostSharp许可证是否有效
- 重新构建项目
- 查看编译输出是否有PostSharp相关信息
4. 性能问题
// 使用异步日志避免阻塞
_ = logger.LogErrorAsync(ex, "异步记录异常");
// 在高频场景中限制日志数量
private static int _logCount = 0;
if (Interlocked.Increment(ref _logCount) % 100 == 0)
{
logger.LogMessage($"已处理 {_logCount} 条记录", "Info", "进度");
}
调试模式
// 启用详细日志用于调试
LogStaticHelper.LogMessage("日志系统初始化完成", "Debug", "系统", "DEBUG");
LogStaticHelper.LogMessage($"当前日志级别: {logConfig.LogLevel}", "Debug", "系统", "DEBUG");
LogStaticHelper.LogMessage($"输出方式: {logConfig.LogOutput}", "Debug", "系统", "DEBUG");
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
-
net8.0
- Microsoft.Extensions.Configuration.Binder (>= 8.0.2)
- Microsoft.Extensions.Configuration.Json (>= 8.0.1)
- PostSharp (>= 2024.1.6)
- Serilog (>= 4.1.0)
- Serilog.Extensions.Logging (>= 8.0.0)
- Serilog.Sinks.Console (>= 6.0.0)
- Serilog.Sinks.File (>= 6.0.0)
- Serilog.Sinks.RabbitMQ (>= 7.0.2)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.