Skip to content

Commit ef00e39

Browse files
committed
File-scoped namespaces
1 parent 947d047 commit ef00e39

16 files changed

+508
-469
lines changed
Lines changed: 42 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,51 @@
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;
216
using Serilog.Configuration;
317
using Serilog.Sinks.Async;
418

5-
namespace Serilog
19+
namespace Serilog;
20+
21+
/// <summary>
22+
/// Extends <see cref="LoggerConfiguration"/> with methods for configuring asynchronous logging.
23+
/// </summary>
24+
public static class LoggerConfigurationAsyncExtensions
625
{
726
/// <summary>
8-
/// Extends <see cref="LoggerConfiguration"/> with methods for configuring asynchronous logging.
27+
/// Configure a sink to be invoked asynchronously, on a background worker thread.
28+
/// Accepts a reference to a <paramref name="monitor"/> that will be supplied the internal state interface for health monitoring purposes.
929
/// </summary>
10-
public static class LoggerConfigurationAsyncExtensions
30+
/// <param name="loggerSinkConfiguration">The <see cref="LoggerSinkConfiguration"/> being configured.</param>
31+
/// <param name="configure">An action that configures the wrapped sink.</param>
32+
/// <param name="bufferSize">The size of the concurrent queue used to feed the background worker thread. If
33+
/// the thread is unable to process events quickly enough and the queue is filled, depending on
34+
/// <paramref name="blockWhenFull"/> the queue will block or subsequent events will be dropped until
35+
/// room is made in the queue.</param>
36+
/// <param name="blockWhenFull">Block when the queue is full, instead of dropping events.</param>
37+
/// <param name="monitor">Monitor to supply buffer information to.</param>
38+
/// <returns>A <see cref="LoggerConfiguration"/> allowing configuration to continue.</returns>
39+
public static LoggerConfiguration Async(
40+
this LoggerSinkConfiguration loggerSinkConfiguration,
41+
Action<LoggerSinkConfiguration> configure,
42+
int bufferSize = 10000,
43+
bool blockWhenFull = false,
44+
IAsyncLogEventSinkMonitor? monitor = null)
1145
{
12-
/// <summary>
13-
/// Configure a sink to be invoked asynchronously, on a background worker thread.
14-
/// Accepts a reference to a <paramref name="monitor"/> that will be supplied the internal state interface for health monitoring purposes.
15-
/// </summary>
16-
/// <param name="loggerSinkConfiguration">The <see cref="LoggerSinkConfiguration"/> being configured.</param>
17-
/// <param name="configure">An action that configures the wrapped sink.</param>
18-
/// <param name="bufferSize">The size of the concurrent queue used to feed the background worker thread. If
19-
/// the thread is unable to process events quickly enough and the queue is filled, depending on
20-
/// <paramref name="blockWhenFull"/> the queue will block or subsequent events will be dropped until
21-
/// room is made in the queue.</param>
22-
/// <param name="blockWhenFull">Block when the queue is full, instead of dropping events.</param>
23-
/// <param name="monitor">Monitor to supply buffer information to.</param>
24-
/// <returns>A <see cref="LoggerConfiguration"/> allowing configuration to continue.</returns>
25-
public static LoggerConfiguration Async(
26-
this LoggerSinkConfiguration loggerSinkConfiguration,
27-
Action<LoggerSinkConfiguration> configure,
28-
int bufferSize = 10000,
29-
bool blockWhenFull = false,
30-
IAsyncLogEventSinkMonitor? monitor = null)
31-
{
32-
var wrapper = LoggerSinkConfiguration.Wrap(
33-
wrappedSink => new BackgroundWorkerSink(wrappedSink, bufferSize, blockWhenFull, monitor),
34-
configure);
35-
return loggerSinkConfiguration.Sink(wrapper);
36-
}
46+
var wrapper = LoggerSinkConfiguration.Wrap(
47+
wrappedSink => new BackgroundWorkerSink(wrappedSink, bufferSize, blockWhenFull, monitor),
48+
configure);
49+
return loggerSinkConfiguration.Sink(wrapper);
3750
}
3851
}
Lines changed: 81 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -1,100 +1,113 @@
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;
216
using System.Collections.Concurrent;
317
using System.Threading;
418
using System.Threading.Tasks;
519
using Serilog.Core;
620
using Serilog.Debugging;
721
using Serilog.Events;
822

