Skip to content

Commit 2168306

Browse files
authored
Merge pull request #23 from serilog/dev
4.0.0 Release
2 parents 461a287 + a692515 commit 2168306

11 files changed

+95
-62
lines changed

Build.ps1

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ if(Test-Path .\artifacts) {
1111

1212
$branch = @{ $true = $env:APPVEYOR_REPO_BRANCH; $false = $(git symbolic-ref --short -q HEAD) }[$env:APPVEYOR_REPO_BRANCH -ne $NULL];
1313
$revision = @{ $true = "{0:00000}" -f [convert]::ToInt32("0" + $env:APPVEYOR_BUILD_NUMBER, 10); $false = "local" }[$env:APPVEYOR_BUILD_NUMBER -ne $NULL];
14-
$suffix = @{ $true = ""; $false = "$($branch.Substring(0, [math]::Min(10,$branch.Length)))-$revision"}[$branch -eq "master" -and $revision -ne "local"]
14+
$suffix = @{ $true = ""; $false = "$($branch.Substring(0, [math]::Min(10,$branch.Length)))-$revision"}[$branch -eq "main" -and $revision -ne "local"]
1515

1616
echo "build: Version suffix is $suffix"
1717

@@ -20,7 +20,7 @@ foreach ($src in ls src/*) {
2020

2121
echo "build: Packaging project in $src"
2222

23-
& dotnet pack -c Release -o ..\..\artifacts --version-suffix=$suffix
23+
& dotnet pack -c Release -o ..\..\artifacts --version-suffix=$suffix -p:ContinuousIntegrationBuild=true
2424
if($LASTEXITCODE -ne 0) { exit 1 }
2525

2626
Pop-Location

README.md

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# Serilog.Enrichers.Thread [![Build status](https://ci.appveyor.com/api/projects/status/2vgxdy3swg6eaj3f?svg=true)](https://ci.appveyor.com/project/serilog/serilog-enrichers-thread) [![NuGet Version](http://img.shields.io/nuget/v/Serilog.Enrichers.Thread.svg?style=flat)](https://www.nuget.org/packages/Serilog.Enrichers.Thread/)
22

33
Enrich Serilog events with properties from the current thread.
4-
4+
55
### Getting started
66

77
Install the package from NuGet:
@@ -10,43 +10,59 @@ Install the package from NuGet:
1010
Install-Package Serilog.Enrichers.Thread
1111
```
1212

13-
In your logger configuration, apply `Enrich.WithThreadId()`:
13+
In your logger configuration, apply `Enrich.WithThreadId()` and `Enrich.WithThreadName()`:
1414

1515
```csharp
1616
Log.Logger = new LoggerConfiguration()
1717
.Enrich.WithThreadId()
18+
.Enrich.WithThreadName()
1819
.CreateLogger();
1920
```
21+
2022
Many sinks simply include all properties without further action required, so the thread id will be logged automatically.
21-
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 to show up in the logging, you will need to create or modify your output template.
23+
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.
2224

2325
```csharp
2426
w.File(...., outputTemplate:
2527
"{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}] {Message:lj} {Properties}{NewLine}{Exception}")
2628
```
27-
Here, {Properties} can include not only ThreadId, but any other enrichment which is applied. Alternatively, {ThreadId} could be used instead, if you want to only add the thread id enrichment.
29+
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.
2830

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

3133
```csharp
34+
Thread.CurrentThread.Name = "MyWorker";
35+
3236
var logger = Log.Logger = new LoggerConfiguration()
3337
.MinimumLevel.Debug()
3438
.WriteTo.Console(restrictedToMinimumLevel:Serilog.Events.LogEventLevel.Information)
35-
.WriteTo.Async(w=>w.File("..\\..\\..\\..\\logs\\SerilogLogFile.json", rollingInterval: RollingInterval.Day, outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}] {Message:lj} <{ThreadId}>{NewLine}{Exception}"))
39+
.WriteTo.Async(w=>w.File("..\\..\\..\\..\\logs\\SerilogLogFile.json", rollingInterval: RollingInterval.Day, outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}] {Message:lj} <{ThreadId}><{ThreadName}>{NewLine}{Exception}"))
3640
.Enrich.WithThreadId()
3741
.CreateLogger();
3842
```
3943
Which would produce an output in the log file as follows:
4044
```
41-
2018-04-06 13:12:45.684 +02:00 [ERR] The file file_name.svg does not exist <4>
45+
2018-04-06 13:12:45.684 +02:00 [ERR] The file file_name.svg does not exist <4><MyWorker>
4246
```
43-
Where, <4> is an example thread id.
47+
Where, <4> is an example thread id and \<MyWorker> is an example thread name.
4448

4549
To use the enricher, first install the NuGet package:
4650

4751
```powershell
4852
Install-Package Serilog.Enrichers.Thread
4953
```
5054

55+
Note:
56+
The \{ThreadName} property will only be attached when it is not null. Otherwise it will be omitted.
57+
If you want to get this property always attached you can use the following:
58+
```csharp
59+
using Serilog.Enrichers;
60+
61+
Log.Logger = new LoggerConfiguration()
62+
.Enrich.WithThreadName()
63+
.Enrich.WithProperty(ThreadNameEnricher.ThreadNamePropertyName, "MyDefault")
64+
.CreateLogger();
65+
```
66+
The enrichment order is important. Otherwise "MyDefault" would always win.
5167

5268
Copyright &copy; 2016 Serilog Contributors - Provided under the [Apache License, Version 2.0](http://apache.org/licenses/LICENSE-2.0.html).

appveyor.yml

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,26 @@
11
version: '{build}'
22
skip_tags: true
3-
image: Visual Studio 2017
3+
image: Visual Studio 2022
44
configuration: Release
55
build_script:
66
- ps: ./Build.ps1
77
test: off
88
artifacts:
99
- path: artifacts/Serilog.*.nupkg
10+
- path: artifacts/Serilog.*.snupkg
1011
deploy:
1112
- provider: NuGet
1213
api_key:
13-
secure: N59tiJECUYpip6tEn0xvdmDAEiP9SIzyLEFLpwiigm/8WhJvBNs13QxzT1/3/JW/
14+
secure: Fh92tRIFbe1FAiyD8lTThWgAorQ1vV+eFYMlUK0iLHBBenJcy/UYc1qj6kgHvUcO
1415
skip_symbols: true
1516
on:
16-
branch: /^(master|dev)$/
17+
branch: /^(main|dev)$/
1718
- provider: GitHub
1819
auth_token:
1920
secure: p4LpVhBKxGS5WqucHxFQ5c7C8cP74kbNB0Z8k9Oxx/PMaDQ1+ibmoexNqVU5ZlmX
20-
artifact: /Serilog.*\.nupkg/
21+
artifacts:
22+
/Serilog.*\.nupkg/
23+
/Serilog.*\.snupkg/
2124
tag: v$(appveyor_build_version)
2225
on:
23-
branch: master
26+
branch: main

assets/serilog-enricher-nuget.png

21.1 KB
Loading

global.json

Lines changed: 0 additions & 1 deletion
This file was deleted.

serilog-enrichers-thread.sln

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,13 @@
11

22
Microsoft Visual Studio Solution File, Format Version 12.00
3-
# Visual Studio 15
4-
VisualStudioVersion = 15.0.28307.329
3+
# Visual Studio Version 17
4+
VisualStudioVersion = 17.10.34928.147
55
MinimumVisualStudioVersion = 10.0.40219.1
66
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{037440DE-440B-4129-9F7A-09B42D00397E}"
77
EndProject
88
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "assets", "assets", "{E9D1B5E1-DEB9-4A04-8BAB-24EC7240ADAF}"
99
ProjectSection(SolutionItems) = preProject
1010
Build.ps1 = Build.ps1
11-
global.json = global.json
12-
NuGet.Config = NuGet.Config
1311
README.md = README.md
1412
assets\Serilog.snk = assets\Serilog.snk
1513
EndProjectSection

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

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
1414

15-
using System.Threading;
1615
using Serilog.Core;
1716
using Serilog.Events;
1817
using System;
@@ -22,12 +21,17 @@ namespace Serilog.Enrichers
2221
/// <summary>
2322
/// Enriches log events with a ThreadId property containing the <see cref="Environment.CurrentManagedThreadId"/>.
2423
/// </summary>
25-
public class ThreadIdEnricher : ILogEventEnricher
24+
sealed class ThreadIdEnricher : ILogEventEnricher
2625
{
2726
/// <summary>
2827
/// The property name added to enriched log events.
2928
/// </summary>
30-
public const string ThreadIdPropertyName = "ThreadId";
29+
const string ThreadIdPropertyName = "ThreadId";
30+
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;
3135

3236
/// <summary>
3337
/// Enrich the log event.
@@ -36,7 +40,14 @@ public class ThreadIdEnricher : ILogEventEnricher
3640
/// <param name="propertyFactory">Factory for creating new properties to add to the event.</param>
3741
public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory)
3842
{
39-
logEvent.AddPropertyIfAbsent(new LogEventProperty(ThreadIdPropertyName, new ScalarValue(Environment.CurrentManagedThreadId)));
43+
var threadId = Environment.CurrentManagedThreadId;
44+
45+
var last = _lastValue;
46+
if (last is 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);
4051
}
4152
}
4253
}

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

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,23 +12,26 @@
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
1414

15-
#if THREAD_NAME
1615
using System.Threading;
1716
using Serilog.Core;
1817
using Serilog.Events;
1918

2019
namespace Serilog.Enrichers
2120
{
22-
2321
/// <summary>
24-
/// Enriches log events with a ThreadName property containing the
22+
/// Enriches log events with a ThreadName property containing the <see cref="Thread.CurrentThread"/> <see cref="Thread.Name"/>.
2523
/// </summary>
26-
public class ThreadNameEnricher : ILogEventEnricher
24+
sealed class ThreadNameEnricher : ILogEventEnricher
2725
{
2826
/// <summary>
2927
/// The property name added to enriched log events.
3028
/// </summary>
31-
public const string ThreadNamePropertyName = "ThreadName";
29+
const string ThreadNamePropertyName = "ThreadName";
30+
31+
/// <summary>
32+
/// The cached last created "ThreadName" property with some thread name. It is likely to be reused frequently so avoiding heap allocations.
33+
/// </summary>
34+
private LogEventProperty? _lastValue;
3235

3336
/// <summary>
3437
/// Enrich the log event.
@@ -38,11 +41,15 @@ public class ThreadNameEnricher : ILogEventEnricher
3841
public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory)
3942
{
4043
var threadName = Thread.CurrentThread.Name;
41-
if (threadName != null)
44+
if (threadName is not null)
4245
{
43-
logEvent.AddPropertyIfAbsent(new LogEventProperty(ThreadNamePropertyName, new ScalarValue(threadName)));
46+
var last = _lastValue;
47+
if (last is null || (string)((ScalarValue)last.Value).Value! != threadName)
48+
// no need to synchronize threads on write - just some of them will win
49+
_lastValue = last = new LogEventProperty(ThreadNamePropertyName, new ScalarValue(threadName));
50+
51+
logEvent.AddPropertyIfAbsent(last);
4452
}
4553
}
4654
}
4755
}
48-
#endif

src/Serilog.Enrichers.Thread/Properties/AssemblyInfo.cs

Lines changed: 0 additions & 6 deletions
This file was deleted.
Lines changed: 25 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,16 @@
1-
<Project Sdk="Microsoft.NET.Sdk">
1+
<Project Sdk="Microsoft.NET.Sdk">
22

33
<PropertyGroup>
44
<Description>Enrich Serilog events with properties from the current thread.</Description>
5-
<VersionPrefix>3.1.0</VersionPrefix>
5+
<VersionPrefix>4.0.0</VersionPrefix>
6+
<AssemblyVersion>4.0.0.0</AssemblyVersion>
67
<Authors>Serilog Contributors</Authors>
7-
<TargetFrameworks>net45;netstandard1.0;netstandard2.0</TargetFrameworks>
8+
<!-- .NET Framework version targeting is frozen at these two TFMs. -->
9+
<TargetFrameworks Condition=" '$(OS)' == 'Windows_NT'">net471;net462</TargetFrameworks>
10+
<!-- Policy is to trim TFM-specific builds to `netstandard2.0`, `net6.0`,
11+
all active LTS versions, and optionally the latest RTM version, when releasing new
12+
major Serilog versions. -->
13+
<TargetFrameworks>$(TargetFrameworks);net8.0;net6.0;netstandard2.0</TargetFrameworks>
814
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
915
<GenerateDocumentationFile>true</GenerateDocumentationFile>
1016
<AssemblyName>Serilog.Enrichers.Thread</AssemblyName>
@@ -13,27 +19,28 @@
1319
<PublicSign Condition=" '$(OS)' != 'Windows_NT' ">true</PublicSign>
1420
<PackageId>Serilog.Enrichers.Thread</PackageId>
1521
<PackageTags>serilog;thread;enricher</PackageTags>
16-
<PackageIconUrl>http://serilog.net/images/serilog-enricher-nuget.png</PackageIconUrl>
22+
<PackageIcon>serilog-enricher-nuget.png</PackageIcon>
1723
<PackageProjectUrl>http://serilog.net</PackageProjectUrl>
18-
<PackageLicenseUrl>http://www.apache.org/licenses/LICENSE-2.0</PackageLicenseUrl>
19-
<GenerateAssemblyVersionAttribute>false</GenerateAssemblyVersionAttribute>
24+
<PackageLicenseExpression>Apache-2.0</PackageLicenseExpression>
25+
<PackageReadmeFile>README.md</PackageReadmeFile>
26+
<PublishRepositoryUrl>true</PublishRepositoryUrl>
27+
<EmbedUntrackedSources>true</EmbedUntrackedSources>
28+
<IncludeSymbols>true</IncludeSymbols>
29+
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
30+
<LangVersion>latest</LangVersion>
31+
<Nullable>enable</Nullable>
2032
</PropertyGroup>
2133

2234
<ItemGroup>
23-
<PackageReference Include="Serilog" Version="2.3.0" />
35+
<PackageReference Include="Serilog" Version="4.0.0" />
2436
</ItemGroup>
2537

26-
<ItemGroup Condition=" '$(TargetFramework)' == 'net45' ">
27-
<Reference Include="System" />
28-
<Reference Include="Microsoft.CSharp" />
38+
<ItemGroup>
39+
<None Include="..\..\assets\serilog-enricher-nuget.png">
40+
<Pack>True</Pack>
41+
<PackagePath></PackagePath>
42+
</None>
43+
<None Include="../../README.md" Pack="true" Visible="false" PackagePath="/" />
2944
</ItemGroup>
3045

31-
<PropertyGroup Condition=" '$(TargetFramework)' == 'net45' ">
32-
<DefineConstants>$(DefineConstants);THREAD_NAME</DefineConstants>
33-
</PropertyGroup>
34-
35-
<PropertyGroup Condition=" '$(TargetFramework)' == 'netstandard2.0' ">
36-
<DefineConstants>$(DefineConstants);THREAD_NAME</DefineConstants>
37-
</PropertyGroup>
38-
3946
</Project>

src/Serilog.Enrichers.Thread/ThreadLoggerConfigurationExtensions.cs

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
1414

15-
1615
using System;
1716
using System.Threading;
1817
using Serilog.Configuration;
@@ -21,7 +20,7 @@
2120
namespace Serilog
2221
{
2322
/// <summary>
24-
/// Extends <see cref="LoggerConfiguration"/> to add enrichers for <see cref="Environment.CurrentManagedThreadId"/>.
23+
/// Extends <see cref="LoggerConfiguration"/> to add enrichers for <see cref="Environment.CurrentManagedThreadId"/>
2524
/// capabilities.
2625
/// </summary>
2726
public static class ThreadLoggerConfigurationExtensions
@@ -31,26 +30,25 @@ public static class ThreadLoggerConfigurationExtensions
3130
/// </summary>
3231
/// <param name="enrichmentConfiguration">Logger enrichment configuration.</param>
3332
/// <returns>Configuration object allowing method chaining.</returns>
34-
/// <exception cref="ArgumentNullException"></exception>
33+
/// <exception cref="ArgumentNullException">If <paramref name="enrichmentConfiguration"/> is null.</exception>
3534
public static LoggerConfiguration WithThreadId(
3635
this LoggerEnrichmentConfiguration enrichmentConfiguration)
3736
{
3837
if (enrichmentConfiguration == null) throw new ArgumentNullException(nameof(enrichmentConfiguration));
3938
return enrichmentConfiguration.With<ThreadIdEnricher>();
4039
}
4140

42-
#if THREAD_NAME
4341
/// <summary>
4442
/// Enrich log events with a ThreadName property containing the <see cref="Thread.CurrentThread"/> <see cref="Thread.Name"/>.
4543
/// </summary>
46-
/// <param name="enrichmentConfiguration"></param>
47-
/// <returns></returns>
44+
/// <param name="enrichmentConfiguration">Logger enrichment configuration.</param>
45+
/// <returns>Configuration object allowing method chaining.</returns>
46+
/// <exception cref="ArgumentNullException">If <paramref name="enrichmentConfiguration"/> is null.</exception>
4847
public static LoggerConfiguration WithThreadName(
4948
this LoggerEnrichmentConfiguration enrichmentConfiguration)
5049
{
5150
if (enrichmentConfiguration == null) throw new ArgumentNullException(nameof(enrichmentConfiguration));
5251
return enrichmentConfiguration.With<ThreadNameEnricher>();
5352
}
54-
#endif
5553
}
5654
}

0 commit comments

Comments
 (0)