Skip to content

Commit bb2896e

Browse files
authored
Merge pull request #14 from serilog/dev
1.0.1 Release
2 parents 050f808 + 6aa2875 commit bb2896e

File tree

7 files changed

+111
-38
lines changed

7 files changed

+111
-38
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,3 +250,4 @@ paket-files/
250250
# JetBrains Rider
251251
.idea/
252252
*.sln.iml
253+
BDN.Auto/

Bench.ps1

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
echo "bench: Benchmarking started"
2+
3+
Push-Location $PSScriptRoot
4+
5+
& dotnet restore --no-cache
6+
7+
foreach ($test in ls test/*.PerformanceTests) {
8+
Push-Location $test
9+
10+
echo "bench: Benchmarking project in $test"
11+
12+
& dotnet test -c Release --framework net4.5.2
13+
if($LASTEXITCODE -ne 0) { exit 3 }
14+
15+
Pop-Location
16+
}
17+
18+
Pop-Location

README.md

Lines changed: 30 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,50 @@
1-
# Serilog.Sinks.Async [![Build status](https://ci.appveyor.com/api/projects/status/ewlh5x6xl4se5ech?svg=true)](https://ci.appveyor.com/project/JezzSantos/serilog-sinks-async)
2-
An async Serilog sink
1+
# Serilog.Sinks.Async [![Build status](https://ci.appveyor.com/api/projects/status/gvk0wl7aows14spn?svg=true)](https://ci.appveyor.com/project/serilog/serilog-sinks-async) [![NuGet](https://img.shields.io/nuget/vpre/Serilog.Sinks.Async.svg?maxAge=2592000)](https://www.nuget.org/packages/Serilog.Sinks.Async) [![Join the chat at https://gitter.im/serilog/serilog](https://img.shields.io/gitter/room/serilog/serilog.svg)](https://gitter.im/serilog/serilog)
32

4-
Use this buffered, async, delegating, sink to reduce the time it takes for your app to write your log events to your sinks. This sink can work with any `IEventLogSink` you use.
3+
An asynchronous wrapper for other [Serilog](https://serilog.net) sinks. Use this sink to reduce the overhead of logging calls by delegating work to a background thread. This is especially suited to non-batching sinks like the [File](https://github.com/serilog/serilog-sinks-file) and [RollingFile](https://github.com/serilog-serilog-sinks-rollingfile) sinks that may be affected by I/O bottlenecks.
54

6-
Especially suited to sinks that are either slow to write or have I/O bottlenecks (like http, databases, file writes etc.).
7-
This sink uses a separate thread pool thread to write to your sink, freeing up the calling thread to run in your app without having to wait.
5+
**Note:** many of the network-based sinks (_CouchDB_, _Elasticsearch_, _MongoDB_, _Seq_, _Splunk_...) already perform asychronous batching natively and do not benefit from this wrapper.
86

9-
Utilizes the producer/consumer pattern (using the TPL `BufferBlock<T>` class), where the calling thread produces log events (on your main thread), and the consumer runs on a thread pool thread consuming log events and writing them to your sink.
7+
### Getting started
108

11-
Install from NuGet:
9+
Install from [NuGet](https://nuget.org/packages/serilog.sinks.async):
1210

1311
```powershell
14-
Install-Package Serilog.Sinks.Async
12+
Install-Package Serilog.Sinks.Async -Pre
1513
```
1614

17-
Add this sink to your pipeline:
15+
Assuming you have already installed the target sink, such as the rolling file sink, move the wrapped sink's configuration within a `WriteTo.Async()` statement:
1816

1917
```csharp
2018
Log.Logger = new LoggerConfiguration()
21-
.WriteTo.Async(x => x.Sink(new YourSink()))
19+
.WriteTo.Async(a => a.RollingFile("logs/myapp-{Date}.txt"))
2220
// Other logger configuration
2321
.CreateLogger()
22+
23+
Log.Information("This will be written to disk on the worker thread");
24+
25+
// At application shutdown
26+
Log.CloseAndFlush();
2427
```
2528

26-
Now `YourSink` will write messages using another [thread pool] thread while your logging thread gets on with more important stuff.
29+
The wrapped sink (`RollingFile` in this case) will be invoked on a worker thread while your application's thread gets on with more important stuff.
30+
31+
Because the memory buffer may contain events that have not yet been written to the target sink, it is important to call `Log.CloseAndFlush()` or `Logger.Dispose()` when the application exits.
32+
33+
### Buffering
2734

28-
If you think your code is producing log events faster than your sink can consume and write them, then the buffer is going to grow in memory, until you run out!
29-
Set a maximum size of the buffer so that your memory is not filled up.
30-
Buffered log events are then (async) postponed in your app thread until your sink catches up.
35+
This sink uses a separate worker thread to write to your sink, freeing up the calling thread to run in your app without having to wait.
36+
37+
The default memory buffer feeding the worker thread is capped to 10,000 items, after which arriving events will be dropped. To increase or decrease this limit, specify it when configuring the async sink.
3138

3239
```csharp
33-
Log.Logger = new LoggerConfiguration()
34-
.WriteTo.Async(x => x.Sink(new YourSink), 500) //Max number of logevents to buffer in memory
35-
// Other logger configurationg
36-
.CreateLogger()
40+
// Reduce the buffer to 500 events
41+
.WriteTo.Async(a => a.RollingFile("logs/myapp-{Date}.txt"), 500)
3742
```
3843

39-
## About this Sink
40-
This sink was created by this conversation thread: https://github.com/serilog/serilog/issues/809
44+
### XML `<appSettings>` and JSON configuration
45+
46+
XML and JSON configuration support has not yet been added for this wrapper.
47+
48+
### About this sink
49+
50+
This sink was created following this conversation thread: https://github.com/serilog/serilog/issues/809.

serilog-sinks-async.sln

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ EndProject
1010
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "global", "global", "{154C7C14-E737-40DF-A631-B1673FE76187}"
1111
ProjectSection(SolutionItems) = preProject
1212
appveyor.yml = appveyor.yml
13+
Bench.ps1 = Bench.ps1
1314
Build.ps1 = Build.ps1
1415
global.json = global.json
1516
LICENSE = LICENSE
Lines changed: 42 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,52 +1,78 @@
11
using System;
2+
using System.IO;
23
using BenchmarkDotNet.Attributes;
3-
using Serilog;
44
using Serilog.Core;
5+
using Serilog.Debugging;
56
using Serilog.Events;
67
using Serilog.Parsing;
8+
using Serilog.Sinks.Async.PerformanceTests.Support;
79

810
namespace Serilog.Sinks.Async.PerformanceTests
911
{
1012
public class LatencyBenchmark
1113
{
12-
private const int Count = 10000;
13-
1414
private readonly LogEvent _evt = new LogEvent(DateTimeOffset.Now, LogEventLevel.Information, null,
1515
new MessageTemplate(new[] {new TextToken("Hello")}), new LogEventProperty[0]);
1616

17-
private Logger _syncLogger, _asyncLogger;
17+
private Logger _syncLogger, _asyncLogger, _fileLogger, _asyncFileLogger;
18+
19+
static LatencyBenchmark()
20+
{
21+
SelfLog.Enable(new TerminatingTextWriter());
22+
}
1823

1924
[Setup]
2025
public void Reset()
2126
{
22-
_syncLogger?.Dispose();
23-
_asyncLogger?.Dispose();
27+
foreach (var logger in new[] { _syncLogger, _asyncLogger, _fileLogger, _asyncFileLogger})
28+
{
29+
logger?.Dispose();
30+
}
31+
32+
foreach (var tmp in Directory.GetFiles(".", "*.tmplog"))
33+
{
34+
System.IO.File.Delete(tmp);
35+
}
2436

2537
_syncLogger = new LoggerConfiguration()
2638
.WriteTo.Sink(new SilentSink())
2739
.CreateLogger();
2840

2941
_asyncLogger = new LoggerConfiguration()
30-
.WriteTo.Async(a => a.Sink(new SilentSink()))
42+
.WriteTo.Async(a => a.Sink(new SilentSink()), 10000000)
43+
.CreateLogger();
44+
45+
_fileLogger = new LoggerConfiguration()
46+
.WriteTo.File("sync-file.tmplog")
47+
.CreateLogger();
48+
49+
_asyncFileLogger = new LoggerConfiguration()
50+
.WriteTo.Async(a => a.File("async-file.tmplog"), 10000000)
3151
.CreateLogger();
3252
}
3353

3454
[Benchmark(Baseline = true)]
3555
public void Sync()
3656
{
37-
for (var i = 0; i < Count; ++i)
38-
{
39-
_syncLogger.Write(_evt);
40-
}
57+
_syncLogger.Write(_evt);
4158
}
4259

4360
[Benchmark]
4461
public void Async()
4562
{
46-
for (var i = 0; i < Count; ++i)
47-
{
48-
_asyncLogger.Write(_evt);
49-
}
63+
_asyncLogger.Write(_evt);
64+
}
65+
66+
[Benchmark]
67+
public void File()
68+
{
69+
_fileLogger.Write(_evt);
70+
}
71+
72+
[Benchmark]
73+
public void AsyncFile()
74+
{
75+
_asyncFileLogger.Write(_evt);
5076
}
5177
}
52-
}
78+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
using System;
2+
using System.IO;
3+
using System.Text;
4+
5+
namespace Serilog.Sinks.Async.PerformanceTests.Support
6+
{
7+
public class TerminatingTextWriter : TextWriter
8+
{
9+
public override Encoding Encoding { get; } = Encoding.ASCII;
10+
11+
public override void Write(char value)
12+
{
13+
Console.WriteLine("SelfLog triggered");
14+
Environment.Exit(1);
15+
}
16+
}
17+
}

test/Serilog.Sinks.Async.PerformanceTests/project.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
"dependencies": {
55
"Serilog.Sinks.Async": { "target": "project" },
6+
"Serilog.Sinks.File": "2.2.0",
67
"xunit": "2.1.0",
78
"dotnet-test-xunit": "1.0.0-rc2-build10025",
89
"BenchmarkDotNet": "0.9.7-beta"
@@ -18,8 +19,7 @@
1819
"Microsoft.NETCore.App": {
1920
"type": "platform",
2021
"version": "1.0.0"
21-
},
22-
"System.Collections": "4.0.11"
22+
}
2323
},
2424
"imports": [
2525
"dnxcore50",

0 commit comments

Comments
 (0)