Skip to content

Commit a049f43

Browse files
authored
Merge pull request #16 from sungam3r/caching
Add simple caching into enrichers
2 parents a30040a + 2a4b62d commit a049f43

File tree

3 files changed

+28
-6
lines changed

3 files changed

+28
-6
lines changed

README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,13 @@ Log.Logger = new LoggerConfiguration()
2222
```
2323

2424
Many sinks simply include all properties without further action required, so the thread id will be logged automatically.
25-
However, some sinks, such as the File and Console sinks use an output template and the new ThreadId may not be automatically output in your sink. In this case, in order for the ThreadId or ThreadName to show up in the logging, you will need to create or modify your output template.
25+
However, some sinks, such as the File and Console sinks use an output template and the new `ThreadId` may not be automatically output in your sink. In this case, in order for the `ThreadId` or `ThreadName` to show up in the logging, you will need to create or modify your output template.
2626

2727
```csharp
2828
w.File(...., outputTemplate:
2929
"{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}] {Message:lj} {Properties}{NewLine}{Exception}")
3030
```
31-
Here, {Properties} can include not only ThreadId and ThreadName, but any other enrichment which is applied. Alternatively, {ThreadId} could be used instead, if you want to only add the thread id enrichment and {ThreadName}, if you want to only add the thread name enrichment.
31+
Here, \{Properties} can include not only `ThreadId` and `ThreadName`, but any other enrichment which is applied. Alternatively, \{ThreadId} could be used instead, if you want to only add the thread id enrichment and \{ThreadName}, if you want to only add the thread name enrichment.
3232

3333
An example, which also uses the Serilogs.Sinks.Async Nuget package, is below:
3434

@@ -46,7 +46,7 @@ An example, which also uses the Serilogs.Sinks.Async Nuget package, is below:
4646
```
4747
2018-04-06 13:12:45.684 +02:00 [ERR] The file file_name.svg does not exist <4><MyWorker>
4848
```
49-
Where, <4> is an example thread id and <MyWorker> is an example thread name.
49+
Where, <4> is an example thread id and \<MyWorker> is an example thread name.
5050

5151
To use the enricher, first install the NuGet package:
5252

@@ -55,7 +55,7 @@ Install-Package Serilog.Enrichers.Thread
5555
```
5656

5757
Note:
58-
The {ThreadName} property will only be attached when it is not null. Otherwise it will be omitted.
58+
The \{ThreadName} property will only be attached when it is not null. Otherwise it will be omitted.
5959
If you want to get this property always attached you can use the following:
6060
```csharp
6161
using Serilog.Enrichers;

src/Serilog.Enrichers.Thread/Enrichers/ThreadIdEnricher.cs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,26 @@ public class ThreadIdEnricher : ILogEventEnricher
2828
/// </summary>
2929
public const string ThreadIdPropertyName = "ThreadId";
3030

31+
/// <summary>
32+
/// The cached last created "ThreadId" property with some thread id. It is likely to be reused frequently so avoiding heap allocations.
33+
/// </summary>
34+
private LogEventProperty _lastValue;
35+
3136
/// <summary>
3237
/// Enrich the log event.
3338
/// </summary>
3439
/// <param name="logEvent">The log event to enrich.</param>
3540
/// <param name="propertyFactory">Factory for creating new properties to add to the event.</param>
3641
public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory)
3742
{
38-
logEvent.AddPropertyIfAbsent(new LogEventProperty(ThreadIdPropertyName, new ScalarValue(Environment.CurrentManagedThreadId)));
43+
var threadId = Environment.CurrentManagedThreadId;
44+
45+
var last = _lastValue;
46+
if (last == null || (int)((ScalarValue)last.Value).Value != threadId)
47+
// no need to synchronize threads on write - just some of them will win
48+
_lastValue = last = new LogEventProperty(ThreadIdPropertyName, new ScalarValue(threadId));
49+
50+
logEvent.AddPropertyIfAbsent(last);
3951
}
4052
}
4153
}

src/Serilog.Enrichers.Thread/Enrichers/ThreadNameEnricher.cs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,11 @@ public class ThreadNameEnricher : ILogEventEnricher
2929
/// </summary>
3030
public const string ThreadNamePropertyName = "ThreadName";
3131

32+
/// <summary>
33+
/// The cached last created "ThreadName" property with some thread name. It is likely to be reused frequently so avoiding heap allocations.
34+
/// </summary>
35+
private LogEventProperty _lastValue;
36+
3237
/// <summary>
3338
/// Enrich the log event.
3439
/// </summary>
@@ -39,7 +44,12 @@ public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory)
3944
var threadName = Thread.CurrentThread.Name;
4045
if (threadName != null)
4146
{
42-
logEvent.AddPropertyIfAbsent(new LogEventProperty(ThreadNamePropertyName, new ScalarValue(threadName)));
47+
var last = _lastValue;
48+
if (last == null || (string)((ScalarValue)last.Value).Value != threadName)
49+
// no need to synchronize threads on write - just some of them will win
50+
_lastValue = last = new LogEventProperty(ThreadNamePropertyName, new ScalarValue(threadName));
51+
52+
logEvent.AddPropertyIfAbsent(last);
4353
}
4454
}
4555
}

0 commit comments

Comments
 (0)