@@ -29,7 +29,9 @@ internal class FileLoggerProcessor : IAsyncDisposable
29
29
private int _fileNumber ;
30
30
private bool _maxFilesReached ;
31
31
private TimeSpan _flushInterval ;
32
+ private W3CLoggingFields _fields ;
32
33
private DateTime _today = DateTime . Now ;
34
+ private bool _firstFile = true ;
33
35
34
36
private readonly IOptionsMonitor < W3CLoggerOptions > _options ;
35
37
private readonly BlockingCollection < string > _messageQueue = new BlockingCollection < string > ( _maxQueuedMessages ) ;
@@ -42,6 +44,8 @@ internal class FileLoggerProcessor : IAsyncDisposable
42
44
43
45
public FileLoggerProcessor ( IOptionsMonitor < W3CLoggerOptions > options , IHostEnvironment environment , ILoggerFactory factory )
44
46
{
47
+ _logger = factory . CreateLogger ( typeof ( FileLoggerProcessor ) ) ;
48
+
45
49
_options = options ;
46
50
var loggerOptions = _options . CurrentValue ;
47
51
@@ -62,25 +66,38 @@ public FileLoggerProcessor(IOptionsMonitor<W3CLoggerOptions> options, IHostEnvir
62
66
_maxFileSize = loggerOptions . FileSizeLimit ;
63
67
_maxRetainedFiles = loggerOptions . RetainedFileCountLimit ;
64
68
_flushInterval = loggerOptions . FlushInterval ;
69
+ _fields = loggerOptions . LoggingFields ;
65
70
_options . OnChange ( options =>
66
71
{
67
72
lock ( _pathLock )
68
73
{
69
74
// Clear the cached settings.
70
75
loggerOptions = options ;
76
+
77
+ // Move to a new file if the fields have changed
78
+ if ( _fields != loggerOptions . LoggingFields )
79
+ {
80
+ _fileNumber ++ ;
81
+ if ( _fileNumber >= W3CLoggerOptions . MaxFileCount )
82
+ {
83
+ _maxFilesReached = true ;
84
+ Log . MaxFilesReached ( _logger ) ;
85
+ }
86
+ _fields = loggerOptions . LoggingFields ;
87
+ }
88
+
71
89
if ( ! string . IsNullOrEmpty ( loggerOptions . LogDirectory ) )
72
90
{
73
91
_path = loggerOptions . LogDirectory ;
74
92
}
93
+
75
94
_fileName = loggerOptions . FileName ;
76
95
_maxFileSize = loggerOptions . FileSizeLimit ;
77
96
_maxRetainedFiles = loggerOptions . RetainedFileCountLimit ;
78
97
_flushInterval = loggerOptions . FlushInterval ;
79
98
}
80
99
} ) ;
81
100
82
- _logger = factory . CreateLogger ( typeof ( FileLoggerProcessor ) ) ;
83
-
84
101
// Start message queue processor
85
102
_cancellationTokenSource = new CancellationTokenSource ( ) ;
86
103
_outputTask = Task . Run ( ProcessLogQueue ) ;
@@ -140,6 +157,23 @@ private async Task WriteMessagesAsync(List<string> messages, CancellationToken c
140
157
// Files are written up to _maxFileSize before rolling to a new file
141
158
DateTime today = DateTime . Now ;
142
159
var fullName = GetFullName ( today ) ;
160
+ // Don't write to an incomplete file left around by a previous FileLoggerProcessor
161
+ if ( _firstFile )
162
+ {
163
+ while ( File . Exists ( fullName ) )
164
+ {
165
+ _fileNumber ++ ;
166
+ if ( _fileNumber >= W3CLoggerOptions . MaxFileCount )
167
+ {
168
+ _maxFilesReached = true ;
169
+ // Return early if log directory is already full
170
+ Log . MaxFilesReached ( _logger ) ;
171
+ return ;
172
+ }
173
+ fullName = GetFullName ( today ) ;
174
+ }
175
+ }
176
+ _firstFile = false ;
143
177
if ( _maxFilesReached )
144
178
{
145
179
// Return early if we've already logged that today's file limit has been reached.
@@ -167,26 +201,20 @@ private async Task WriteMessagesAsync(List<string> messages, CancellationToken c
167
201
fileInfo . Refresh ( ) ;
168
202
// Roll to new file if _maxFileSize is reached
169
203
// _maxFileSize could be less than the length of the file header - in that case we still write the first log message before rolling.
170
- // Previous instance of FileLoggerProcessor could have already written files to the same directory.
171
- // Loop through them until we find what the current _fileNumber should be.
172
204
if ( fileInfo . Exists && fileInfo . Length > _maxFileSize )
173
205
{
174
206
streamWriter . Dispose ( ) ;
175
- do
207
+ _fileNumber ++ ;
208
+ if ( _fileNumber >= W3CLoggerOptions . MaxFileCount )
176
209
{
177
- _fileNumber ++ ;
178
- if ( _fileNumber >= W3CLoggerOptions . MaxFileCount )
179
- {
180
- streamWriter = null ;
181
- _maxFilesReached = true ;
182
- // Return early if log directory is already full
183
- Log . MaxFilesReached ( _logger , new ApplicationException ( ) ) ;
184
- return ;
185
- }
186
- fullName = GetFullName ( today ) ;
187
- fileInfo = new FileInfo ( fullName ) ;
210
+ streamWriter = null ;
211
+ _maxFilesReached = true ;
212
+ // Return early if log directory is already full
213
+ Log . MaxFilesReached ( _logger ) ;
214
+ return ;
188
215
}
189
- while ( fileInfo . Exists && fileInfo . Length > _maxFileSize ) ;
216
+ fullName = GetFullName ( today ) ;
217
+ fileInfo = new FileInfo ( fullName ) ;
190
218
if ( ! TryCreateDirectory ( ) )
191
219
{
192
220
streamWriter = null ;
@@ -309,13 +337,13 @@ private static class Log
309
337
310
338
public static void CreateDirectoryFailed ( ILogger logger , string path , Exception ex ) => _createDirectoryFailed ( logger , path , ex ) ;
311
339
312
- private static readonly Action < ILogger , Exception > _maxFilesReached =
340
+ private static readonly Action < ILogger , Exception ? > _maxFilesReached =
313
341
LoggerMessage . Define (
314
342
LogLevel . Warning ,
315
343
new EventId ( 3 , "MaxFilesReached" ) ,
316
- "Limit of 10,000 files per day has been reached" ) ;
344
+ $ "Limit of { W3CLoggerOptions . MaxFileCount } files per day has been reached") ;
317
345
318
- public static void MaxFilesReached ( ILogger logger , Exception ex ) => _maxFilesReached ( logger , ex ) ;
346
+ public static void MaxFilesReached ( ILogger logger ) => _maxFilesReached ( logger , null ) ;
319
347
}
320
348
}
321
349
0 commit comments