22
22
23
23
namespace Serilog . Sinks . Async ;
24
24
25
- sealed class BackgroundWorkerSink : ILogEventSink , IAsyncLogEventSinkInspector , IDisposable
25
+ sealed class BackgroundWorkerSink : ILogEventSink , IAsyncLogEventSinkInspector , IDisposable , ISetLoggingFailureListener
26
26
{
27
27
readonly ILogEventSink _wrappedSink ;
28
28
readonly bool _blockWhenFull ;
29
29
readonly BlockingCollection < LogEvent > _queue ;
30
30
readonly Task _worker ;
31
31
readonly IAsyncLogEventSinkMonitor ? _monitor ;
32
+
33
+ // By contract, set only during initialization, so updates are not synchronized.
34
+ ILoggingFailureListener _failureListener = SelfLog . FailureListener ;
32
35
33
36
long _droppedMessages ;
34
37
@@ -46,7 +49,10 @@ public BackgroundWorkerSink(ILogEventSink wrappedSink, int bufferCapacity, bool
46
49
public void Emit ( LogEvent logEvent )
47
50
{
48
51
if ( _queue . IsAddingCompleted )
52
+ {
53
+ _failureListener . OnLoggingFailed ( this , LoggingFailureKind . Final , "the sink has been disposed" , [ logEvent ] , null ) ;
49
54
return ;
55
+ }
50
56
51
57
try
52
58
{
@@ -59,14 +65,15 @@ public void Emit(LogEvent logEvent)
59
65
if ( ! _queue . TryAdd ( logEvent ) )
60
66
{
61
67
Interlocked . Increment ( ref _droppedMessages ) ;
62
- SelfLog . WriteLine ( "{0} unable to enqueue, capacity {1 }", typeof ( BackgroundWorkerSink ) , _queue . BoundedCapacity ) ;
68
+ _failureListener . OnLoggingFailed ( this , LoggingFailureKind . Permanent , $ " unable to enqueue, capacity { _queue . BoundedCapacity } ", [ logEvent ] , null ) ;
63
69
}
64
70
}
65
71
}
66
- catch ( InvalidOperationException )
72
+ catch ( InvalidOperationException ex )
67
73
{
68
74
// Thrown in the event of a race condition when we try to add another event after
69
75
// CompleteAdding has been called
76
+ _failureListener . OnLoggingFailed ( this , LoggingFailureKind . Final , "the sink has been disposed" , [ logEvent ] , ex ) ;
70
77
}
71
78
}
72
79
@@ -95,13 +102,13 @@ void Pump()
95
102
}
96
103
catch ( Exception ex )
97
104
{
98
- SelfLog . WriteLine ( "{0} failed to emit event to wrapped sink: {1} ", typeof ( BackgroundWorkerSink ) , ex ) ;
105
+ _failureListener . OnLoggingFailed ( this , LoggingFailureKind . Permanent , " failed to emit event to wrapped sink", [ next ] , ex ) ;
99
106
}
100
107
}
101
108
}
102
109
catch ( Exception fatal )
103
110
{
104
- SelfLog . WriteLine ( "{0} fatal error in worker thread: {1} ", typeof ( BackgroundWorkerSink ) , fatal ) ;
111
+ _failureListener . OnLoggingFailed ( this , LoggingFailureKind . Final , " fatal error in worker thread", null , fatal ) ;
105
112
}
106
113
}
107
114
@@ -110,4 +117,9 @@ void Pump()
110
117
int IAsyncLogEventSinkInspector . Count => _queue . Count ;
111
118
112
119
long IAsyncLogEventSinkInspector . DroppedMessagesCount => _droppedMessages ;
120
+
121
+ public void SetFailureListener ( ILoggingFailureListener failureListener )
122
+ {
123
+ _failureListener = failureListener ?? throw new ArgumentNullException ( nameof ( failureListener ) ) ;
124
+ }
113
125
}
0 commit comments