@@ -6,7 +6,7 @@ internal sealed class BufferedFileLogWriter(
66 Func < FileLoggerConfiguration > getCurrentConfig
77) : IFileLogWriter
88{
9- private readonly Channel < string > _logEntryChannel = Channel . CreateUnbounded < string > ( new ( )
9+ private readonly Channel < LogEvent > _logEntryChannel = Channel . CreateUnbounded < LogEvent > ( new ( )
1010 {
1111 SingleReader = true ,
1212 SingleWriter = false ,
@@ -31,15 +31,15 @@ public void Start()
3131 _writerThread . Start ( ) ;
3232 }
3333
34- public void Log ( string log )
34+ public void Log ( string log , LogLevel logLevel )
3535 {
3636 var attempt = 0 ;
3737
3838 while ( true )
3939 {
4040 try
4141 {
42- _logEntryChannel . Writer . TryWrite ( log ) ;
42+ _logEntryChannel . Writer . TryWrite ( new ( log , logLevel ) ) ;
4343
4444 break ;
4545 }
@@ -63,103 +63,124 @@ public void Dispose()
6363 }
6464
6565 private static void RunBackgroundThread (
66- ChannelReader < string > reader ,
66+ ChannelReader < LogEvent > reader ,
6767 IFileSystem fileSystem ,
6868 TimeProvider timeProvider ,
6969 Func < FileLoggerConfiguration > getCurrentConfig ,
7070 CancellationToken cancellationToken )
7171 {
7272 while ( ! cancellationToken . IsCancellationRequested )
7373 {
74- var config = getCurrentConfig ( ) ! ;
74+ var logsByLevel = new Dictionary < LogLevel , List < string > > ( ) ;
75+ var logsLengthBytesByLevel = new Dictionary < LogLevel , int > ( ) ;
7576
76- var logs = new List < string > ( ) ;
77- var logsLengthBytes = 0 ;
77+ #if NET8_0_OR_GREATER
78+ var config = getCurrentConfig ( ) ;
79+ #else
80+ var config = getCurrentConfig ( ) ! ;
81+ #endif
7882
7983 var readCount = 0 ;
8084 const int maxReadCount = 10 ;
8185
8286 while ( reader . TryRead ( out var item ) && readCount < maxReadCount )
8387 {
84- logs . Add ( item ) ;
85- logsLengthBytes += Encoding . UTF8 . GetByteCount ( item ) ;
88+ logsByLevel . TryAdd ( item . LogLevel , [ ] ) ;
89+
90+ logsByLevel [ item . LogLevel ]
91+ . Add ( item . Message ) ;
92+
93+ logsLengthBytesByLevel . TryAdd ( item . LogLevel , 0 ) ;
94+ logsLengthBytesByLevel [ item . LogLevel ] += Encoding . UTF8 . GetByteCount ( item . Message ) ;
95+
8696 readCount ++ ;
8797 }
8898
89- if ( logs . Count == 0 )
99+ if ( logsByLevel . Count == 0 )
90100 continue ;
91101
92- var attempt = 0 ;
93-
94- while ( true )
102+ foreach ( var logLevel in logsByLevel . Keys )
95103 {
96- try
97- {
98- var logsDirectoryName = config . LogDirectory ;
99-
100- var logsDirectory = fileSystem . Path . IsPathRooted ( logsDirectoryName )
101- ? logsDirectoryName
102- : fileSystem . Path . Combine ( fileSystem . Directory . GetCurrentDirectory ( ) , logsDirectoryName ) ;
103-
104- if ( ! fileSystem . Directory . Exists ( logsDirectory ) )
105- fileSystem . Directory . CreateDirectory ( logsDirectory ) ;
106-
107- var logName = config . LogName ?? AppDomain . CurrentDomain . FriendlyName ;
108- var logFilePath = fileSystem . Path . Combine ( logsDirectory , $ "{ logName } .log") ;
109-
110- var fileInfo = fileSystem . FileInfo . New ( logFilePath ) ;
111- var newFileCreated = ! fileInfo . Exists ;
104+ var logs = logsByLevel [ logLevel ] ;
105+ var logsLengthBytes = logsLengthBytesByLevel [ logLevel ] ;
112106
113- if ( ! newFileCreated && fileInfo . Length + logsLengthBytes >= config . FileSizeLimitBytes )
114- {
115- FileLogWriterUtil . RollOnFileSize ( fileSystem , timeProvider , logsDirectory , logName , logFilePath ) ;
116- newFileCreated = true ;
117- }
107+ var logsDirectoryName = config . LogDirectory ;
118108
119- if ( ! newFileCreated && config . RolloverInterval is not FileRolloverInterval . Infinite )
120- newFileCreated = FileLogWriterUtil . RollOnTimeInterval ( fileSystem ,
121- timeProvider ,
122- config . RolloverInterval ,
123- fileInfo ,
124- logsDirectory ,
125- logName ,
126- logFilePath ) ;
109+ var logsDirectory = fileSystem . Path . IsPathRooted ( logsDirectoryName )
110+ ? logsDirectoryName
111+ : fileSystem . Path . Combine ( fileSystem . Directory . GetCurrentDirectory ( ) , logsDirectoryName ) ;
127112
128- if ( newFileCreated )
129- FileLogWriterUtil . PurgeOnTotalSize ( fileSystem , config . MaxTotalSizeBytes , logsDirectory , logName ) ;
113+ if ( ! fileSystem . Directory . Exists ( logsDirectory ) )
114+ fileSystem . Directory . CreateDirectory ( logsDirectory ) ;
130115
131- FileLogWriterUtil . WriteToFile ( fileSystem , logFilePath , logs ) ;
116+ var logName = config . PerLevelLogName . TryGetValue ( logLevel , out var name )
117+ ? name ?? AppDomain . CurrentDomain . FriendlyName
118+ : config . LogName ?? AppDomain . CurrentDomain . FriendlyName ;
132119
133- // If we have rolled over the file or are writing for the first time, we want to ensure the
134- // file has the correct timestamps
135- if ( newFileCreated )
136- {
137- fileInfo . Refresh ( ) ;
120+ var logFilePath = fileSystem . Path . Combine ( logsDirectory , $ "{ logName } .log") ;
138121
139- fileInfo . CreationTimeUtc = fileInfo . LastWriteTimeUtc = fileInfo . LastAccessTimeUtc = timeProvider . GetUtcNow ( )
140- . DateTime ;
141- }
122+ var attempt = 0 ;
142123
143- break ;
144- }
145- catch ( Exception ex )
124+ while ( true )
146125 {
147126 try
148127 {
149- Console . WriteLine ( ex ) ;
150- Debug . WriteLine ( ex ) ;
128+ var fileInfo = fileSystem . FileInfo . New ( logFilePath ) ;
129+ var newFileCreated = ! fileInfo . Exists ;
130+
131+ if ( ! newFileCreated && fileInfo . Length + logsLengthBytes >= config . FileSizeLimitBytes )
132+ {
133+ FileLogWriterUtil . RollOnFileSize ( fileSystem , timeProvider , logsDirectory , logName , logFilePath ) ;
134+ newFileCreated = true ;
135+ }
136+
137+ if ( ! newFileCreated && config . RolloverInterval is not FileRolloverInterval . Infinite )
138+ newFileCreated = FileLogWriterUtil . RollOnTimeInterval ( fileSystem ,
139+ timeProvider ,
140+ config . RolloverInterval ,
141+ fileInfo ,
142+ logsDirectory ,
143+ logName ,
144+ logFilePath ) ;
145+
146+ if ( newFileCreated )
147+ FileLogWriterUtil . PurgeOnTotalSize ( fileSystem , config . MaxTotalSizeBytes , logsDirectory , logName ) ;
148+
149+ FileLogWriterUtil . WriteToFile ( fileSystem , logFilePath , logs ) ;
150+
151+ // If we have rolled over the file or are writing for the first time, we want to ensure the
152+ // file has the correct timestamps
153+ if ( newFileCreated )
154+ {
155+ fileInfo . Refresh ( ) ;
156+
157+ fileInfo . CreationTimeUtc = fileInfo . LastWriteTimeUtc = fileInfo . LastAccessTimeUtc = timeProvider . GetUtcNow ( )
158+ . DateTime ;
159+ }
160+
161+ break ;
151162 }
152- catch
163+ catch ( Exception ex )
153164 {
154- // Can't do anything more here, better to just continue
165+ try
166+ {
167+ Console . WriteLine ( ex ) ;
168+ Debug . WriteLine ( ex ) ;
169+ }
170+ catch
171+ {
172+ // Can't do anything more here, better to just continue
173+ }
174+
175+ if ( attempt >= 5 )
176+ break ;
177+
178+ attempt ++ ;
155179 }
156-
157- if ( attempt >= 5 )
158- break ;
159-
160- attempt ++ ;
161180 }
162181 }
163182 }
164183 }
184+
185+ private sealed record LogEvent ( string Message , LogLevel LogLevel ) ;
165186}
0 commit comments