9-
namespace Serilog.Sinks.Async
23+
namespace Serilog.Sinks.Async;
24+
25+
sealed class BackgroundWorkerSink : ILogEventSink, IAsyncLogEventSinkInspector, IDisposable
1026
{
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;
1832

19-
long _droppedMessages;
33+
long _droppedMessages;
2034

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+
}
3145

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;
3650

37-
try
51+
try
52+
{
53+
if (_blockWhenFull)
3854
{
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);
5156
}
52-
catch (InvalidOperationException)
57+
else
5358
{
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+
}
5664
}
5765
}
58-
59-
public void Dispose()
66+
catch (InvalidOperationException)
6067
{
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();
6377

64-
// Allow queued events to be flushed
65-
_worker.Wait();
78+
// Allow queued events to be flushed
79+
_worker.Wait();
6680

67-
(_wrappedSink as IDisposable)?.Dispose();
81+
(_wrappedSink as IDisposable)?.Dispose();
6882

69-
_monitor?.StopMonitoring(this);
70-
}
83+
_monitor?.StopMonitoring(this);
84+
}
7185

72-
void Pump()
86+
void Pump()
87+
{
88+
try
7389
{
74-
try
90+
foreach (var next in _queue.GetConsumingEnumerable())
7591
{
76-
foreach (var next in _queue.GetConsumingEnumerable())
92+
try
7793
{
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);
8699
}
87-
}
88-
catch (Exception fatal)
89-
{
90-
SelfLog.WriteLine("{0} fatal error in worker thread: {1}", typeof(BackgroundWorkerSink), fatal);
91100
}
92101
}
102+
catch (Exception fatal)
103+
{
104+
SelfLog.WriteLine("{0} fatal error in worker thread: {1}", typeof(BackgroundWorkerSink), fatal);
105+
}
106+
}
93107

94-
int IAsyncLogEventSinkInspector.BufferSize => _queue.BoundedCapacity;
108+
int IAsyncLogEventSinkInspector.BufferSize => _queue.BoundedCapacity;
95109

96-
int IAsyncLogEventSinkInspector.Count => _queue.Count;
110+
int IAsyncLogEventSinkInspector.Count => _queue.Count;
97111

