44using Serilog . Events ;
55using System ;
66using System . Collections . Generic ;
7- using System . Linq ;
87using System . Reactive . Concurrency ;
98
109namespace YoutubeDl . Wpf . Models ;
@@ -13,61 +12,80 @@ public class QueuedTextBoxSink : ReactiveObject, ILogEventSink
1312{
1413 private readonly object _locker = new ( ) ;
1514 private readonly ObservableSettings _settings ;
16- private readonly Queue < LogEvent > _queuedLogEvents ;
15+ private readonly Queue < string > _queuedLogMessages ;
1716 private readonly IFormatProvider ? _formatProvider ;
17+ private int _contentLength ;
1818
1919 [ Reactive ]
2020 public string Content { get ; set ; } = "" ;
2121
2222 public QueuedTextBoxSink ( ObservableSettings settings , IFormatProvider ? formatProvider = null )
2323 {
2424 _settings = settings ;
25- _queuedLogEvents = new ( settings . LoggingMaxEntries ) ;
25+ _queuedLogMessages = new ( settings . LoggingMaxEntries ) ;
2626 _formatProvider = formatProvider ;
2727 }
2828
2929 public void Emit ( LogEvent logEvent )
3030 {
3131 // Workaround for https://github.com/reactiveui/ReactiveUI/issues/3415 before upstream has a fix.
32- if ( logEvent . MessageTemplate . Text . EndsWith ( " is a POCO type and won't send change notifications, WhenAny will only return a single value!" ) )
32+ if ( logEvent . MessageTemplate . Text . EndsWith ( " is a POCO type and won't send change notifications, WhenAny will only return a single value!" , StringComparison . Ordinal ) )
3333 {
3434 return ;
3535 }
3636
37+ var renderedMessage = logEvent . RenderMessage ( _formatProvider ) ;
38+
39+ // 2023-04-24T10:24:00.000+00:00 [I] Hi!
40+ var length = 29 + 1 + 3 + 1 + renderedMessage . Length + Environment . NewLine . Length ;
41+ var message = string . Create ( length , logEvent , ( buf , logEvent ) =>
42+ {
43+ if ( ! logEvent . Timestamp . TryFormat ( buf , out var charsWritten , "yyyy-MM-ddTHH:mm:ss.fffzzz" ) )
44+ throw new Exception ( "Failed to format timestamp for log message." ) ;
45+ if ( charsWritten != 29 )
46+ throw new Exception ( $ "Unexpected formatted timestamp length { charsWritten } .") ;
47+
48+ buf [ 29 ] = ' ' ;
49+ buf [ 30 ] = '[' ;
50+ buf [ 31 ] = logEvent . Level switch
51+ {
52+ LogEventLevel . Verbose => 'V' ,
53+ LogEventLevel . Debug => 'D' ,
54+ LogEventLevel . Information => 'I' ,
55+ LogEventLevel . Warning => 'W' ,
56+ LogEventLevel . Error => 'E' ,
57+ LogEventLevel . Fatal => 'F' ,
58+ _ => '?' ,
59+ } ;
60+ buf [ 32 ] = ']' ;
61+ buf [ 33 ] = ' ' ;
62+ renderedMessage . CopyTo ( buf [ 34 ..] ) ;
63+ Environment . NewLine . CopyTo ( buf [ ( 34 + renderedMessage . Length ) ..] ) ;
64+ } ) ;
65+
3766 lock ( _locker )
3867 {
39- if ( _queuedLogEvents . Count >= _settings . LoggingMaxEntries )
68+ while ( _queuedLogMessages . Count >= _settings . LoggingMaxEntries )
4069 {
41- _queuedLogEvents . Dequeue ( ) ;
70+ var dequeuedMessage = _queuedLogMessages . Dequeue ( ) ;
71+ _contentLength -= dequeuedMessage . Length ;
4272 }
4373
44- _queuedLogEvents . Enqueue ( logEvent ) ;
74+ _queuedLogMessages . Enqueue ( message ) ;
75+ _contentLength += message . Length ;
4576
46- var messages = _queuedLogEvents . Select ( x => ( x . Timestamp . ToString ( "yyyy-MM-ddTHH:mm:ss.fffzzz" ) , x . Level , x . RenderMessage ( _formatProvider ) ) ) ;
47- var length = messages . Sum ( x => x . Item1 . Length + 1 + 3 + 1 + x . Item3 . Length + Environment . NewLine . Length ) ;
48- var text = string . Create ( length , messages , ( buf , msgs ) =>
77+ var content = string . Create ( _contentLength , _queuedLogMessages , ( buf , msgs ) =>
4978 {
5079 foreach ( var msg in msgs )
5180 {
52- msg . Item1 . CopyTo ( buf ) ;
53- buf [ msg . Item1 . Length ] = ' ' ;
54- buf = buf [ ( msg . Item1 . Length + 1 ) ..] ;
55-
56- buf [ 0 ] = '[' ;
57- buf [ 1 ] = msg . Level . ToString ( ) [ 0 ] ;
58- buf [ 2 ] = ']' ;
59- buf [ 3 ] = ' ' ;
60- buf = buf [ 4 ..] ;
61-
62- msg . Item3 . CopyTo ( buf ) ;
63- Environment . NewLine . CopyTo ( buf [ msg . Item3 . Length ..] ) ;
64- buf = buf [ ( msg . Item3 . Length + Environment . NewLine . Length ) ..] ;
81+ msg . CopyTo ( buf ) ;
82+ buf = buf [ msg . Length ..] ;
6583 }
6684 } ) ;
6785
6886 RxApp . MainThreadScheduler . Schedule ( ( ) =>
6987 {
70- Content = text ;
88+ Content = content ;
7189 } ) ;
7290 }
7391 }
0 commit comments