log4net Action Log 設定
我之前設定網站執行的 Action Log 的一個記錄,有些東西都是拼拼湊湊出來的,並不見得是最佳版本
log4net 設定檔
1 |
|
2 | <log4net> |
3 | <root> |
4 | <level value="DEBUG" /> |
5 | <appender-ref ref="stdout" /> |
6 | <appender-ref ref="ActionLogRollingFile" /> |
7 | </root> |
8 | <appender name="ActionLogRollingFile" type="log4net.Appender.RollingFileAppender"> |
9 | <file type="log4net.Util.PatternString" value="action.log" /> |
10 | <appendToFile value="true" /> |
11 | <encoding value="utf-8" /> |
12 | <maxSizeRollBackups value="30" /> |
13 | <rollingStyle value="Date" /> |
14 | <datePattern value="'.'yyyy-MM-dd" /> |
15 | <layout type="log4net.Layout.PatternLayout"> |
16 | <conversionPattern value="(%date{HH:mm:ss,fff}) [%t] - %u %5property{Duration} %property{StatusCode} %6property{Method} %property{Uri} %m%n " /> |
17 | </layout> |
18 | <filter type="log4net.Filter.LoggerMatchFilter"> |
19 | <acceptOnMatch value="true" /> |
20 | <LoggerToMatch value="Sample.Web.Filters.WebApiActionFilter" /> |
21 | </filter> |
22 | |
23 | <filter type="log4net.Filter.DenyAllFilter" /> |
24 | </appender> |
25 | </log4net> |
其中要注意的是
- log4net.Filter.LoggerMatchFilter: 用來設定特定的 class 記錄才使用這個 Appender
- acceptOnMatch: 這個設定有點像是 blacklist/whitelist,true 表示有 match 才是,相當於 whitelist
- LoggerToMatch: 設定要篩選的類別名稱
- log4net.Filter.DenyAllFilter: 篩選掉其他的 Log,不會在這個 Appender 裡面記錄
C# Filter 程式參考
1 | /// <summary> |
2 | /// 執行 Web Api 的呼叫記錄 |
3 | /// </summary> |
4 | /// <remarks> |
5 | /// 紀錄資料: |
6 | /// |
7 | /// 呼叫時間 |
8 | /// USER |
9 | /// URL |
10 | /// METHOD |
11 | /// BODY |
12 | /// StatusCode |
13 | /// Duration |
14 | /// |
15 | /// Logger 的紀錄格式,參考 https://logging.apache.org/log4net/release/sdk/log4net.Layout.PatternLayout.html |
16 | /// </remarks> |
17 | public class WebApiActionFilter : ActionFilterAttribute |
18 | { |
19 | private ILog Logger { get; set; } |
20 | |
21 | public WebApiActionFilter() |
22 | { |
23 | Logger = LogManager.GetLog(GetType()); |
24 | } |
25 | |
26 | public WebApiActionFilter(ILog logger) |
27 | { |
28 | Logger = logger; |
29 | } |
30 | |
31 | private ThreadLocal<Stopwatch> counter = new ThreadLocal<Stopwatch>(() => new Stopwatch()); |
32 | public static ThreadLocal<Task<string>> RequestBody = new ThreadLocal<Task<string>>(); |
33 | |
34 | public override void OnActionExecuting(HttpActionContext actionContext) |
35 | { |
36 | RequestBody.Value = actionContext.Request.Content.ReadAsStringAsync(); |
37 | counter.Value.Start(); |
38 | } |
39 | |
40 | public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext) |
41 | { |
42 | counter.Value.Stop(); |
43 | LogActivity(actionExecutedContext.ActionContext, actionExecutedContext.Response); |
44 | } |
45 | |
46 | private void LogActivity(HttpActionContext actionContext, HttpResponseMessage response) |
47 | { |
48 | try |
49 | { |
50 | var loggerProp = ThreadContext.Properties; |
51 | loggerProp["Uri"] = actionContext.Request.RequestUri.PathAndQuery; |
52 | loggerProp["Method"] = actionContext.Request.Method.Method; |
53 | loggerProp["Duration"] = counter.Value.ElapsedMilliseconds; |
54 | loggerProp["StatusCode"] = (int) response.StatusCode; |
55 | |
56 | Logger.Info(RequestBody.Value.Result); |
57 | } |
58 | catch (Exception e) |
59 | { |
60 | Console.WriteLine(e); |
61 | } |
62 | } |
63 | } |
64 | |
65 | /// <summary> |
66 | /// 用來擷取傳入的 Request Content Body, 因為沒辦法在 Filter 中取得 Body |
67 | /// </summary> |
68 | /// <remark> |
69 | /// 如果需要抓傳遞資料才需要 |
70 | /// </remark> |
71 | public class LogBodyDelegateHandler : DelegatingHandler |
72 | { |
73 | |
74 | protected async override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken) |
75 | { |
76 | if (request.Content != null) |
77 | { |
78 | var requestText = request.Content.ReadAsStringAsync(); |
79 | |
80 | WebApiActionFilter.RequestBody.Value = requestText; |
81 | } |
82 | // Execute the request, this does not block |
83 | var response = base.SendAsync(request, cancellationToken); |
84 | |
85 | return response.Result; |
86 | } |
87 | } |
另外從網路上有查到一篇不錯的文章,http://it.tomtang.idv.tw/2013/12/log4net-best-practice.html
這篇是在說明 log4net 的一些設定建議
以下是他一個常用設定值的參考
1 |
|
2 | <log4net> |
3 | <appender name="ErrorFile" type="log4net.Appender.RollingFileAppender"> |
4 | <file type="log4net.Util.PatternString" value="C:\applications\logs\%property{appname}\Error-%property{appname}.log" /> |
5 | <encoding value="utf-8" /> |
6 | <appendToFile value="true" /> |
7 | <maximumFileSize value="10000KB" /> |
8 | <maxSizeRollBackups value="50" /> |
9 | <lockingModel type="log4net.Appender.FileAppender+MinimalLock" /> |
10 | <layout type="log4net.Layout.PatternLayout"> |
11 | <conversionPattern value="%date	[%thread]	%level	%logger	%property{appname}	- %message%newline" /> |
12 | </layout> |
13 | <filter type="log4net.Filter.LevelRangeFilter"> |
14 | <levelMin value="ERROR" /> |
15 | <levelMax value="FATAL" /> |
16 | </filter> |
17 | <filter type="log4net.Filter.DenyAllFilter" /> |
18 | </appender> |
19 | <appender name="WarnFile" type="log4net.Appender.RollingFileAppender"> |
20 | <file type="log4net.Util.PatternString" value="C:\applications\logs\%property{appname}\Warn-%property{appname}.log" /> |
21 | <encoding value="utf-8" /> |
22 | <appendToFile value="true" /> |
23 | <maximumFileSize value="10000KB" /> |
24 | <maxSizeRollBackups value="50" /> |
25 | <lockingModel type="log4net.Appender.FileAppender+MinimalLock" /> |
26 | <layout type="log4net.Layout.PatternLayout"> |
27 | <conversionPattern value="%date	[%thread]	%level	%logger	%property{appname}	- %message%newline" /> |
28 | </layout> |
29 | <filter type="log4net.Filter.LevelMatchFilter"> |
30 | <param name="LevelToMatch" value="WARN" /> |
31 | </filter> |
32 | <filter type="log4net.Filter.DenyAllFilter" /> |
33 | </appender> |
34 | <appender name="InfoFile" type="log4net.Appender.RollingFileAppender"> |
35 | <file type="log4net.Util.PatternString" value="C:\applications\logs\%property{appname}\Info-%property{appname}.log" /> |
36 | <encoding value="utf-8" /> |
37 | <appendToFile value="true" /> |
38 | <maximumFileSize value="10000KB" /> |
39 | <maxSizeRollBackups value="50" /> |
40 | <lockingModel type="log4net.Appender.FileAppender+MinimalLock" /> |
41 | <layout type="log4net.Layout.PatternLayout"> |
42 | <conversionPattern value="%date	[%thread]	%level	%logger	%property{appname}	- %message%newline" /> |
43 | </layout> |
44 | <filter type="log4net.Filter.LevelMatchFilter"> |
45 | <LevelToMatch value="INFO" /> |
46 | </filter> |
47 | <filter type="log4net.Filter.DenyAllFilter" /> |
48 | </appender> |
49 | <appender name="RollingFile" type="log4net.Appender.RollingFileAppender"> |
50 | <file type="log4net.Util.PatternString" value="C:\applications\logs\%property{appname}\ALL-%property{appname}.log" /> |
51 | <encoding value="utf-8" /> |
52 | <appendToFile value="true" /> |
53 | <maximumFileSize value="10000KB" /> |
54 | <maxSizeRollBackups value="50" /> |
55 | <lockingModel type="log4net.Appender.FileAppender+MinimalLock" /> |
56 | <layout type="log4net.Layout.PatternLayout"> |
57 | <conversionPattern value="%date	[%thread]	%level	%logger	%property{appname}	- %message%newline" /> |
58 | </layout> |
59 | </appender> |
60 | <appender name="debugger" type="log4net.Appender.OutputDebugStringAppender"> |
61 | <layout type="log4net.Layout.PatternLayout"> |
62 | <conversionPattern value="%date	[%thread]	%level	%logger	%property{appname}	- %message%newline" /> |
63 | </layout> |
64 | </appender> |
65 | <root additivity="true"> |
66 | <level value="ALL" /> |
67 | <appender-ref ref="debugger" /> |
68 | <appender-ref ref="RollingFile" /> |
69 | <appender-ref ref="InfoFile" /> |
70 | <appender-ref ref="WarnFile" /> |
71 | <appender-ref ref="ErrorFile" /> |
72 | </root> |
73 | <logger name=「doway.sample.helloworld」> |
74 | <level value="WARN" /> |
75 | </logger> |
76 | </log4net> |
參考