解决MySql布尔型新旧版本兼容问题,采用枚举来表示布尔型的数据表。由正向工程赋值
|
# 日志ILog
## 概述
`NewLife.Log.ILog` 是 NewLife.Core çš„æ ¸å¿ƒæ—¥å¿—æŽ¥å£ï¼Œæä¾›ç»Ÿä¸€çš„æ—¥å¿—记录规范。NewLife 全系列组件å‡ä½¿ç”¨è¯¥æŽ¥å£è®°å½•日志。
é€šè¿‡é™æ€ç±» `XTrace` å¯ä»¥æ–¹ä¾¿åœ°ä½¿ç”¨æ—¥å¿—功能,支æŒï¼š
- 文件日志(默认)
- æŽ§åˆ¶å°æ—¥å¿—
- 网络日志
- 自定义日志实现
**命å空间**: `NewLife.Log`
**æºç **: [NewLife.Core/Log/ILog.cs](https://github.com/NewLifeX/X/blob/master/NewLife.Core/Log/ILog.cs)
**文档**: https://newlifex.com/core/log
---
## 快速入门
### 基础用法
```csharp
using NewLife.Log;
// æ–¹å¼1:使用 XTrace 陿€ç±»ï¼ˆæŽ¨è)
XTrace.WriteLine("这是一æ¡ä¿¡æ¯");
XTrace.WriteLine("用户{0}登录", "admin");
// æ–¹å¼2:直接使用 ILog 接å£
ILog log = XTrace.Log;
log.Info("这是一æ¡ä¿¡æ¯");
log.Error("这是一æ¡é”™è¯¯");
```
### 日志级别
```csharp
XTrace.Log.Debug("调试信æ¯"); // 调试日志
XTrace.Log.Info("普通信æ¯"); // ä¿¡æ¯æ—¥å¿—
XTrace.Log.Warn("è¦å‘Šä¿¡æ¯"); // è¦å‘Šæ—¥å¿—
XTrace.Log.Error("错误信æ¯"); // 错误日志
XTrace.Log.Fatal("严é‡é”™è¯¯"); // 严é‡é”™è¯¯æ—¥å¿—
```
### 输出异常
```csharp
try
{
// 业务代ç
}
catch (Exception ex)
{
XTrace.WriteException(ex); // è¾“å‡ºå¼‚å¸¸å †æ ˆ
}
```
---
## ILog 接å£
```csharp
public interface ILog
{
/// <summary>写日志</summary>
void Write(LogLevel level, String format, params Object?[] args);
/// <summary>调试日志</summary>
void Debug(String format, params Object?[] args);
/// <summary>ä¿¡æ¯æ—¥å¿—</summary>
void Info(String format, params Object?[] args);
/// <summary>è¦å‘Šæ—¥å¿—</summary>
void Warn(String format, params Object?[] args);
/// <summary>错误日志</summary>
void Error(String format, params Object?[] args);
/// <summary>严é‡é”™è¯¯æ—¥å¿—</summary>
void Fatal(String format, params Object?[] args);
/// <summary>是å¦å¯ç”¨æ—¥å¿—。为falseæ—¶ä¸è¾“出任何日志</summary>
Boolean Enable { get; set; }
/// <summary>日志ç‰çº§ï¼Œåªè¾“出大于ç‰äºŽè¯¥çº§åˆ«çš„æ—¥å¿—,默认Info</summary>
LogLevel Level { get; set; }
}
```
### 日志级别 LogLevel
```csharp
public enum LogLevel
{
/// <summary>关闿—¥å¿—</summary>
Off = 0,
/// <summary>严é‡é”™è¯¯ã€‚导致应用程åºé€€å‡º</summary>
Fatal = 1,
/// <summary>错误。影å“功能è¿è¡Œï¼Œéœ€è¦ç«‹å³å¤„ç†</summary>
Error = 2,
/// <summary>è¦å‘Šã€‚ä¸å½±å“功能,但需è¦å…³æ³¨</summary>
Warn = 3,
/// <summary>ä¿¡æ¯ã€‚常规日志信æ¯</summary>
Info = 4,
/// <summary>调试。调试日志,生产环境应关é—</summary>
Debug = 5,
/// <summary>全部</summary>
All = 6
}
```
---
## XTrace 陿€ç±»
`XTrace` 是日志的主è¦ä½¿ç”¨å…¥å£ï¼Œæä¾›ä¾¿æ·çš„陿€æ–¹æ³•。
### 基础方法
```csharp
// è¾“å‡ºä¿¡æ¯æ—¥å¿—
XTrace.WriteLine("消æ¯");
XTrace.WriteLine("用户{0}在{1}登录", "admin", DateTime.Now);
// 输出异常
XTrace.WriteException(ex);
```
### 关键属性
```csharp
// èŽ·å–æˆ–设置日志实现
ILog log = XTrace.Log; // 默认为文件日志
XTrace.Log = new ConsoleLog(); // 切æ¢ä¸ºæŽ§åˆ¶å°æ—¥å¿—
// 是å¦è°ƒè¯•模å¼
XTrace.Debug = true; // å¼€å¯è°ƒè¯•,输出Debug级别日志
// 日志路径
XTrace.LogPath = "Logs"; // 设置日志文件夹
```
---
## 默认文件日志
NewLife 默认使用 `TextFileLog`,将日志输出到文本文件。
### 特性
- 自动按日期分割日志文件(如 `2025-01-07.log`)
- 异æ¥å†™å…¥ï¼Œä¸é˜»å¡žä¸šåŠ¡çº¿ç¨‹
- è‡ªåŠ¨å¤‡ä»½å’Œæ¸…ç†æ—§æ—¥å¿—
- 支æŒé…ç½®æ—¥å¿—è·¯å¾„ã€æœ€å¤§æ–‡ä»¶å¤§å°ç‰
### é…ç½®
在 `NewLife.config` 或 `appsettings.json` ä¸é…置:
```xml
<!-- NewLife.config -->
<Config>
<Setting>
<LogPath>Logs</LogPath> <!-- 日志路径 -->
<LogLevel>Info</LogLevel> <!-- 日志级别 -->
<LogFileFormat>{0:yyyy_MM_dd}.log</LogFileFormat> <!-- æ–‡ä»¶å‘½åæ ¼å¼ -->
</Setting>
</Config>
```
```json
// appsettings.json
{
"NewLife": {
"Setting": {
"LogPath": "Logs",
"LogLevel": "Info",
"LogFileFormat": "{0:yyyy_MM_dd}.log"
}
}
}
```
### 日志文件示例
```
2025-01-07 10:15:23.456 Info 应用程åºå¯åЍ
2025-01-07 10:15:24.123 Info 用户admin登录
2025-01-07 10:20:15.789 Warn è¿žæŽ¥æ± å·²æ»¡
2025-01-07 10:25:30.456 Error æ•°æ®åº“连接超时
System.TimeoutException: 连接超时
at MyApp.Database.Query(String sql)
at MyApp.Service.GetData()
```
---
## æŽ§åˆ¶å°æ—¥å¿—
在控制å°åº”用ä¸ï¼Œå¯ä»¥ä½¿ç”¨ `UseConsole()` 将日志输出到控制å°ã€‚
### 使用方法
```csharp
class Program
{
static void Main(String[] args)
{
// é‡å®šå‘日志到控制å°
XTrace.UseConsole();
XTrace.WriteLine("应用程åºå¯åЍ");
XTrace.Log.Error("这是一æ¡é”™è¯¯");
}
}
```
### 彩色输出
æŽ§åˆ¶å°æ—¥å¿—支æŒå½©è‰²è¾“出,ä¸åŒæ—¥å¿—级别使用ä¸åŒé¢œè‰²ï¼š
- **Debug**: ç°è‰²
- **Info**: 白色
- **Warn**: 黄色
- **Error**: 红色
- **Fatal**: 洋红色
### 多线程彩色
```csharp
XTrace.UseConsole(useColor: true); // å¯ç”¨å½©è‰²è¾“出
ThreadPool.QueueUserWorkItem(_ =>
{
XTrace.WriteLine("线程1"); // 自动使用ä¸åŒé¢œè‰²
});
ThreadPool.QueueUserWorkItem(_ =>
{
XTrace.WriteLine("线程2"); // 自动使用ä¸åŒé¢œè‰²
});
```
---
## 网络日志
将日志通过网络å‘é€åˆ°è¿œç¨‹æ—¥å¿—æœåŠ¡å™¨ã€‚
### 使用方法
```csharp
// é…置网络日志
XTrace.Log = new NetworkLog("tcp://logserver:514");
XTrace.WriteLine("è¿™æ¡æ—¥å¿—会å‘é€åˆ°è¿œç¨‹æœåС噍");
```
### 适用场景
- 集ä¸å¼æ—¥å¿—收集
- 分布å¼ç³»ç»Ÿæ—¥å¿—èšåˆ
- 容器化应用日志输出
---
## å¤åˆæ—¥å¿—
åŒæ—¶è¾“å‡ºåˆ°å¤šä¸ªç›®æ ‡ã€‚
### 使用方法
```csharp
using NewLife.Log;
var compositeLog = new CompositeLog();
compositeLog.Add(new TextFileLog()); // 文件日志
compositeLog.Add(new ConsoleLog()); // æŽ§åˆ¶å°æ—¥å¿—
compositeLog.Add(new NetworkLog("tcp://logserver:514")); // 网络日志
XTrace.Log = compositeLog;
```
---
## 自定义日志
实现 `ILog` 接å£åˆ›å»ºè‡ªå®šä¹‰æ—¥å¿—。
### 示例:数æ®åº“日志
```csharp
public class DatabaseLog : ILog
{
public Boolean Enable { get; set; } = true;
public LogLevel Level { get; set; } = LogLevel.Info;
public void Write(LogLevel level, String format, params Object?[] args)
{
if (!Enable || level > Level) return;
var message = args.Length > 0 ? String.Format(format, args) : format;
// 写入数æ®åº“
Database.Insert("Logs", new
{
Level = level.ToString(),
Message = message,
CreateTime = DateTime.Now
});
}
public void Debug(String format, params Object?[] args) => Write(LogLevel.Debug, format, args);
public void Info(String format, params Object?[] args) => Write(LogLevel.Info, format, args);
public void Warn(String format, params Object?[] args) => Write(LogLevel.Warn, format, args);
public void Error(String format, params Object?[] args) => Write(LogLevel.Error, format, args);
public void Fatal(String format, params Object?[] args) => Write(LogLevel.Fatal, format, args);
}
// 使用
XTrace.Log = new DatabaseLog();
```
---
## 使用场景
### 1. 应用程åºå¯åŠ¨æ—¥å¿—
```csharp
class Program
{
static void Main(String[] args)
{
XTrace.WriteLine("应用程åºå¯åЍ");
XTrace.WriteLine("版本:{0}", Assembly.GetExecutingAssembly().GetName().Version);
XTrace.WriteLine("è¿è¡Œæ—¶ï¼š{0}", Runtime.Version);
try
{
RunApplication();
}
catch (Exception ex)
{
XTrace.WriteException(ex);
XTrace.Log.Fatal("应用程åºå¼‚常退出");
}
}
}
```
### 2. 接å£è°ƒç”¨æ—¥å¿—
```csharp
public class UserService
{
public void Login(String username, String password)
{
XTrace.WriteLine("用户{0}å°è¯•登录", username);
if (ValidateUser(username, password))
{
XTrace.WriteLine("用户{0}登录æˆåŠŸ", username);
}
else
{
XTrace.Log.Warn("用户{0}登录失败:密ç 错误", username);
}
}
}
```
### 3. 异常处ç†
```csharp
try
{
var data = await FetchDataAsync();
ProcessData(data);
}
catch (TimeoutException ex)
{
XTrace.Log.Warn("æ•°æ®èŽ·å–超时:{0}", ex.Message);
}
catch (Exception ex)
{
XTrace.WriteException(ex);
throw;
}
```
### 4. 调试日志
```csharp
#if DEBUG
XTrace.Debug = true; // å¼€å‘环境开å¯è°ƒè¯•
#endif
XTrace.Log.Debug("å¼€å§‹å¤„ç†æ•°æ®ï¼š{0}æ¡", data.Length);
foreach (var item in data)
{
XTrace.Log.Debug("处ç†é¡¹ç›®ï¼š{0}", item.Id);
ProcessItem(item);
}
XTrace.Log.Debug("æ•°æ®å¤„ç†å®Œæˆ");
```
---
## 最佳实践
### 1. åˆç†ä½¿ç”¨æ—¥å¿—级别
```csharp
// Debug:调试信æ¯ï¼Œç”Ÿäº§çŽ¯å¢ƒåº”å…³é—
XTrace.Log.Debug("å˜é‡å€¼ï¼š{0}", value);
// Info:常规信æ¯ï¼Œè®°å½•é‡è¦æ“作
XTrace.Log.Info("用户{0}登录", username);
// Warn:è¦å‘Šä¿¡æ¯ï¼Œä¸å½±å“功能但需关注
XTrace.Log.Warn("è¿žæŽ¥æ± ä½¿ç”¨çŽ‡ï¼š{0}%", usage);
// Error:错误信æ¯ï¼Œå½±å“功能è¿è¡Œ
XTrace.Log.Error("æ•°æ®åº“连接失败:{0}", ex.Message);
// Fatal:严é‡é”™è¯¯ï¼Œå¯¼è‡´åº”用退出
XTrace.Log.Fatal("é…置文件æŸå,应用程åºé€€å‡º");
```
### 2. é¿å…日志信æ¯è¿‡å¤š
```csharp
// 䏿ލè:循环ä¸è¾“出日志
foreach (var item in items) // 100ä¸‡æ¡æ•°æ®
{
XTrace.Log.Debug("处ç†ï¼š{0}", item); // 产生100ä¸‡æ¡æ—¥å¿—ï¼
}
// 推è:汇总输出
var count = 0;
foreach (var item in items)
{
ProcessItem(item);
count++;
}
XTrace.Log.Info("处ç†å®Œæˆï¼š{0}æ¡", count);
```
### 3. 使用结构化日志
```csharp
// 推è:使用å ä½ç¬¦
XTrace.Log.Info("用户{0}从{1}登录,IP={2}", username, location, ip);
// 䏿ލè:å—符串拼接
XTrace.Log.Info("用户" + username + "从" + location + "登录,IP=" + ip);
```
### 4. 性能考虑
```csharp
// 推è:先判æ–级别
if (XTrace.Log.Enable && XTrace.Log.Level >= LogLevel.Debug)
{
var expensiveData = GetExpensiveDebugInfo(); // 昂贵æ“作
XTrace.Log.Debug("调试信æ¯ï¼š{0}", expensiveData);
}
// 䏿ލè:直接调用
XTrace.Log.Debug("调试信æ¯ï¼š{0}", GetExpensiveDebugInfo()); // å³ä½¿Debugå…³é—也会执行
```
---
## é…置管ç†
### 通过代ç é…ç½®
```csharp
// 设置日志级别
XTrace.Log.Level = LogLevel.Warn; // åªè¾“出WarnåŠä»¥ä¸Š
// 关闿—¥å¿—
XTrace.Log.Enable = false;
// 设置日志路径
XTrace.LogPath = "C:\\Logs";
```
### 通过é…置文件
```xml
<!-- NewLife.config -->
<Config>
<Setting>
<LogPath>Logs</LogPath>
<LogLevel>Info</LogLevel>
<Debug>false</Debug>
</Setting>
</Config>
```
### è¿è¡Œæ—¶ä¿®æ”¹
```csharp
// 临时开å¯è°ƒè¯•
var oldDebug = XTrace.Debug;
XTrace.Debug = true;
try
{
DebugMethod();
}
finally
{
XTrace.Debug = oldDebug; // æ¢å¤è®¾ç½®
}
```
---
## 全局异常处ç†
XTrace 自动æ•获未处ç†å¼‚常:
```csharp
static XTrace()
{
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
TaskScheduler.UnobservedTaskException += TaskScheduler_UnobservedTaskException;
}
```
当å‘生未处ç†å¼‚常时,会自动输出异常日志。
---
## 常è§é—®é¢˜
### 1. 如何关闿—¥å¿—?
```csharp
// æ–¹å¼1ï¼šå…³é—æ—¥å¿—输出
XTrace.Log.Enable = false;
// æ–¹å¼2:设置日志级别为Off
XTrace.Log.Level = LogLevel.Off;
// æ–¹å¼3:使用空日志
XTrace.Log = Logger.Null;
```
### 2. 日志文件在哪里?
é»˜è®¤åœ¨åº”ç”¨ç¨‹åºæ ¹ç›®å½•çš„ `Logs` æ–‡ä»¶å¤¹ä¸‹ï¼Œæ–‡ä»¶åæ ¼å¼ä¸º `yyyy_MM_dd.log`。
### 3. å¦‚ä½•è¾“å‡ºåˆ°å¤šä¸ªç›®æ ‡ï¼Ÿ
```csharp
var compositeLog = new CompositeLog();
compositeLog.Add(new TextFileLog());
compositeLog.Add(new ConsoleLog());
XTrace.Log = compositeLog;
```
### 4. 日志文件太大怎么办?
é…置日志备份和清ç†ç–略:
```csharp
var textLog = new TextFileLog();
textLog.MaxBytes = 10 * 1024 * 1024; // 最大10MB
textLog.Backups = 10; // ä¿ç•™10个备份
```
### 5. 如何在ASP.NET Coreä¸ä½¿ç”¨ï¼Ÿ
```csharp
// Startup.cs 或 Program.cs
public void Configure(IApplicationBuilder app)
{
// 日志已自动åˆå§‹åŒ–,直接使用
XTrace.WriteLine("应用程åºå¯åЍ");
}
```
---
## å‚考资料
- **在线文档**: https://newlifex.com/core/log
- **æºç **: https://github.com/NewLifeX/X/tree/master/NewLife.Core/Log
- **链路追踪**: [tracer-链路追踪ITracer.md](/NewLife/X/Blob/v12/Doc/tracer-链路追踪ITracer.md)
---
## 更新日志
- **2025-01**: 完善文档,补充详细示例
- **2024**: æ”¯æŒ .NET 9.0
- **2023**: 优化异æ¥å†™å…¥æ€§èƒ½
- **2022**: å¢žåŠ ç½‘ç»œæ—¥å¿—æ”¯æŒ
- **2020**: 釿ž„日志架构,统一接å£
|