Add XCode skills for entity caching, ORM, and sharding ETL
|
---
name: logging-tracing-system
description: >
在 .NET 应用ä¸è®¾è®¡æˆ–使用统一日志与链路追踪系统,涵盖 ILog 分级写入ã€XTrace 陿€é—¨é¢ã€
ITracer/ISpan è½»é‡çº§ APM 埋点ã€TraceId é€ä¼ ï¼Œä»¥åŠæ—¥å¿—实现切æ¢ï¼ˆæ–‡ä»¶/控制å°/网络/组åˆï¼‰ã€‚
适用于日志接å£è®¾è®¡ã€é“¾è·¯è¿½è¸ªé›†æˆã€è§‚测性基础设施建设与代ç 审查任务。
argument-hint: >
è¯´æ˜Žä½ çš„å¯è§‚测性需求:是å¦åªéœ€è¦æ—¥å¿—还是也需è¦è¿½è¸ªï¼›
用 XTrace 陿€é—¨é¢è¿˜æ˜¯ DI 注入 ILogï¼›TraceId 是å¦è¦è·¨æœåŠ¡ä¼ æ’ï¼›
需è¦å“ªç§æ—¥å¿—实现(文件/控制å°/网络/CompositeLog)。
---
# 日志与链路追踪系统技能
## 适用场景
- 新建 .NET 应用需è¦å¿«é€Ÿé›†æˆæ—¥å¿—,希望é¢å‘接å£è€Œéžç»‘定æŸä¸ªå…·ä½“日志框架。
- 已有 `XTrace.WriteLine` æ•£è½å„å¤„ï¼Œéœ€è¦æ¢³ç†æ—¥å¿—级别ã€åˆ‡æ¢æ—¥å¿—ç›®æ ‡ï¼ˆæ–‡ä»¶â†’æŽ§åˆ¶å°â†’网络)。
- 需è¦åœ¨ HTTP/RPC 调用链ä¸ä¼ æ’ `TraceId`,并在本地 `ISpan` ä¸è®°å½•耗时和 Tag。
- 代ç 审查:确认ä¾èµ–æ³¨å…¥ä¸æ˜¯å¦é€šè¿‡ `ILog` / `ILogFeature` æŽ¥å£æŽ¥å—æ—¥å¿—,而éžç¡¬ç¼–ç `XTrace`。
- 接入 APM å¹³å°ï¼Œéœ€è¦å®žçް `ITracer` æˆ–æ›¿æ¢ `DefaultTracer.Instance`。
## æ ¸å¿ƒåŽŸåˆ™
1. **接å£å†™æ—¥å¿—**:业务类通过 `ILog` 接å£è®°å½•æ—¥å¿—ï¼ˆæž„é€ æ³¨å…¥æˆ– `ILogFeature.Log` å±žæ€§ï¼‰ï¼›åªæœ‰åº”用入å£å’Œå·¥å…·ç±»æ‰ç›´æŽ¥ç”¨ `XTrace` 陿€é—¨é¢ã€‚
2. **`XTrace` 是全局门é¢**:`XTrace.Log` æŒæœ‰å½“å‰ `ILog` 实现;`XTrace.WriteLine` 委托给 `XTrace.Log.Info`;切æ¢å…¨å±€æ—¥å¿—实现åªéœ€æ›¿æ¢ `XTrace.Log`。
3. **日志级别控制**:通过 `ILog.Level` 过滤;`Debug` 级默认ä¸å†™æ–‡ä»¶ï¼ˆ`XTrace.Debug = true` æ‰å¯ç”¨ï¼‰ï¼›ç”Ÿäº§çŽ¯å¢ƒè‡³å°‘ä¿ç•™ `Info`。
4. **`ITracer` è½»é‡ APM**:通过 `DefaultTracer.Instance` 全局替æ¢è¿½è¸ªå™¨ï¼›æ¯ä¸ªæ“作用 `using var span = tracer.NewSpan("name", tag)` 包裹;`Span.Dispose` 自动上报。
5. **TraceId é€ä¼ **:`ISpan` 活跃期间,å‘出的 HTTP/RPC 请求自动注入 `traceparent`(W3C æ ‡å‡†ï¼‰ï¼›äº‹ä»¶æ€»çº¿ç‰ç»„ä»¶è¯»å– `DefaultTracer.Current?.TraceId` 写入消æ¯å¤´ã€‚
6. **ç»„åˆæ—¥å¿—**:用 `CompositeLog` 将多个 `ILog` 实现åˆå¹¶ä¸ºä¸€è·¯ï¼Œæ›¿æ¢ `XTrace.Log` å³å¯åŒæ—¶å†™æ–‡ä»¶å’ŒæŽ§åˆ¶å°ã€‚
## 执行æ¥éª¤
### 一ã€ç¡®å®šæ—¥å¿—ç›®æ ‡
| 场景 | 推è实现 |
|------|---------|
| 默认文件日志 | `TextFileLog`(`XTrace` 自动åˆå§‹åŒ–)|
| 控制å°åº”用调试 | `XTrace.UseConsole()` 或 `ConsoleLog` |
| 远程èšåˆ | `NetworkLog` |
| å¤šç›®æ ‡ | `CompositeLog(fileLog, consoleLog)` |
### 二ã€ä¸šåŠ¡ç±»æ³¨å…¥æ—¥å¿—
```csharp
// æ–¹å¼ 1ï¼šæž„é€ æ³¨å…¥ï¼ˆæŽ¨èï¼Œå¯æµ‹è¯•)
public class MyService(ILog log)
{
public void Process()
{
log.Info("开始处ç†");
try { /* ... */ }
catch (Exception ex) { log.Error("{0}", ex.Message); }
}
}
// æ–¹å¼ 2:ILogFeature 接å£å±žæ€§ï¼ˆNewLife ç»„ä»¶å¸¸è§æ¨¡å¼ï¼‰
public class MyComponent : ILogFeature
{
public ILog Log { get; set; } = Logger.Null; // 默认空日志,ä¸å†™ä»»ä½•内容
public void DoWork() => Log.Info("工作ä¸...");
}
```
### 三ã€åˆ‡æ¢å…¨å±€æ—¥å¿—实现
```csharp
// 在 Main / Startup ä¸ï¼Œå°½æ—©è°ƒç”¨
XTrace.UseConsole(); // 切æ¢åˆ°å½©è‰²æŽ§åˆ¶å°
// 或
XTrace.Log = new CompositeLog(
TextFileLog.Create("Logs"),
new ConsoleLog());
XTrace.Debug = true; // å¯ç”¨ Debug 级日志
```
### å››ã€é“¾è·¯è¿½è¸ªåŸ‹ç‚¹
```csharp
// 1. 设置全局追踪器(一次性,应用å¯åŠ¨æ—¶ï¼‰
DefaultTracer.Instance = new DefaultTracer
{
Period = 15, // é‡‡æ ·å‘¨æœŸï¼ˆç§’ï¼‰
MaxSamples = 1, // æ¯å‘¨æœŸæ£å¸¸æ ·æœ¬æ•°
MaxErrors = 10, // æ¯å‘¨æœŸå¼‚å¸¸æ ·æœ¬æ•°
Timeout = 3_000, // è¶…æ—¶å¼ºåˆ¶é‡‡æ ·ï¼ˆæ¯«ç§’ï¼‰
};
// 2. 埋点(æ¯ä¸ªæ“作)
var tracer = DefaultTracer.Instance;
using var span = tracer.NewSpan("db/query", $"SELECT user:{id}");
try
{
var result = await db.QueryAsync(id);
return result;
}
catch (Exception ex)
{
span?.SetError(ex, null); // æ ‡è®°å¼‚å¸¸
throw;
}
// Span.Dispose() 自动上报
```
### 五ã€TraceId è·¨å±‚ä¼ é€’
```csharp
// åœ¨å½“å‰ Span 活跃时,自动注入 HTTP 请求头 traceparent
var http = new HttpClient();
// DefaultTracer 自动为 HttpClient 注入 traceparent(若已é…置)
// 在事件总线ç‰éž HTTP 场景手动读å–当剿´»è·ƒ Span çš„ TraceId
var traceId = DefaultSpan.Current?.TraceId; // DefaultSpan.Current 是 AsyncLocal
```
### å…ã€æ—¥å¿—级别与é…ç½®
```xml
<!-- NewLife.config -->
<Setting>
<LogPath>Logs</LogPath>
<LogLevel>Info</LogLevel>
<LogFileFormat>{0:yyyy-MM-dd}.log</LogFileFormat>
</Setting>
```
日志级别顺åºï¼š`Off < Fatal < Error < Warn < Info < Debug < All`
设置 `Level = Warn` æ—¶ï¼Œåªæœ‰ `Warn`/`Error`/`Fatal` 会输出。
## é‡ç‚¹æ£€æŸ¥é¡¹
- [ ] 业务类是å¦é€šè¿‡ `ILog` / `ILogFeature` 接å£è®°å½•日志,而éžç¡¬ç¼–ç `XTrace`?
- [ ] `ILog.Enable = false` 或 `Level = Off` æ—¶ï¼Œæ˜¯å¦æœ‰ä»£ç ä»åœ¨æž„建开销大的日志å—符串(应先检查 `Enable`)?
- [ ] 追踪 `Span` 是å¦åœ¨æ‰€æœ‰ä»£ç 路径(å«å¼‚常)ä¸éƒ½è¢« `Dispose`?推è `using`。
- [ ] 异常路径是å¦è°ƒç”¨äº† `span.SetError(ex, tag)` æ ‡è®°å¤±è´¥ï¼Ÿ
- [ ] `DefaultTracer.Instance` 是å¦åœ¨åº”用å¯åŠ¨æ—¶è®¾ç½®ï¼ˆæ™šäºŽ DI 容器构建则组件追ä¸åˆ°æ—©æœŸåŸ‹ç‚¹ï¼‰ï¼Ÿ
- [ ] `CompositeLog` ä¸è‹¥æŸä¸ªå®žçŽ°æŠ›å‡ºå¼‚å¸¸ï¼Œæ˜¯å¦å½±å“å…¶ä»–ç›®æ ‡çš„å†™å…¥ï¼ˆå®žçŽ°åº”ç‹¬ç«‹ try-catch)?
## è¾“å‡ºè¦æ±‚
- **日志接å£**:`ILog` + `LogLevel` 枚举;`ILogFeature` 属性注入接å£ã€‚
- **实现文件**:`TextFileLog`(文件)ã€`ConsoleLog`(控制å°ï¼‰ã€`CompositeLog`(组åˆï¼‰ï¼Œå„自独立文件。
- **追踪接å£**:`ITracer` + `ISpanBuilder` + `ISpan`ï¼›`DefaultTracer` 作为默认实现。
- **é…ç½®**:在 `NewLife.config` / `appsettings.json` ä¸ç»Ÿä¸€ç®¡ç†æ—¥å¿—路径和级别,ä¸ç¡¬ç¼–ç 。
- **测试**:å¯é€šè¿‡æ³¨å…¥ `Logger.Null` 或 `TestLog`ï¼ˆè®°å½•æ—¥å¿—åˆ°åˆ—è¡¨ï¼‰æµ‹è¯•å„æ¨¡å—,ä¸ä¾èµ–文件 IO。
## å‚考资料
å‚考示例与模å¼è¯æ®è§ `references/newlife-log-tracer-patterns.md`。
|