Files

178 lines
5.2 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 日志服务使用指南 | Logger Service Usage Guide
## 概述 | Overview
XplorePlane 使用 Serilog 作为底层日志框架,通过 `ILoggerService` 接口提供统一的日志服务。
## 基本用法 | Basic Usage
### 方式 1:自动类型推断(推荐)| Method 1: Auto Type Inference (Recommended)
使用泛型方法 `ForModule<T>()` 自动获取类型的完整名称(命名空间 + 类名):
```csharp
public class PlcService
{
private readonly ILoggerService _logger;
public PlcService(ILoggerService logger)
{
// 自动使用 "XP.Hardware.Plc.Services.PlcService" 作为模块名
// Automatically uses "XP.Hardware.Plc.Services.PlcService" as module name
_logger = logger?.ForModule<PlcService>() ?? throw new ArgumentNullException(nameof(logger));
}
public void DoSomething()
{
_logger.Info("执行操作 | Performing operation");
}
}
```
### 方式 2:手动指定模块名 | Method 2: Manual Module Name
如果需要自定义模块名,可以使用字符串参数:
```csharp
public class PlcService
{
private readonly ILoggerService _logger;
public PlcService(ILoggerService logger)
{
// 手动指定简短的模块名
// Manually specify a short module name
_logger = logger?.ForModule("PlcService") ?? throw new ArgumentNullException(nameof(logger));
}
}
```
### 方式 3:使用 typeof 获取类型名 | Method 3: Using typeof for Type Name
在静态方法或无法使用泛型的场景:
```csharp
public class PlcService
{
private readonly ILoggerService _logger;
public PlcService(ILoggerService logger)
{
// 使用 typeof 获取类型
// Use typeof to get type
_logger = logger?.ForModule<PlcService>() ?? throw new ArgumentNullException(nameof(logger));
}
public static void StaticMethod(ILoggerService logger)
{
// 静态方法中也可以使用泛型
// Can also use generics in static methods
var log = logger.ForModule<PlcService>();
log.Info("静态方法日志 | Static method log");
}
}
```
## 日志级别 | Log Levels
```csharp
// 调试信息(开发环境)| Debug information (development environment)
_logger.Debug("调试信息:变量值={Value} | Debug info: variable value={Value}", someValue);
// 一般信息 | General information
_logger.Info("操作成功 | Operation successful");
// 警告信息 | Warning information
_logger.Warn("连接不稳定 | Connection unstable");
// 错误信息(带异常)| Error information (with exception)
_logger.Error(ex, "操作失败:{Message} | Operation failed: {Message}", ex.Message);
// 致命错误 | Fatal error
_logger.Fatal(ex, "系统崩溃 | System crash");
```
## 日志输出格式 | Log Output Format
使用 `ForModule<T>()` 后,日志会自动包含完整的类型信息:
```
2026-03-12 10:30:15.123 [INF] [XP.Hardware.Plc.Services.PlcService] 正在初始化 PLC 连接... | Initializing PLC connection...
2026-03-12 10:30:16.456 [INF] [XP.Hardware.Plc.Services.PlcService] PLC 连接成功 | PLC connection successful
```
## 最佳实践 | Best Practices
### 1. 在构造函数中初始化日志器 | Initialize Logger in Constructor
```csharp
public class MyService
{
private readonly ILoggerService _logger;
public MyService(ILoggerService logger)
{
_logger = logger?.ForModule<MyService>() ?? throw new ArgumentNullException(nameof(logger));
}
}
```
### 2. 使用结构化日志 | Use Structured Logging
```csharp
// 好的做法:使用占位符 | Good: use placeholders
_logger.Info("用户 {UserId} 执行了操作 {Action} | User {UserId} performed action {Action}", userId, action);
// 不好的做法:字符串拼接 | Bad: string concatenation
_logger.Info($"用户 {userId} 执行了操作 {action}");
```
### 3. 异常日志包含上下文 | Exception Logs Include Context
```csharp
try
{
await _plcClient.ConnectAsync(config);
}
catch (PlcException ex)
{
_logger.Error(ex, "PLC 连接失败:地址={Address}, 端口={Port} | PLC connection failed: address={Address}, port={Port}",
config.Address, config.Port);
throw;
}
```
## 对比:三种方式的输出 | Comparison: Output of Three Methods
```csharp
// 方式 1ForModule<T>() - 完整类型名
// Method 1: ForModule<T>() - Full type name
_logger = logger.ForModule<PlcService>();
// 输出 | Output: [XP.Hardware.Plc.Services.PlcService]
// 方式 2ForModule("PlcService") - 自定义名称
// Method 2: ForModule("PlcService") - Custom name
_logger = logger.ForModule("PlcService");
// 输出 | Output: [PlcService]
// 方式 3:不调用 ForModule - 无模块标记
// Method 3: Don't call ForModule - No module tag
_logger = logger;
// 输出 | Output: [] (空标记 | empty tag)
```
## 配置 | Configuration
日志配置在 `App.config` 中设置,通过 `SerilogConfig` 加载:
```xml
<appSettings>
<add key="Serilog:LogPath" value="C:\Logs\XplorePlane" />
<add key="Serilog:MinimumLevel" value="Information" />
<add key="Serilog:EnableConsole" value="true" />
<add key="Serilog:RollingInterval" value="Day" />
<add key="Serilog:FileSizeLimitMB" value="100" />
<add key="Serilog:RetainedFileCountLimit" value="30" />
</appSettings>
```