8
8
9
9
namespace dotnetCampus . Logging . Writers ;
10
10
11
+ /// <summary>
12
+ /// 在控制台输出日志的日志记录器。
13
+ /// </summary>
11
14
public class ConsoleLogger : ILogger
12
15
{
13
16
/// <summary>
@@ -16,18 +19,40 @@ public class ConsoleLogger : ILogger
16
19
private int _isCursorMovementEnabled = 3 ;
17
20
18
21
private readonly RepeatLoggerDetector _repeat ;
19
- private TagFilterManager ? _tagFilterManager ;
20
22
21
23
/// <summary>
22
- /// 高于或等于此级别的日志才会被记录 。
24
+ /// 创建一个 <see cref="ConsoleLogger"/> 的新实例 。
23
25
/// </summary>
24
- public LogLevel Level { get ; set ; }
26
+ /// <param name="threadMode">指定控制台日志的线程安全模式。</param>
27
+ /// <param name="mainArgs">Main 方法的参数。</param>
28
+ public ConsoleLogger ( LogWritingThreadMode threadMode = LogWritingThreadMode . NotThreadSafe , string [ ] ? mainArgs = null )
29
+ : this ( threadMode . CreateCoreLogWriter ( ) , TagFilterManager . FromCommandLineArgs ( mainArgs ?? [ ] ) )
30
+ {
31
+ }
25
32
26
- public ConsoleLogger ( )
33
+ internal ConsoleLogger ( ICoreLogWriter coreWriter , TagFilterManager ? tagManager )
27
34
{
28
- _repeat = new ( ClearAndMoveToLastLine ) ;
35
+ _repeat = new RepeatLoggerDetector ( ClearAndMoveToLastLine ) ;
36
+ CoreWriter = coreWriter ;
37
+ TagManager = tagManager ;
29
38
}
30
39
40
+ /// <summary>
41
+ /// 高于或等于此级别的日志才会被记录。
42
+ /// </summary>
43
+ public LogLevel Level { get ; init ; }
44
+
45
+ /// <summary>
46
+ /// 最终日志写入器。
47
+ /// </summary>
48
+ private ICoreLogWriter CoreWriter { get ; }
49
+
50
+ /// <summary>
51
+ /// 管理控制台日志的标签过滤。
52
+ /// </summary>
53
+ private TagFilterManager ? TagManager { get ; }
54
+
55
+ /// <inheritdoc />
31
56
public void Log < TState > ( LogLevel logLevel , EventId eventId , TState state , Exception ? exception , Func < TState , Exception ? , string > formatter )
32
57
{
33
58
if ( logLevel < Level )
@@ -36,24 +61,37 @@ public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Except
36
61
}
37
62
38
63
var message = formatter ( state , exception ) ;
39
- if ( _tagFilterManager ? . IsTagEnabled ( message ) is false )
64
+ if ( TagManager ? . IsTagEnabled ( message ) is false )
40
65
{
41
66
return ;
42
67
}
43
68
69
+ var traceTag = TraceTag ;
70
+ var debugTag = DebugTag ;
71
+ var informationTag = InformationTag ;
72
+ var warningTag = WarningTag ;
73
+ var errorTag = ErrorTag ;
74
+ var criticalTag = CriticalTag ;
44
75
LogCore ( logLevel , exception , message , m => logLevel switch
45
76
{
46
- LogLevel . Trace => $ "{ TraceTag } { TraceText } { m } { Reset } ",
47
- LogLevel . Debug => $ "{ DebugTag } { DebugText } { m } { Reset } ",
48
- LogLevel . Information => $ "{ InformationTag } { InformationText } { m } { Reset } ",
49
- LogLevel . Warning => $ "{ WarningTag } { WarningText } { m } { Reset } ",
50
- LogLevel . Error => $ "{ ErrorTag } { ErrorText } { m } { Reset } ",
51
- LogLevel . Critical => $ "{ CriticalTag } { CriticalText } { m } { Reset } ",
77
+ LogLevel . Trace => $ "{ traceTag } { TraceText } { m } { Reset } ",
78
+ LogLevel . Debug => $ "{ debugTag } { DebugText } { m } { Reset } ",
79
+ LogLevel . Information => $ "{ informationTag } { InformationText } { m } { Reset } ",
80
+ LogLevel . Warning => $ "{ warningTag } { WarningText } { m } { Reset } ",
81
+ LogLevel . Error => $ "{ errorTag } { ErrorText } { m } { Reset } ",
82
+ LogLevel . Critical => $ "{ criticalTag } { CriticalText } { m } { Reset } ",
52
83
_ => null ,
53
84
} ) ;
54
85
}
55
86
56
- private void LogCore ( LogLevel logLevel , Exception ? exception , string message , Func < string , string ? > formatter )
87
+ /// <summary>
88
+ /// 记录日志。在必要的情况下会保证线程安全。
89
+ /// </summary>
90
+ /// <param name="logLevel"></param>
91
+ /// <param name="exception"></param>
92
+ /// <param name="message"></param>
93
+ /// <param name="formatter"></param>
94
+ private void LogCore ( LogLevel logLevel , Exception ? exception , string message , Func < string , string ? > formatter ) => CoreWriter . Do ( ( ) =>
57
95
{
58
96
if ( _repeat . RepeatOrResetLastLog ( logLevel , message , exception ) is var count and > 1 )
59
97
{
@@ -77,9 +115,15 @@ private void LogCore(LogLevel logLevel, Exception? exception, string message, Fu
77
115
{ tag } { exception }
78
116
""" , formatter ) ;
79
117
}
80
- }
118
+ } ) ;
81
119
82
- private static void ConsoleMultilineMessage ( string message , Func < string , string ? > formatter , bool forceSingleLine = false )
120
+ /// <summary>
121
+ /// 记录多行日志。
122
+ /// </summary>
123
+ /// <param name="message"></param>
124
+ /// <param name="formatter"></param>
125
+ /// <param name="forceSingleLine"></param>
126
+ private void ConsoleMultilineMessage ( string message , Func < string , string ? > formatter , bool forceSingleLine = false )
83
127
{
84
128
if ( forceSingleLine || ! message . Contains ( '\n ' ) )
85
129
{
@@ -96,46 +140,34 @@ private static void ConsoleMultilineMessage(string message, Func<string, string?
96
140
}
97
141
98
142
/// <summary>
99
- /// 高于或等于此级别的日志才会被记录 。
143
+ /// 清空当前行并移动光标到上一行 。
100
144
/// </summary>
101
- public ConsoleLogger UseLevel ( LogLevel level )
102
- {
103
- Level = level ;
104
- return this ;
105
- }
106
-
107
- /// <summary>
108
- /// 从命令行参数中提取过滤标签。
109
- /// </summary>
110
- /// <param name="args">命令行参数。</param>
111
- public ConsoleLogger FilterConsoleTagsFromCommandLineArgs ( string [ ] args )
112
- {
113
- _tagFilterManager = TagFilterManager . FromCommandLineArgs ( args ) ;
114
- return this ;
115
- }
116
-
145
+ /// <param name="repeatCount">此移动光标,是因为日志已重复第几次。</param>
117
146
private void ClearAndMoveToLastLine ( int repeatCount )
118
147
{
119
- if ( _isCursorMovementEnabled > 0 && repeatCount > 2 )
148
+ if ( _isCursorMovementEnabled <= 0 || repeatCount <= 2 )
120
149
{
121
- try
122
- {
123
- var desiredY = Console . CursorTop - 1 ;
124
- var y = Math . Clamp ( desiredY , 0 , Console . WindowHeight - 1 ) ;
125
- Console . SetCursorPosition ( 0 , y ) ;
126
- Console . Write ( new string ( ' ' , Console . WindowWidth ) ) ;
127
- Console . SetCursorPosition ( 0 , y ) ;
128
- }
129
- catch ( IOException )
130
- {
131
- // 日志记录时,如果无法移动光标,说明可能当前输出位置不在缓冲区内。
132
- // 如果多次尝试失败,则认为当前控制台缓冲区不支持光标移动,遂放弃。
133
- _isCursorMovementEnabled -- ;
134
- }
135
- catch ( ArgumentException )
136
- {
137
- // 日志记录时,有可能已经移动到头了,就不要移动了。
138
- }
150
+ // 如果光标控制不可用,或者还没有重复次数,则不尝试移动光标。
151
+ return ;
152
+ }
153
+
154
+ try
155
+ {
156
+ var desiredY = Console . CursorTop - 1 ;
157
+ var y = Math . Clamp ( desiredY , 0 , Console . WindowHeight - 1 ) ;
158
+ Console . SetCursorPosition ( 0 , y ) ;
159
+ Console . Write ( new string ( ' ' , Console . WindowWidth ) ) ;
160
+ Console . SetCursorPosition ( 0 , y ) ;
161
+ }
162
+ catch ( IOException )
163
+ {
164
+ // 日志记录时,如果无法移动光标,说明可能当前输出位置不在缓冲区内。
165
+ // 如果多次尝试失败,则认为当前控制台缓冲区不支持光标移动,遂放弃。
166
+ _isCursorMovementEnabled -- ;
167
+ }
168
+ catch ( ArgumentException )
169
+ {
170
+ // 日志记录时,有可能已经移动到头了,就不要移动了。
139
171
}
140
172
}
141
173
0 commit comments