@@ -11,11 +11,22 @@ namespace Microsoft.PowerShell.EditorServices.Utility
11
11
/// </summary>
12
12
public class PsesLogger : ILogger
13
13
{
14
+ /// <summary>
15
+ /// The standard log template for all log entries.
16
+ /// </summary>
17
+ private static readonly string s_logMessageTemplate =
18
+ "[{LogLevelName:l}] tid:{ThreadId} in '{CallerName:l}' {CallerSourceFile:l} (line {CallerLineNumber}):{IndentedLogMsg:l}" ;
19
+
14
20
/// <summary>
15
21
/// The name of the ERROR log level.
16
22
/// </summary>
17
23
private static readonly string ErrorLevelName = LogLevel . Error . ToString ( ) . ToUpper ( ) ;
18
24
25
+ /// <summary>
26
+ /// The name of the WARNING log level.
27
+ /// </summary>
28
+ private static readonly string WarningLevelName = LogLevel . Warning . ToString ( ) . ToUpper ( ) ;
29
+
19
30
/// <summary>
20
31
/// The internal Serilog logger to log to.
21
32
/// </summary>
@@ -51,31 +62,46 @@ public void Write(
51
62
[ CallerMemberName ] string callerName = null ,
52
63
[ CallerFilePath ] string callerSourceFile = null ,
53
64
[ CallerLineNumber ] int callerLineNumber = 0 )
65
+ {
66
+ Write ( logLevel , new StringBuilder ( logMessage ) , callerName , callerSourceFile , callerLineNumber ) ;
67
+ }
68
+
69
+ /// <summary>
70
+ /// Write a message with the given severity to the logs. Takes a StringBuilder to allow for minimal allocation.
71
+ /// </summary>
72
+ /// <param name="logLevel">The severity level of the log message.</param>
73
+ /// <param name="logMessage">The log message itself in StringBuilder form for manipulation.</param>
74
+ /// <param name="callerName">The name of the calling method.</param>
75
+ /// <param name="callerSourceFile">The name of the source file of the caller.</param>
76
+ /// <param name="callerLineNumber">The line number where the log is being called.</param>
77
+ private void Write (
78
+ LogLevel logLevel ,
79
+ StringBuilder logMessage ,
80
+ [ CallerMemberName ] string callerName = null ,
81
+ [ CallerFilePath ] string callerSourceFile = null ,
82
+ [ CallerLineNumber ] int callerLineNumber = 0 )
54
83
{
55
84
string indentedLogMsg = IndentMsg ( logMessage ) ;
56
85
string logLevelName = logLevel . ToString ( ) . ToUpper ( ) ;
57
86
58
87
int threadId = Thread . CurrentThread . ManagedThreadId ;
59
88
60
- string messageTemplate =
61
- "[{LogLevelName:l}] tid:{threadId} in '{CallerName:l}' {CallerSourceFile:l}:{CallerLineNumber}:{IndentedLogMsg:l}" ;
62
-
63
89
switch ( logLevel )
64
90
{
65
91
case LogLevel . Diagnostic :
66
- _logger . Verbose ( messageTemplate , logLevelName , threadId , callerName , callerSourceFile , callerLineNumber , indentedLogMsg ) ;
92
+ _logger . Verbose ( s_logMessageTemplate , logLevelName , threadId , callerName , callerSourceFile , callerLineNumber , indentedLogMsg ) ;
67
93
return ;
68
94
case LogLevel . Verbose :
69
- _logger . Debug ( messageTemplate , logLevelName , threadId , callerName , callerSourceFile , callerLineNumber , indentedLogMsg ) ;
95
+ _logger . Debug ( s_logMessageTemplate , logLevelName , threadId , callerName , callerSourceFile , callerLineNumber , indentedLogMsg ) ;
70
96
return ;
71
97
case LogLevel . Normal :
72
- _logger . Information ( messageTemplate , logLevelName , threadId , callerName , callerSourceFile , callerLineNumber , indentedLogMsg ) ;
98
+ _logger . Information ( s_logMessageTemplate , logLevelName , threadId , callerName , callerSourceFile , callerLineNumber , indentedLogMsg ) ;
73
99
return ;
74
100
case LogLevel . Warning :
75
- _logger . Warning ( messageTemplate , logLevelName , threadId , callerName , callerSourceFile , callerLineNumber , indentedLogMsg ) ;
101
+ _logger . Warning ( s_logMessageTemplate , logLevelName , threadId , callerName , callerSourceFile , callerLineNumber , indentedLogMsg ) ;
76
102
return ;
77
103
case LogLevel . Error :
78
- _logger . Error ( messageTemplate , logLevelName , threadId , callerName , callerSourceFile , callerLineNumber , indentedLogMsg ) ;
104
+ _logger . Error ( s_logMessageTemplate , logLevelName , threadId , callerName , callerSourceFile , callerLineNumber , indentedLogMsg ) ;
79
105
return ;
80
106
}
81
107
}
@@ -95,26 +121,63 @@ public void WriteException(
95
121
[ CallerFilePath ] string callerSourceFile = null ,
96
122
[ CallerLineNumber ] int callerLineNumber = 0 )
97
123
{
98
- string indentedException = IndentMsg ( exception . ToString ( ) ) ;
124
+ StringBuilder body = FormatExceptionMessage ( "Exception" , errorMessage , exception ) ;
125
+ Write ( LogLevel . Error , body , callerName , callerSourceFile , callerLineNumber ) ;
126
+ }
99
127
100
- _logger . Error ( "[{ErrorLevelName:l}] {CallerSourceFile:l}: In method '{CallerName:l}', line {CallerLineNumber}: {ErrorMessage:l}{IndentedException:l}" ,
101
- ErrorLevelName , callerSourceFile , callerName , callerLineNumber , errorMessage , indentedException ) ;
128
+ /// <summary>
129
+ /// Log an exception that has been handled cleanly or is otherwise not expected to cause problems in the logs.
130
+ /// </summary>
131
+ /// <param name="errorMessage">The error message of the exception to be logged.</param>
132
+ /// <param name="exception">The exception itself that has been thrown.</param>
133
+ /// <param name="callerName">The name of the method in which the ILogger is being called.</param>
134
+ /// <param name="callerSourceFile">The name of the source file in which the ILogger is being called.</param>
135
+ /// <param name="callerLineNumber">The line number in the file where the ILogger is being called.</param>
136
+ public void WriteHandledException (
137
+ string errorMessage ,
138
+ Exception exception ,
139
+ [ CallerMemberName ] string callerName = null ,
140
+ [ CallerFilePath ] string callerSourceFile = null ,
141
+ [ CallerLineNumber ] int callerLineNumber = 0 )
142
+ {
143
+ StringBuilder body = FormatExceptionMessage ( "Handled exception" , errorMessage , exception ) ;
144
+ Write ( LogLevel . Warning , body , callerName , callerSourceFile , callerLineNumber ) ;
102
145
}
103
146
104
147
/// <summary>
105
148
/// Utility function to indent a log message by one level.
106
149
/// </summary>
107
- /// <param name="logMessage">The log message to indent .</param>
150
+ /// <param name="logMessageBuilder">Log message string builder to transform .</param>
108
151
/// <returns>The indented log message string.</returns>
109
- private static string IndentMsg ( string logMessage )
152
+ private static string IndentMsg ( StringBuilder logMessageBuilder )
110
153
{
111
- return new StringBuilder ( logMessage )
154
+ return logMessageBuilder
112
155
. Replace ( Environment . NewLine , s_indentedPrefix )
113
156
. Insert ( 0 , s_indentedPrefix )
114
157
. AppendLine ( )
115
158
. ToString ( ) ;
116
159
}
117
160
161
+ /// <summary>
162
+ /// Creates a prettified log message from an exception.
163
+ /// </summary>
164
+ /// <param name="messagePrelude">The user-readable tag for this exception entry.</param>
165
+ /// <param name="errorMessage">The user-readable short description of the error.</param>
166
+ /// <param name="exception">The exception object itself. Must not be null.</param>
167
+ /// <returns>An indented, formatted string of the body.</returns>
168
+ private static StringBuilder FormatExceptionMessage (
169
+ string messagePrelude ,
170
+ string errorMessage ,
171
+ Exception exception )
172
+ {
173
+ var sb = new StringBuilder ( )
174
+ . Append ( messagePrelude ) . Append ( ": " ) . Append ( errorMessage ) . Append ( Environment . NewLine )
175
+ . Append ( Environment . NewLine )
176
+ . Append ( exception . ToString ( ) ) ;
177
+
178
+ return sb ;
179
+ }
180
+
118
181
/// <summary>
119
182
/// A newline followed by a single indentation prefix.
120
183
/// </summary>
0 commit comments