98-
long IAsyncLogEventSinkInspector.DroppedMessagesCount => _droppedMessages;
99-
}
112+
long IAsyncLogEventSinkInspector.DroppedMessagesCount => _droppedMessages;
100113
}
Lines changed: 32 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,38 @@
1-
namespace Serilog.Sinks.Async
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+
namespace Serilog.Sinks.Async;
16+
17+
/// <summary>
18+
/// Provides a way to inspect the state of Async wrapper's ingestion queue.
19+
/// </summary>
20+
public interface IAsyncLogEventSinkInspector
221
{
322
/// <summary>
4-
/// Provides a way to inspect the state of Async wrapper's ingestion queue.
23+
/// Configured maximum number of items permitted to be held in the buffer awaiting ingestion.
524
/// </summary>
6-
public interface IAsyncLogEventSinkInspector
7-
{
8-
/// <summary>
9-
/// Configured maximum number of items permitted to be held in the buffer awaiting ingestion.
10-
/// </summary>
11-
/// <exception cref="T:System.ObjectDisposedException">The Sink has been disposed.</exception>
12-
int BufferSize { get; }
25+
/// <exception cref="T:System.ObjectDisposedException">The Sink has been disposed.</exception>
26+
int BufferSize { get; }
1327

14-
/// <summary>
15-
/// Current moment-in-time Count of items currently awaiting ingestion.
16-
/// </summary>
17-
/// <exception cref="T:System.ObjectDisposedException">The Sink has been disposed.</exception>
18-
int Count { get; }
28+
/// <summary>
29+
/// Current moment-in-time Count of items currently awaiting ingestion.
30+
/// </summary>
31+
/// <exception cref="T:System.ObjectDisposedException">The Sink has been disposed.</exception>
32+
int Count { get; }
1933

20-
/// <summary>
21-
/// Accumulated number of messages dropped due to breaches of <see cref="BufferSize"/> limit.
22-
/// </summary>
23-
long DroppedMessagesCount { get; }
24-
}
34+
/// <summary>
35+
/// Accumulated number of messages dropped due to breaches of <see cref="BufferSize"/> limit.
36+
/// </summary>
37+
long DroppedMessagesCount { get; }
2538
}
Lines changed: 27 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,32 @@
1-
namespace Serilog.Sinks.Async
1+
namespace Serilog.Sinks.Async;
2+
// Copyright © Serilog Contributors
3+
//
4+
// Licensed under the Apache License, Version 2.0 (the "License");
5+
// you may not use this file except in compliance with the License.
6+
// You may obtain a copy of the License at
7+
//
8+
// http://www.apache.org/licenses/LICENSE-2.0
9+
//
10+
// Unless required by applicable law or agreed to in writing, software
11+
// distributed under the License is distributed on an "AS IS" BASIS,
12+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
// See the License for the specific language governing permissions and
14+
// limitations under the License.
15+
16+
/// <summary>
17+
/// Defines a mechanism for the Async Sink to afford Health Checks a buffer metadata inspection mechanism.
18+
/// </summary>
19+
public interface IAsyncLogEventSinkMonitor
220
{
321
/// <summary>
4-
/// Defines a mechanism for the Async Sink to afford Health Checks a buffer metadata inspection mechanism.
22+
/// Invoked by Sink to supply the inspector to the monitor.
523
/// </summary>
6-
public interface IAsyncLogEventSinkMonitor
7-
{
8-
/// <summary>
9-
/// Invoked by Sink to supply the inspector to the monitor.
10-
/// </summary>
11-
/// <param name="inspector">The Async Sink's inspector.</param>
12-
void StartMonitoring(IAsyncLogEventSinkInspector inspector);
24+
/// <param name="inspector">The Async Sink's inspector.</param>
25+
void StartMonitoring(IAsyncLogEventSinkInspector inspector);
1326

14-
/// <summary>
15-
/// Invoked by Sink to indicate that it is being Disposed.
16-
/// </summary>
17-
/// <param name="inspector">The Async Sink's inspector.</param>
18-
void StopMonitoring(IAsyncLogEventSinkInspector inspector);
19-
}
27+
/// <summary>
28+
/// Invoked by Sink to indicate that it is being Disposed.
29+
/// </summary>
30+
/// <param name="inspector">The Async Sink's inspector.</param>
31+
void StopMonitoring(IAsyncLogEventSinkInspector inspector);
2032
}
Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
11
using BenchmarkDotNet.Running;
22
using Xunit;
33

4-
namespace Serilog.Sinks.Async.PerformanceTests
4+
namespace Serilog.Sinks.Async.PerformanceTests;
5+
6+
public class Benchmarks
57
{
6-
public class Benchmarks
8+
[Fact]
9+
public void Benchmark()
710
{
8-
[Fact]
9-
public void Benchmark()
10-
{
11-
BenchmarkRunner.Run<ThroughputBenchmark>();
12-
BenchmarkRunner.Run<LatencyBenchmark>();
13-
}
11+
BenchmarkRunner.Run<ThroughputBenchmark>();
12+
BenchmarkRunner.Run<LatencyBenchmark>();
1413
}
1514
}

0 commit comments

Comments
 (0)