1
- using System ;
1
+ // Copyright © Serilog Contributors
2
+ //
3
+ // Licensed under the Apache License, Version 2.0 (the "License");
4
+ // you may not use this file except in compliance with the License.
5
+ // You may obtain a copy of the License at
6
+ //
7
+ // http://www.apache.org/licenses/LICENSE-2.0
8
+ //
9
+ // Unless required by applicable law or agreed to in writing, software
10
+ // distributed under the License is distributed on an "AS IS" BASIS,
11
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ // See the License for the specific language governing permissions and
13
+ // limitations under the License.
14
+
15
+ using System ;
2
16
using System . Collections . Concurrent ;
3
17
using System . Threading ;
4
18
using System . Threading . Tasks ;
5
19
using Serilog . Core ;
6
20
using Serilog . Debugging ;
7
21
using Serilog . Events ;
8
22
9
- namespace Serilog . Sinks . Async
23
+ namespace Serilog . Sinks . Async ;
24
+
25
+ sealed class BackgroundWorkerSink : ILogEventSink , IAsyncLogEventSinkInspector , IDisposable
10
26
{
11
- sealed class BackgroundWorkerSink : ILogEventSink , IAsyncLogEventSinkInspector , IDisposable
12
- {
13
- readonly ILogEventSink _wrappedSink ;
14
- readonly bool _blockWhenFull ;
15
- readonly BlockingCollection < LogEvent > _queue ;
16
- readonly Task _worker ;
17
- readonly IAsyncLogEventSinkMonitor ? _monitor ;
27
+ readonly ILogEventSink _wrappedSink ;
28
+ readonly bool _blockWhenFull ;
29
+ readonly BlockingCollection < LogEvent > _queue ;
30
+ readonly Task _worker ;
31
+ readonly IAsyncLogEventSinkMonitor ? _monitor ;
18
32
19
- long _droppedMessages ;
33
+ long _droppedMessages ;
20
34
21
- public BackgroundWorkerSink ( ILogEventSink wrappedSink , int bufferCapacity , bool blockWhenFull , IAsyncLogEventSinkMonitor ? monitor = null )
22
- {
23
- if ( bufferCapacity <= 0 ) throw new ArgumentOutOfRangeException ( nameof ( bufferCapacity ) ) ;
24
- _wrappedSink = wrappedSink ?? throw new ArgumentNullException ( nameof ( wrappedSink ) ) ;
25
- _blockWhenFull = blockWhenFull ;
26
- _queue = new BlockingCollection < LogEvent > ( bufferCapacity ) ;
27
- _worker = Task . Factory . StartNew ( Pump , CancellationToken . None , TaskCreationOptions . LongRunning | TaskCreationOptions . DenyChildAttach , TaskScheduler . Default ) ;
28
- _monitor = monitor ;
29
- monitor ? . StartMonitoring ( this ) ;
30
- }
35
+ public BackgroundWorkerSink ( ILogEventSink wrappedSink , int bufferCapacity , bool blockWhenFull , IAsyncLogEventSinkMonitor ? monitor = null )
36
+ {
37
+ if ( bufferCapacity <= 0 ) throw new ArgumentOutOfRangeException ( nameof ( bufferCapacity ) ) ;
38
+ _wrappedSink = wrappedSink ?? throw new ArgumentNullException ( nameof ( wrappedSink ) ) ;
39
+ _blockWhenFull = blockWhenFull ;
40
+ _queue = new BlockingCollection < LogEvent > ( bufferCapacity ) ;
41
+ _worker = Task . Factory . StartNew ( Pump , CancellationToken . None , TaskCreationOptions . LongRunning | TaskCreationOptions . DenyChildAttach , TaskScheduler . Default ) ;
42
+ _monitor = monitor ;
43
+ monitor ? . StartMonitoring ( this ) ;
44
+ }
31
45
32
- public void Emit ( LogEvent logEvent )
33
- {
34
- if ( _queue . IsAddingCompleted )
35
- return ;
46
+ public void Emit ( LogEvent logEvent )
47
+ {
48
+ if ( _queue . IsAddingCompleted )
49
+ return ;
36
50
37
- try
51
+ try
52
+ {
53
+ if ( _blockWhenFull )
38
54
{
39
- if ( _blockWhenFull )
40
- {
41
- _queue . Add ( logEvent ) ;
42
- }
43
- else
44
- {
45
- if ( ! _queue . TryAdd ( logEvent ) )
46
- {
47
- Interlocked . Increment ( ref _droppedMessages ) ;
48
- SelfLog . WriteLine ( "{0} unable to enqueue, capacity {1}" , typeof ( BackgroundWorkerSink ) , _queue . BoundedCapacity ) ;
49
- }
50
- }
55
+ _queue . Add ( logEvent ) ;
51
56
}
52
- catch ( InvalidOperationException )
57
+ else
53
58
{
54
- // Thrown in the event of a race condition when we try to add another event after
55
- // CompleteAdding has been called
59
+ if ( ! _queue . TryAdd ( logEvent ) )
60
+ {
61
+ Interlocked . Increment ( ref _droppedMessages ) ;
62
+ SelfLog . WriteLine ( "{0} unable to enqueue, capacity {1}" , typeof ( BackgroundWorkerSink ) , _queue . BoundedCapacity ) ;
63
+ }
56
64
}
57
65
}
58
-
59
- public void Dispose ( )
66
+ catch ( InvalidOperationException )
60
67
{
61
- // Prevent any more events from being added
62
- _queue . CompleteAdding ( ) ;
68
+ // Thrown in the event of a race condition when we try to add another event after
69
+ // CompleteAdding has been called
70
+ }
71
+ }
72
+
73
+ public void Dispose ( )
74
+ {
75
+ // Prevent any more events from being added
76
+ _queue . CompleteAdding ( ) ;
63
77
64
- // Allow queued events to be flushed
65
- _worker . Wait ( ) ;
78
+ // Allow queued events to be flushed
79
+ _worker . Wait ( ) ;
66
80
67
- ( _wrappedSink as IDisposable ) ? . Dispose ( ) ;
81
+ ( _wrappedSink as IDisposable ) ? . Dispose ( ) ;
68
82
69
- _monitor ? . StopMonitoring ( this ) ;
70
- }
83
+ _monitor ? . StopMonitoring ( this ) ;
84
+ }
71
85
72
- void Pump ( )
86
+ void Pump ( )
87
+ {
88
+ try
73
89
{
74
- try
90
+ foreach ( var next in _queue . GetConsumingEnumerable ( ) )
75
91
{
76
- foreach ( var next in _queue . GetConsumingEnumerable ( ) )
92
+ try
77
93
{
78
- try
79
- {
80
- _wrappedSink . Emit ( next ) ;
81
- }
82
- catch ( Exception ex )
83
- {
84
- SelfLog . WriteLine ( "{0} failed to emit event to wrapped sink: {1}" , typeof ( BackgroundWorkerSink ) , ex ) ;
85
- }
94
+ _wrappedSink . Emit ( next ) ;
95
+ }
96
+ catch ( Exception ex )
97
+ {
98
+ SelfLog . WriteLine ( "{0} failed to emit event to wrapped sink: {1}" , typeof ( BackgroundWorkerSink ) , ex ) ;
86
99
}
87
- }
88
- catch ( Exception fatal )
89
- {
90
- SelfLog . WriteLine ( "{0} fatal error in worker thread: {1}" , typeof ( BackgroundWorkerSink ) , fatal ) ;
91
100
}
92
101
}
102
+ catch ( Exception fatal )
103
+ {
104
+ SelfLog . WriteLine ( "{0} fatal error in worker thread: {1}" , typeof ( BackgroundWorkerSink ) , fatal ) ;
105
+ }
106
+ }
93
107
94
- int IAsyncLogEventSinkInspector . BufferSize => _queue . BoundedCapacity ;
108
+ int IAsyncLogEventSinkInspector . BufferSize => _queue . BoundedCapacity ;
95
109
96
- int IAsyncLogEventSinkInspector . Count => _queue . Count ;
110
+ int IAsyncLogEventSinkInspector . Count => _queue . Count ;
97
111
98
- long IAsyncLogEventSinkInspector . DroppedMessagesCount => _droppedMessages ;
99
- }
112
+ long IAsyncLogEventSinkInspector . DroppedMessagesCount => _droppedMessages ;
100
113
}
0 commit comments