diff --git a/README.md b/README.md index d4e0d26..84c0264 100644 --- a/README.md +++ b/README.md @@ -22,13 +22,13 @@ Log.Logger = new LoggerConfiguration() ``` Many sinks simply include all properties without further action required, so the thread id will be logged automatically. -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. +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. ```csharp w.File(...., outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}] {Message:lj} {Properties}{NewLine}{Exception}") ``` -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. +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. An example, which also uses the Serilogs.Sinks.Async Nuget package, is below: @@ -46,7 +46,7 @@ An example, which also uses the Serilogs.Sinks.Async Nuget package, is below: ``` 2018-04-06 13:12:45.684 +02:00 [ERR] The file file_name.svg does not exist <4> ``` -Where, <4> is an example thread id and is an example thread name. +Where, <4> is an example thread id and \ is an example thread name. To use the enricher, first install the NuGet package: @@ -55,7 +55,7 @@ Install-Package Serilog.Enrichers.Thread ``` Note: -The {ThreadName} property will only be attached when it is not null. Otherwise it will be omitted. +The \{ThreadName} property will only be attached when it is not null. Otherwise it will be omitted. If you want to get this property always attached you can use the following: ```csharp using Serilog.Enrichers; diff --git a/src/Serilog.Enrichers.Thread/Enrichers/ThreadIdEnricher.cs b/src/Serilog.Enrichers.Thread/Enrichers/ThreadIdEnricher.cs index 656cce7..a19dc94 100644 --- a/src/Serilog.Enrichers.Thread/Enrichers/ThreadIdEnricher.cs +++ b/src/Serilog.Enrichers.Thread/Enrichers/ThreadIdEnricher.cs @@ -28,6 +28,11 @@ public class ThreadIdEnricher : ILogEventEnricher /// public const string ThreadIdPropertyName = "ThreadId"; + /// + /// The cached last created "ThreadId" property with some thread id. It is likely to be reused frequently so avoiding heap allocations. + /// + private LogEventProperty _lastValue; + /// /// Enrich the log event. /// @@ -35,7 +40,14 @@ public class ThreadIdEnricher : ILogEventEnricher /// Factory for creating new properties to add to the event. public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory) { - logEvent.AddPropertyIfAbsent(new LogEventProperty(ThreadIdPropertyName, new ScalarValue(Environment.CurrentManagedThreadId))); + var threadId = Environment.CurrentManagedThreadId; + + var last = _lastValue; + if (last == null || (int)((ScalarValue)last.Value).Value != threadId) + // no need to synchronize threads on write - just some of them will win + _lastValue = last = new LogEventProperty(ThreadIdPropertyName, new ScalarValue(threadId)); + + logEvent.AddPropertyIfAbsent(last); } } } diff --git a/src/Serilog.Enrichers.Thread/Enrichers/ThreadNameEnricher.cs b/src/Serilog.Enrichers.Thread/Enrichers/ThreadNameEnricher.cs index 92ac313..cffa6c0 100644 --- a/src/Serilog.Enrichers.Thread/Enrichers/ThreadNameEnricher.cs +++ b/src/Serilog.Enrichers.Thread/Enrichers/ThreadNameEnricher.cs @@ -29,6 +29,11 @@ public class ThreadNameEnricher : ILogEventEnricher /// public const string ThreadNamePropertyName = "ThreadName"; + /// + /// The cached last created "ThreadName" property with some thread name. It is likely to be reused frequently so avoiding heap allocations. + /// + private LogEventProperty _lastValue; + /// /// Enrich the log event. /// @@ -39,7 +44,12 @@ public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory) var threadName = Thread.CurrentThread.Name; if (threadName != null) { - logEvent.AddPropertyIfAbsent(new LogEventProperty(ThreadNamePropertyName, new ScalarValue(threadName))); + var last = _lastValue; + if (last == null || (string)((ScalarValue)last.Value).Value != threadName) + // no need to synchronize threads on write - just some of them will win + _lastValue = last = new LogEventProperty(ThreadNamePropertyName, new ScalarValue(threadName)); + + logEvent.AddPropertyIfAbsent(last); } } }