@elf-express/admin-net-mcp 1.0.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +83 -88
- package/knowledge/Furion_Teaching_Manual/04-1-/351/205/215/347/275/256.md +442 -0
- package/knowledge/Furion_Teaching_Manual/04-2-/351/201/270/351/240/205.md +363 -0
- package/knowledge/Furion_Teaching_Manual/05-1-/345/213/225/346/205/213WebAPI.md +825 -0
- package/knowledge/Furion_Teaching_Manual/05-2-HttpContext.md +217 -0
- package/knowledge/Furion_Teaching_Manual/05-3-/347/257/251/351/201/270/345/231/250/346/224/224/346/210/252/345/231/250AOP.md +581 -0
- package/knowledge/Furion_Teaching_Manual/05-4-/350/253/213/346/261/202/347/250/275/346/240/270/346/227/245/350/252/214.md +129 -0
- package/knowledge/Furion_Teaching_Manual/05-5-/344/270/255/344/273/213/350/273/237/351/253/224Middleware.md +328 -0
- package/knowledge/Furion_Teaching_Manual/05-6-Vue-React-Angular/344/273/213/351/235/242/344/273/243/347/220/206.md +317 -0
- package/knowledge/Furion_Teaching_Manual/06-1/350/246/217/347/257/204/345/214/226/346/216/245/345/217/243.md +1458 -0
- package/knowledge/Furion_Teaching_Manual/06-2/347/254/254/344/270/211/346/226/271API_Scalar.md +91 -0
- package/knowledge/Furion_Teaching_Manual/07-/345/217/213/345/245/275/344/276/213/345/244/226/350/231/225/347/220/206.md +511 -0
- package/knowledge/Furion_Teaching_Manual/08-1-/350/263/207/346/226/231/351/251/227/350/255/211/345/237/272/347/244/216/344/275/277/347/224/250.md +587 -0
- package/knowledge/Furion_Teaching_Manual/10-1-SqlSugar/346/225/264/345/220/210.md +336 -0
- package/knowledge/Furion_Teaching_Manual/11-SaaS /345/244/232/347/247/237/346/210/266/347/255/206/350/250/230.md" +271 -0
- package/knowledge/Furion_Teaching_Manual/12-furion-dependency-injection.md +408 -0
- package/knowledge/Furion_Teaching_Manual/13-/347/211/251/344/273/266/350/263/207/346/226/231/346/230/240/345/260/204/357/274/210Mapster/357/274/211.md +162 -0
- package/knowledge/Furion_Teaching_Manual/14-/345/210/206/345/270/203/345/274/217/347/274/223/345/255/230.md +311 -0
- package/knowledge/Furion_Teaching_Manual/15-/345/256/211/345/205/250/351/211/264/346/235/203.md +832 -0
- package/knowledge/Furion_Teaching_Manual/17-/346/252/242/350/246/226/347/257/204/346/234/254/345/274/225/346/223/216.md +327 -0
- package/knowledge/Furion_Teaching_Manual/18-/346/227/245/350/252/214/350/250/230/351/214/204.md +639 -0
- package/knowledge/Furion_Teaching_Manual/19-1-HTTP/351/201/240/347/253/257/350/253/213/346/261/202/345/237/272/347/244/216/344/275/277/347/224/250.md +621 -0
- package/knowledge/Furion_Teaching_Manual/19-2-HTTP/351/201/240/347/253/257/350/253/213/346/261/202/351/200/262/351/232/216/346/214/207/345/215/227.md +928 -0
- package/knowledge/Furion_Teaching_Manual/19-3-HTTP/351/201/240/347/253/257/350/253/213/346/261/202/345/270/270/350/246/213/345/225/217/351/241/214.md +362 -0
- package/knowledge/Furion_Teaching_Manual/20-/350/263/207/346/226/231/345/212/240/350/247/243/345/257/206.md +286 -0
- package/knowledge/Furion_Teaching_Manual/20-/351/231/204/351/214/204-KSort/350/263/207/346/226/231/347/260/275/345/220/215/345/256/214/346/225/264/345/216/237/345/247/213/347/242/274.md +305 -0
- package/knowledge/Furion_Teaching_Manual/21-/345/205/250/347/220/203/345/214/226/345/222/214/346/234/254/345/234/260/345/214/226.md +342 -0
- package/knowledge/Furion_Teaching_Manual/22-/344/272/213/344/273/266/345/214/257/346/265/201/346/216/222EventBus.md +448 -0
- package/knowledge/Furion_Teaching_Manual/23-JSON/345/272/217/345/210/227/345/214/226.md +340 -0
- package/knowledge/Furion_Teaching_Manual/24-/345/215/263/346/231/202/351/200/232/350/250/212SignalR.md +247 -0
- package/knowledge/Furion_Teaching_Manual/25-/350/274/224/345/212/251/350/247/222/350/211/262/346/234/215/345/213/231WorkerService.md +295 -0
- package/knowledge/Furion_Teaching_Manual/26-1-/346/216/222/347/250/213/344/275/234/346/245/255/345/256/232/346/231/202/344/273/273/345/213/231.md +631 -0
- package/knowledge/Furion_Teaching_Manual/26-2-Cron/350/241/250/351/201/224/345/274/217.md +203 -0
- package/knowledge/Furion_Teaching_Manual/26-3-/344/273/273/345/213/231/344/275/207/345/210/227TaskQueue.md +215 -0
- package/knowledge/Furion_Teaching_Manual/27-/345/210/206/346/225/243/345/274/217ID/347/224/237/346/210/220.md +86 -0
- package/knowledge/Furion_Teaching_Manual/28-/346/250/241/347/265/204/345/214/226/351/226/213/347/231/274.md +68 -0
- package/knowledge/Furion_Teaching_Manual/29-/346/265/201/350/256/212/347/211/251/344/273/266Clay.md +313 -0
- package/knowledge/Furion_Teaching_Manual/30-/350/204/253/346/225/217/350/231/225/347/220/206/357/274/210Sensitive Detection).md" +168 -0
- package/knowledge/Furion_Teaching_Manual/32-/346/234/203/350/251/261/345/222/214/347/213/200/346/205/213/347/256/241/347/220/206.md +147 -0
- package/knowledge/Furion_Teaching_Manual/33-IPC/347/250/213/345/272/217/351/200/232/350/250/212.md +98 -0
- package/knowledge/Furion_Teaching_Manual/34-2-Docker/351/203/250/347/275/262.md +313 -0
- package/knowledge/Furion_Teaching_Manual/34-3-Nginx/351/203/250/347/275/262.md +157 -0
- package/knowledge/Furion_Teaching_Manual/34-8-WindowsService/351/203/250/347/275/262.md +112 -0
- package/knowledge/Furion_Teaching_Manual/35-1-Docker/347/222/260/345/242/203/346/214/201/347/272/214/351/203/250/347/275/262Jenkins.md +169 -0
- package/knowledge/Furion_Teaching_Manual/36-1-/345/226/256/345/205/203/346/270/254/350/251/246/346/225/264/345/220/210/346/270/254/350/251/246.md +275 -0
- package/knowledge/Furion_Teaching_Manual/36-3-/345/237/272/346/272/226/346/270/254/350/251/246Benchmarking.md +80 -0
- package/knowledge/attributes.md +153 -0
- package/knowledge/config.md +147 -0
- package/knowledge/entity.md +115 -0
- package/knowledge/event.md +124 -0
- package/knowledge/plugin.md +136 -0
- package/knowledge/service.md +146 -0
- package/knowledge/sqlsugar.md +172 -0
- package/knowledge/vue-typescript.md +338 -0
- package/package.json +3 -2
package/knowledge/Furion_Teaching_Manual/18-/346/227/245/350/252/214/350/250/230/351/214/204.md
ADDED
|
@@ -0,0 +1,639 @@
|
|
|
1
|
+
# 18. 日誌記錄
|
|
2
|
+
|
|
3
|
+
## 18.1 關於日誌
|
|
4
|
+
|
|
5
|
+
- **系統日誌**:記錄系統中硬體、軟體和系統問題的資訊,可監視系統中發生的事件
|
|
6
|
+
- **程式日誌**:程式執行中產生的日誌,包括請求日誌、例外日誌、稽核日誌、行為日誌等
|
|
7
|
+
|
|
8
|
+
## 18.2 日誌作用
|
|
9
|
+
|
|
10
|
+
- **偵錯**:查看堆疊資訊方便知道當前程式的執行狀態
|
|
11
|
+
- **錯誤定位**:快速定位錯誤位置,提出解決方案
|
|
12
|
+
- **資料分析**:日誌中蘊含大量的使用者資料,對公司策略有指引作用
|
|
13
|
+
|
|
14
|
+
## 18.3 日誌級別
|
|
15
|
+
|
|
16
|
+
| 級別 | 值 | 方法 | 描述 |
|
|
17
|
+
|------|---|------|------|
|
|
18
|
+
| Trace | 0 | `LogTrace` | 最詳細的訊息,預設停用 |
|
|
19
|
+
| Debug | 1 | `LogDebug` | 用於偵錯和開發 |
|
|
20
|
+
| Information | 2 | `LogInformation` | 追蹤應用的常規流 |
|
|
21
|
+
| Warning | 3 | `LogWarning` | 異常事件或意外事件 |
|
|
22
|
+
| Error | 4 | `LogError` | 無法處理的錯誤和例外 |
|
|
23
|
+
| Critical | 5 | `LogCritical` | 需要立即關注的失敗 |
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## 18.4 如何使用
|
|
28
|
+
|
|
29
|
+
### 18.4.1 ILogger\<T\> 泛型方式
|
|
30
|
+
|
|
31
|
+
```csharp
|
|
32
|
+
public class PrivacyModel : PageModel
|
|
33
|
+
{
|
|
34
|
+
private readonly ILogger<PrivacyModel> _logger;
|
|
35
|
+
|
|
36
|
+
public PrivacyModel(ILogger<PrivacyModel> logger)
|
|
37
|
+
{
|
|
38
|
+
_logger = logger;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
public void OnGet()
|
|
42
|
+
{
|
|
43
|
+
_logger.LogInformation("GET Pages.PrivacyModel called.");
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### 18.4.2 ILoggerFactory 工廠方式
|
|
49
|
+
|
|
50
|
+
```csharp
|
|
51
|
+
public class ContactModel : PageModel
|
|
52
|
+
{
|
|
53
|
+
private readonly ILogger _logger;
|
|
54
|
+
|
|
55
|
+
public ContactModel(ILoggerFactory logger)
|
|
56
|
+
{
|
|
57
|
+
_logger = logger.CreateLogger("MyCategory");
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### 18.4.3 Log 靜態類別方式(Furion 4.2.1+)
|
|
63
|
+
|
|
64
|
+
```csharp
|
|
65
|
+
var logger = Log.CreateLogger("日誌名稱");
|
|
66
|
+
|
|
67
|
+
Log.Information("Information");
|
|
68
|
+
Log.Warning("Warning");
|
|
69
|
+
Log.Error("Error");
|
|
70
|
+
Log.Debug("Debug");
|
|
71
|
+
Log.Trace("Trace");
|
|
72
|
+
Log.Critical("Critical");
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### 18.4.4 懶人模式 😁
|
|
76
|
+
|
|
77
|
+
```csharp
|
|
78
|
+
"簡單日誌".LogInformation();
|
|
79
|
+
"百小僧 新增了一條記錄".LogInformation<HomeController>();
|
|
80
|
+
"程式出現例外啦".LogError<HomeController>();
|
|
81
|
+
"這是自訂類別日誌".SetCategory<HomeController>().LogInformation();
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
86
|
+
## 18.5 輸出到主控台
|
|
87
|
+
|
|
88
|
+
### 18.5.1 日誌過濾/篩選
|
|
89
|
+
|
|
90
|
+
```csharp
|
|
91
|
+
services.AddConsoleFormatter(options =>
|
|
92
|
+
{
|
|
93
|
+
options.WriteFilter = (logMsg) =>
|
|
94
|
+
{
|
|
95
|
+
return logMsg.LogLevel == LogLevel.Information;
|
|
96
|
+
};
|
|
97
|
+
});
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### 18.5.2 日誌標準化(美化)範本(Furion 4.5.0+)
|
|
101
|
+
|
|
102
|
+
```csharp
|
|
103
|
+
services.AddConsoleFormatter();
|
|
104
|
+
// 或在 .NET6 中:builder.Logging.AddConsoleFormatter();
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### 18.5.3 自訂日誌範本
|
|
108
|
+
|
|
109
|
+
```csharp
|
|
110
|
+
services.AddConsoleFormatter(options =>
|
|
111
|
+
{
|
|
112
|
+
options.MessageFormat = (logMsg) =>
|
|
113
|
+
{
|
|
114
|
+
var sb = new StringBuilder();
|
|
115
|
+
sb.Append(DateTime.Now.ToString("o"));
|
|
116
|
+
return sb.ToString();
|
|
117
|
+
};
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
// 輸出為 JSON 格式(Furion 4.5.2+)
|
|
121
|
+
services.AddConsoleFormatter(options =>
|
|
122
|
+
{
|
|
123
|
+
options.MessageFormat = LoggerFormatter.Json;
|
|
124
|
+
// Furion 4.8.0+ 新增 JSON 美化輸出
|
|
125
|
+
options.MessageFormat = LoggerFormatter.JsonIndented;
|
|
126
|
+
});
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### 18.5.4 自訂日誌輸出時間格式(Furion 4.5.1+)
|
|
130
|
+
|
|
131
|
+
```csharp
|
|
132
|
+
services.AddConsoleFormatter(options =>
|
|
133
|
+
{
|
|
134
|
+
options.DateFormat = "yyyy-MM-dd HH:mm:ss.fffffff zzz dddd";
|
|
135
|
+
});
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
### 18.5.5 自訂日誌輸出程式(Furion 4.5.2+)
|
|
139
|
+
|
|
140
|
+
```csharp
|
|
141
|
+
services.AddConsoleFormatter(options =>
|
|
142
|
+
{
|
|
143
|
+
options.WriteHandler = (logMsg, scopeProvider, writer, fmtMsg, opt) =>
|
|
144
|
+
{
|
|
145
|
+
writer.WriteLine(fmtMsg);
|
|
146
|
+
};
|
|
147
|
+
});
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### 18.5.6 輸出日誌 TraceId(Furion 4.8.1.3+)
|
|
151
|
+
|
|
152
|
+
```csharp
|
|
153
|
+
services.AddConsoleFormatter(options =>
|
|
154
|
+
{
|
|
155
|
+
options.WithTraceId = true;
|
|
156
|
+
});
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### 18.5.7 輸出日誌程式集/型別/方法(Furion 4.8.7.16+)
|
|
160
|
+
|
|
161
|
+
```csharp
|
|
162
|
+
services.AddConsoleFormatter(options =>
|
|
163
|
+
{
|
|
164
|
+
options.WithStackFrame = true;
|
|
165
|
+
});
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
### 18.5.8 日誌訊息額外處理(Furion 4.9.2.32+)
|
|
169
|
+
|
|
170
|
+
```csharp
|
|
171
|
+
services.AddConsoleFormatter(options =>
|
|
172
|
+
{
|
|
173
|
+
options.MessageProcess = (originalMessage) =>
|
|
174
|
+
{
|
|
175
|
+
return 脫敏處理(originalMessage);
|
|
176
|
+
};
|
|
177
|
+
});
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
---
|
|
181
|
+
|
|
182
|
+
## 18.6 輸出到檔案
|
|
183
|
+
|
|
184
|
+
### 18.6.1 基礎使用
|
|
185
|
+
|
|
186
|
+
```csharp
|
|
187
|
+
services.AddFileLogging("application.log");
|
|
188
|
+
services.AddFileLogging("logs/application.log");
|
|
189
|
+
services.AddFileLogging("application.log", true); // true 為追加,false 為覆蓋
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
### 18.6.2 從設定檔讀取設定
|
|
193
|
+
|
|
194
|
+
> ⚠️ 只有不在 `.AddFile` 第一個參數設定檔案名稱才會自動載入設定。
|
|
195
|
+
|
|
196
|
+
```json
|
|
197
|
+
{
|
|
198
|
+
"Logging": {
|
|
199
|
+
"File": {
|
|
200
|
+
"FileName": "application.log",
|
|
201
|
+
"Append": true,
|
|
202
|
+
"MinimumLevel": "Information",
|
|
203
|
+
"FileSizeLimitBytes": 0,
|
|
204
|
+
"MaxRollingFiles": 0
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
```csharp
|
|
211
|
+
services.AddFileLogging(); // 預設讀取 Logging:File 節點
|
|
212
|
+
|
|
213
|
+
services.AddFileLogging(() => "MyLogger"); // 自訂設定節點
|
|
214
|
+
|
|
215
|
+
services.AddFileLogging(options =>
|
|
216
|
+
{
|
|
217
|
+
options.MinimumLevel = LogLevel.Warning;
|
|
218
|
+
});
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
### 18.6.3 自訂日誌檔案名稱規則
|
|
222
|
+
|
|
223
|
+
```csharp
|
|
224
|
+
// 每天建立一個日誌檔案
|
|
225
|
+
services.AddFileLogging("application-{0:yyyy}-{0:MM}-{0:dd}.log", options =>
|
|
226
|
+
{
|
|
227
|
+
options.FileNameRule = fileName => string.Format(fileName, DateTime.UtcNow);
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
// 批次設定多個(依級別分檔)
|
|
231
|
+
Array.ForEach(new[] { LogLevel.Information, LogLevel.Warning, LogLevel.Error }, logLevel =>
|
|
232
|
+
{
|
|
233
|
+
services.AddFileLogging("application-{1}-{0:yyyy}-{0:MM}-{0:dd}.log", options =>
|
|
234
|
+
{
|
|
235
|
+
options.FileNameRule = fileName => string.Format(fileName, DateTime.UtcNow, logLevel.ToString());
|
|
236
|
+
options.WriteFilter = logMsg => logMsg.LogLevel == logLevel;
|
|
237
|
+
});
|
|
238
|
+
});
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
### 18.6.4 日誌過濾器/篩選器
|
|
242
|
+
|
|
243
|
+
```csharp
|
|
244
|
+
services.AddFileLogging("information.log", options =>
|
|
245
|
+
{
|
|
246
|
+
options.WriteFilter = (logMsg) => logMsg.LogLevel == LogLevel.Information;
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
services.AddFileLogging("error.log", options =>
|
|
250
|
+
{
|
|
251
|
+
options.WriteFilter = (logMsg) => logMsg.LogLevel == LogLevel.Error;
|
|
252
|
+
});
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
### 18.6.5 自訂日誌範本
|
|
256
|
+
|
|
257
|
+
```csharp
|
|
258
|
+
services.AddFileLogging("mytemplate.log", options =>
|
|
259
|
+
{
|
|
260
|
+
options.MessageFormat = (logMsg) =>
|
|
261
|
+
{
|
|
262
|
+
var sb = new StringBuilder();
|
|
263
|
+
sb.Append(DateTime.Now.ToString("o"));
|
|
264
|
+
return sb.ToString();
|
|
265
|
+
};
|
|
266
|
+
});
|
|
267
|
+
|
|
268
|
+
// JSON 格式(Furion 4.5.2+)
|
|
269
|
+
services.AddFileLogging("mytemplate.log", options =>
|
|
270
|
+
{
|
|
271
|
+
options.MessageFormat = LoggerFormatter.Json;
|
|
272
|
+
});
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
### 18.6.6 日誌寫入失敗處理
|
|
276
|
+
|
|
277
|
+
```csharp
|
|
278
|
+
services.AddFileLogging("template-obj.log", options =>
|
|
279
|
+
{
|
|
280
|
+
options.HandleWriteError = (writeError) =>
|
|
281
|
+
{
|
|
282
|
+
// 啟用備用日誌檔案(推薦)
|
|
283
|
+
writeError.UseRollbackFileName(
|
|
284
|
+
Path.GetFileNameWithoutExtension(writeError.CurrentFileName)
|
|
285
|
+
+ "-oops" + Path.GetExtension(writeError.CurrentFileName));
|
|
286
|
+
};
|
|
287
|
+
});
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
---
|
|
291
|
+
|
|
292
|
+
## 18.7 輸出到資料庫/其他儲存媒體
|
|
293
|
+
|
|
294
|
+
### 建立資料庫日誌寫入器
|
|
295
|
+
|
|
296
|
+
```csharp
|
|
297
|
+
using Furion.Logging;
|
|
298
|
+
|
|
299
|
+
namespace YourProject.Core;
|
|
300
|
+
|
|
301
|
+
public class DatabaseLoggingWriter : IDatabaseLoggingWriter
|
|
302
|
+
{
|
|
303
|
+
public DatabaseLoggingWriter() { } // 支援建構函式注入
|
|
304
|
+
|
|
305
|
+
public Task WriteAsync(LogMessage logMsg, bool flush)
|
|
306
|
+
{
|
|
307
|
+
// 這裡寫你任何插入資料庫的操作,無需 try catch
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
> ⚠️ 在 Furion 4.8.5.4+ 版本之後,如果注入了 `ILogger<>` 實例,將強制實例化為 `EmptyLogger` 物件,避免死迴圈。
|
|
313
|
+
|
|
314
|
+
### 18.7.1 基礎使用
|
|
315
|
+
|
|
316
|
+
```csharp
|
|
317
|
+
services.AddDatabaseLogging<DatabaseLoggingWriter>(options => {});
|
|
318
|
+
|
|
319
|
+
services.AddDatabaseLogging<DatabaseLoggingWriter>(options =>
|
|
320
|
+
{
|
|
321
|
+
options.MinimumLevel = LogLevel.Warning;
|
|
322
|
+
});
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
### 18.7.2 從設定檔中讀取
|
|
326
|
+
|
|
327
|
+
```json
|
|
328
|
+
{
|
|
329
|
+
"Logging": {
|
|
330
|
+
"Database": {
|
|
331
|
+
"MinimumLevel": "Information"
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
```csharp
|
|
338
|
+
services.AddDatabaseLogging<DatabaseLoggingWriter>(); // 預設讀取 Logging:Database
|
|
339
|
+
services.AddDatabaseLogging<DatabaseLoggingWriter>("MyLogger"); // 自訂設定節點
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
### 18.7.3~18.7.7 進階設定
|
|
343
|
+
|
|
344
|
+
日誌過濾、自訂範本、寫入失敗處理、TraceId、WithStackFrame 等設定方式與檔案日誌相同,將 `AddFileLogging` 替換為 `AddDatabaseLogging<T>` 即可。
|
|
345
|
+
|
|
346
|
+
### 18.7.8 關於高頻寫入儲存媒體
|
|
347
|
+
|
|
348
|
+
```csharp
|
|
349
|
+
public class DatabaseLoggingWriter : IDatabaseLoggingWriter, IDisposable
|
|
350
|
+
{
|
|
351
|
+
private readonly IServiceScope _serviceScope;
|
|
352
|
+
private readonly IRepository<LogTable> _logRepository;
|
|
353
|
+
|
|
354
|
+
public DatabaseLoggingWriter(IServiceScopeFactory scopeFactory)
|
|
355
|
+
{
|
|
356
|
+
_serviceScope = scopeFactory.CreateScope();
|
|
357
|
+
_logRepository = _serviceScope.ServiceProvider.GetRequiredService<IRepository<LogTable>>();
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
public Task WriteAsync(LogMessage logMsg, bool flush)
|
|
361
|
+
{
|
|
362
|
+
_logRepository.Insert(/* ... */);
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
public void Dispose() => _serviceScope.Dispose();
|
|
366
|
+
}
|
|
367
|
+
```
|
|
368
|
+
|
|
369
|
+
### 18.7.9 關於資料庫日誌循環輸出
|
|
370
|
+
|
|
371
|
+
ORM 本身操作資料庫時自帶日誌輸出會導致 `IDatabaseLoggingWriter` 的 `Write` 死迴圈。解決方式:建立新的資料庫操作實例並關閉日誌,或更新到 Furion 4.7.0+。如不存在該問題可關閉偵測:
|
|
372
|
+
|
|
373
|
+
```csharp
|
|
374
|
+
services.AddDatabaseLogging<DatabaseLoggingWriter>(options =>
|
|
375
|
+
{
|
|
376
|
+
options.IgnoreReferenceLoop = false;
|
|
377
|
+
});
|
|
378
|
+
```
|
|
379
|
+
|
|
380
|
+
---
|
|
381
|
+
|
|
382
|
+
## 18.8 新增日誌提供器方式
|
|
383
|
+
|
|
384
|
+
```csharp
|
|
385
|
+
// ILoggingBuilder 方式
|
|
386
|
+
services.AddLogging(builder =>
|
|
387
|
+
{
|
|
388
|
+
builder.AddFile("application.log");
|
|
389
|
+
builder.AddDatabase<DatabaseLoggingWriter>();
|
|
390
|
+
});
|
|
391
|
+
|
|
392
|
+
// LoggerFactory 方式(執行時動態新增,需自行釋放)
|
|
393
|
+
var loggerFactory = LoggerFactory.Create(builder => builder.AddFile("application.log"));
|
|
394
|
+
var logger = loggerFactory.CreateLogger("MyCategory");
|
|
395
|
+
```
|
|
396
|
+
|
|
397
|
+
---
|
|
398
|
+
|
|
399
|
+
## 18.10 Debug 與 Trace 日誌預設不輸出問題
|
|
400
|
+
|
|
401
|
+
預設 `LogLevel.Default` 為 `Information`,低於此級別的 Debug 和 Trace 不會輸出。在 `appsettings.json` 中修改:
|
|
402
|
+
|
|
403
|
+
```json
|
|
404
|
+
{
|
|
405
|
+
"Logging": {
|
|
406
|
+
"LogLevel": {
|
|
407
|
+
"Default": "Trace",
|
|
408
|
+
"System.Logging.StringLogging": "Trace"
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
```
|
|
413
|
+
|
|
414
|
+
---
|
|
415
|
+
|
|
416
|
+
## 18.11 [LoggingMonitor] 監聽日誌
|
|
417
|
+
|
|
418
|
+
> ⚠️ **生產環境**應關閉 LoggingMonitor 功能,全域啟用對效能有一定影響。
|
|
419
|
+
|
|
420
|
+
### 18.11.1 特性設定
|
|
421
|
+
|
|
422
|
+
```csharp
|
|
423
|
+
[LoggingMonitor]
|
|
424
|
+
public PersonDto GetPerson(int id) => new PersonDto { Id = id };
|
|
425
|
+
```
|
|
426
|
+
|
|
427
|
+
`[LoggingMonitor]` 支援設定:`Title`、`WithReturnValue`、`ReturnValueThreshold`、`JsonBehavior`、`JsonIndented`、`LongTypeConverter`。
|
|
428
|
+
|
|
429
|
+
### 18.11.2 全域設定
|
|
430
|
+
|
|
431
|
+
```csharp
|
|
432
|
+
services.AddMonitorLogging(); // 預設讀取 Logging:Monitor 下設定
|
|
433
|
+
```
|
|
434
|
+
|
|
435
|
+
```json
|
|
436
|
+
{
|
|
437
|
+
"Logging": {
|
|
438
|
+
"Monitor": {
|
|
439
|
+
"GlobalEnabled": false,
|
|
440
|
+
"IncludeOfMethods": [],
|
|
441
|
+
"ExcludeOfMethods": [],
|
|
442
|
+
"LogLevel": "Information",
|
|
443
|
+
"BahLogLevel": "Information",
|
|
444
|
+
"WithReturnValue": true,
|
|
445
|
+
"ReturnValueThreshold": 0,
|
|
446
|
+
"JsonBehavior": "None",
|
|
447
|
+
"JsonIndented": false,
|
|
448
|
+
"LongTypeConverter": false,
|
|
449
|
+
"ContractResolver": "CamelCase",
|
|
450
|
+
"MethodsSettings": [
|
|
451
|
+
{
|
|
452
|
+
"FullName": "Furion.Application.TestLoggerServices.MethodName",
|
|
453
|
+
"WithReturnValue": true,
|
|
454
|
+
"ReturnValueThreshold": 0,
|
|
455
|
+
"JsonBehavior": "None",
|
|
456
|
+
"JsonIndented": false,
|
|
457
|
+
"ContractResolver": "CamelCase"
|
|
458
|
+
}
|
|
459
|
+
]
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
```
|
|
464
|
+
|
|
465
|
+
> `IncludeOfMethods` 和 `ExcludeOfMethods` 格式為:`類完全限定名.方法名`。個別不需要監視的介面貼 `[SuppressMonitor]` 特性即可。
|
|
466
|
+
|
|
467
|
+
### 18.11.3 更多設定(Furion 4.3.9+)
|
|
468
|
+
|
|
469
|
+
```csharp
|
|
470
|
+
services.AddMonitorLogging(options =>
|
|
471
|
+
{
|
|
472
|
+
options.ConfigureLogger((logger, logContext, context) =>
|
|
473
|
+
{
|
|
474
|
+
var httpContext = context.HttpContext;
|
|
475
|
+
logContext.Set("extra", "其他資料");
|
|
476
|
+
});
|
|
477
|
+
});
|
|
478
|
+
```
|
|
479
|
+
|
|
480
|
+
### 18.11.4 JSON 格式(Furion 4.5.2+)
|
|
481
|
+
|
|
482
|
+
```csharp
|
|
483
|
+
// 全域
|
|
484
|
+
services.AddMonitorLogging(options =>
|
|
485
|
+
{
|
|
486
|
+
options.JsonBehavior = JsonBehavior.OnlyJson;
|
|
487
|
+
options.JsonIndented = true;
|
|
488
|
+
});
|
|
489
|
+
|
|
490
|
+
// 局部
|
|
491
|
+
[LoggingMonitor(JsonBehavior = JsonBehavior.OnlyJson, JsonIndented = true)]
|
|
492
|
+
```
|
|
493
|
+
|
|
494
|
+
在 `IDatabaseLoggingWriter` 中讀取 JSON:
|
|
495
|
+
|
|
496
|
+
```csharp
|
|
497
|
+
public Task WriteAsync(LogMessage logMsg, bool flush)
|
|
498
|
+
{
|
|
499
|
+
if (logMsg.LogName == "System.Logging.LoggingMonitor")
|
|
500
|
+
{
|
|
501
|
+
var jsonString = logMsg.Context.Get("loggingMonitor");
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
```
|
|
505
|
+
|
|
506
|
+
### 18.11.5 全域過濾 WriteFilter(Furion 4.5.9+)
|
|
507
|
+
|
|
508
|
+
```csharp
|
|
509
|
+
services.AddMonitorLogging(options =>
|
|
510
|
+
{
|
|
511
|
+
options.WriteFilter = (context) =>
|
|
512
|
+
{
|
|
513
|
+
var descriptor = context.ActionDescriptor as ControllerActionDescriptor;
|
|
514
|
+
return true; // 需要攔截回傳 false
|
|
515
|
+
};
|
|
516
|
+
});
|
|
517
|
+
```
|
|
518
|
+
|
|
519
|
+
### 18.11.6 忽略屬性名或屬性型別(Furion 4.6.1+)
|
|
520
|
+
|
|
521
|
+
```csharp
|
|
522
|
+
// 局部
|
|
523
|
+
[LoggingMonitor(JsonBehavior = JsonBehavior.OnlyJson,
|
|
524
|
+
IgnorePropertyNames = new[] { "Bytes" },
|
|
525
|
+
IgnorePropertyTypes = new[] { typeof(byte[]) })]
|
|
526
|
+
|
|
527
|
+
// 全域
|
|
528
|
+
services.AddMonitorLogging(options =>
|
|
529
|
+
{
|
|
530
|
+
options.IgnorePropertyNames = new[] { "Byte" };
|
|
531
|
+
options.IgnorePropertyTypes = new[] { typeof(byte[]) };
|
|
532
|
+
});
|
|
533
|
+
```
|
|
534
|
+
|
|
535
|
+
### 18.11.7 將 LoggingMonitor 寫入資料庫
|
|
536
|
+
|
|
537
|
+
```csharp
|
|
538
|
+
services.AddDatabaseLogging<DatabaseLoggingWriter>(options =>
|
|
539
|
+
{
|
|
540
|
+
options.WriteFilter = (logMsg) => logMsg.LogName == "System.Logging.LoggingMonitor";
|
|
541
|
+
});
|
|
542
|
+
```
|
|
543
|
+
|
|
544
|
+
### 18.11.10 跳過特定參數記錄(Furion 4.8.7.3+)
|
|
545
|
+
|
|
546
|
+
```csharp
|
|
547
|
+
[LoggingMonitor]
|
|
548
|
+
public string GetName([SuppressMonitor] SomeType type, int id) => nameof(Furion);
|
|
549
|
+
```
|
|
550
|
+
|
|
551
|
+
### 18.11.11 設定稽核日誌附加資訊(Furion 4.9.4.6+)
|
|
552
|
+
|
|
553
|
+
```csharp
|
|
554
|
+
[LoggingMonitor]
|
|
555
|
+
public void AddUser()
|
|
556
|
+
{
|
|
557
|
+
LoggingMonitorContext.Append((items, httpContext) =>
|
|
558
|
+
{
|
|
559
|
+
items.Add("框架作者", "百小僧");
|
|
560
|
+
items.Add("User-Agent", httpContext.Request.Headers.UserAgent);
|
|
561
|
+
});
|
|
562
|
+
}
|
|
563
|
+
```
|
|
564
|
+
|
|
565
|
+
### 18.11.13 過濾特定條目輸出(Furion 4.9.7.127+)
|
|
566
|
+
|
|
567
|
+
```csharp
|
|
568
|
+
services.AddMonitorLogging(options =>
|
|
569
|
+
{
|
|
570
|
+
options.ItemFilter = key => key != "Authorization";
|
|
571
|
+
});
|
|
572
|
+
```
|
|
573
|
+
|
|
574
|
+
---
|
|
575
|
+
|
|
576
|
+
## 18.15 日誌上下文(Furion 4.6.0+)
|
|
577
|
+
|
|
578
|
+
### 18.15.1 新增上下文資料
|
|
579
|
+
|
|
580
|
+
```csharp
|
|
581
|
+
// 寫法一
|
|
582
|
+
using (var scope = _logger.ScopeContext(ctx => ctx.Set("Name", "Furion").Set("UserId", 10)))
|
|
583
|
+
{
|
|
584
|
+
_logger.LogInformation("我是一個日誌 {id}", 20);
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
// 寫法二
|
|
588
|
+
using var scope = _logger.ScopeContext(new Dictionary<object, object> {
|
|
589
|
+
{ "Name", "Furion" }, { "UserId", 10 }
|
|
590
|
+
});
|
|
591
|
+
|
|
592
|
+
// 多次設定上下文(Furion 4.9.8.18+)
|
|
593
|
+
using var scope = _logger.CreateScope();
|
|
594
|
+
scope.WithContext(ctx => ctx.Set("Name", "Furion"));
|
|
595
|
+
_logger.LogInformation("日誌一");
|
|
596
|
+
scope.WithContext(ctx => ctx.Set("Other", "Some"));
|
|
597
|
+
_logger.LogInformation("日誌二");
|
|
598
|
+
```
|
|
599
|
+
|
|
600
|
+
### 18.15.2 讀取上下文資料
|
|
601
|
+
|
|
602
|
+
```csharp
|
|
603
|
+
var value = logMsg.Context.Get("Key");
|
|
604
|
+
var scopes = logMsg.Context.Scopes; // Furion 4.9.3+ 支援
|
|
605
|
+
```
|
|
606
|
+
|
|
607
|
+
---
|
|
608
|
+
|
|
609
|
+
## 18.16 關閉 .NET Core 底層日誌
|
|
610
|
+
|
|
611
|
+
```json
|
|
612
|
+
{
|
|
613
|
+
"Logging": {
|
|
614
|
+
"LogLevel": {
|
|
615
|
+
"Default": "Information",
|
|
616
|
+
"Microsoft.AspNetCore": "Warning",
|
|
617
|
+
"Microsoft.EntityFrameworkCore": "Information",
|
|
618
|
+
"System.Net.Http.HttpClient": "Warning"
|
|
619
|
+
}
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
```
|
|
623
|
+
|
|
624
|
+
---
|
|
625
|
+
|
|
626
|
+
## 18.17 全域日誌過濾/篩選
|
|
627
|
+
|
|
628
|
+
> ⚠️ 此方式會影響所有的日誌介質輸出(主控台、檔案、資料庫等)。
|
|
629
|
+
|
|
630
|
+
```csharp
|
|
631
|
+
// .NET6+
|
|
632
|
+
builder.Logging.AddFilter((provider, category, logLevel) =>
|
|
633
|
+
{
|
|
634
|
+
return !new[] { "Microsoft.Hosting", "Microsoft.AspNetCore" }.Any(u => category.StartsWith(u))
|
|
635
|
+
&& logLevel >= LogLevel.Information;
|
|
636
|
+
});
|
|
637
|
+
```
|
|
638
|
+
|
|
639
|
+
> **日誌過濾無效情況**:請確認 `appsettings.json` 中沒有配置 `"Microsoft": "Warning"` 和 `"Microsoft.Hosting.Lifetime": "Information"`,如果有請刪除。
|