Skip to content

Commit 86cb1c6

Browse files
committed
Merge pull request #36 from nblumhardt/dev
Fixes #35 - push ASP.NET contextual properties onto LogContext
2 parents 893a728 + 0a40f24 commit 86cb1c6

File tree

7 files changed

+63
-51
lines changed

7 files changed

+63
-51
lines changed

README.md

Lines changed: 4 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ This package routes ASP.NET log messages through Serilog, so you can get informa
1111
**First**, install the _Serilog.Extensions.Logging_ [NuGet package](https://www.nuget.org/packages/Serilog.Extensions.Logging) into your web or console app. You will need a way to view the log messages - _Serilog.Sinks.Literate_ writes these to the console.
1212

1313
```powershell
14-
Install-Package Serilog.Extensions.Logging
15-
Install-Package Serilog.Sinks.Literate
14+
Install-Package Serilog.Extensions.Logging -Pre -DependencyVersion Highest
15+
Install-Package Serilog.Sinks.Literate -Pre
1616
```
1717

1818
**Next**, in your application's `Startup` method, configure Serilog first:
@@ -31,7 +31,8 @@ public class Startup
3131
// Other startup code
3232
```
3333

34-
**Finally**, in your `Startup` class's `Configure()` method, call `AddSerilog()` on the provided `loggerFactory`.
34+
**Finally**, in your `Startup` class's `Configure()` method, remove the existing logger configuration entries and
35+
call `AddSerilog()` on the provided `loggerFactory`.
3536

3637
```csharp
3738
public void Configure(IApplicationBuilder app,
@@ -56,19 +57,6 @@ That's it! With the level bumped up a little you should see log output like:
5657
2015-05-15 22:14:45.741 +10:00 [DBG] Handled. Status code: 304 File: /css/site.css
5758
```
5859

59-
### Levels
60-
61-
If you want to get more information from the log you'll need to bump up the level.
62-
63-
Two things:
64-
65-
* You need to set `MinimumLevel` on **both** the Serilog `LoggerConfiguration` and the `ILoggerFactory`
66-
* Serilog and ASP.NET assign different priorities to the `Debug` and `Verbose` levels; Serilog's `Debug` is ASP.NET's `Verbose`, and vice-versa
67-
68-
### Building from source
69-
70-
To build the `dev` branch, which tracks the `dev` branch of _Microsoft.Extensions.Logging_, you must add https://www.myget.org/F/aspnetvnext/ to your package sources.
71-
7260
### Credits
7361

7462
This package evolved from an earlier package _Microsoft.Framework.Logging.Serilog_ [provided by the ASP.NET team](https://github.com/aspnet/Logging/pull/182).

samples/WebSample/Controllers/HomeController.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using System.Linq;
44
using System.Threading.Tasks;
55
using Microsoft.AspNetCore.Mvc;
6+
using Serilog;
67

78
namespace WebSample.Controllers
89
{
@@ -17,6 +18,8 @@ public IActionResult About()
1718
{
1819
ViewData["Message"] = "Your application description page.";
1920

21+
Log.Information("This is a Serilog-native event from the About action");
22+
2023
return View();
2124
}
2225

samples/WebSample/Startup.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ public Startup(IHostingEnvironment env)
2222
{
2323
Log.Logger = new LoggerConfiguration()
2424
.MinimumLevel.Debug()
25+
.Enrich.FromLogContext()
2526
.WriteTo.Seq("http://localhost:5341")
2627
.CreateLogger();
2728

src/Serilog.Extensions.Logging/Extensions/Logging/EventIdEnricher.cs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,17 @@
1+
// Copyright 2016 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+
115
using System.Collections.Generic;
216
using Microsoft.Extensions.Logging;
317
using Serilog.Core;

src/Serilog.Extensions.Logging/Extensions/Logging/SerilogLogger.cs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ namespace Serilog.Extensions.Logging
1616
class SerilogLogger : FrameworkLogger
1717
{
1818
readonly SerilogLoggerProvider _provider;
19-
readonly string _name;
2019
readonly ILogger _logger;
2120

2221
static readonly MessageTemplateParser _messageTemplateParser = new MessageTemplateParser();
@@ -28,13 +27,12 @@ public SerilogLogger(
2827
{
2928
if (provider == null) throw new ArgumentNullException(nameof(provider));
3029
_provider = provider;
31-
_name = name;
3230
_logger = logger;
3331

3432
// If a logger was passed, the provider has already added itself as an enricher
3533
_logger = _logger ?? Serilog.Log.Logger.ForContext(new[] { provider });
3634

37-
if (_name != null)
35+
if (name != null)
3836
{
3937
_logger = _logger.ForContext(Constants.SourceContextPropertyName, name);
4038
}
@@ -47,7 +45,7 @@ public bool IsEnabled(LogLevel logLevel)
4745

4846
public IDisposable BeginScope<TState>(TState state)
4947
{
50-
return _provider.BeginScope(_name, state);
48+
return _provider.BeginScope(state);
5149
}
5250

5351
public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)

src/Serilog.Extensions.Logging/Extensions/Logging/SerilogLoggerProvider.cs

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
33

44
using System;
5-
using System.Collections.Generic;
65
#if ASYNCLOCAL
76
using System.Threading;
87
#else
@@ -34,27 +33,16 @@ public FrameworkLogger CreateLogger(string name)
3433
return new SerilogLogger(this, _logger, name);
3534
}
3635

37-
public IDisposable BeginScope<T>(string name, T state)
36+
public IDisposable BeginScope<T>(T state)
3837
{
39-
return new SerilogLoggerScope(this, name, state);
38+
return new SerilogLoggerScope(this, state);
4039
}
4140

4241
public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory)
4342
{
4443
for (var scope = CurrentScope; scope != null; scope = scope.Parent)
4544
{
46-
var stateStructure = scope.State as IEnumerable<KeyValuePair<string, object>>;
47-
if (stateStructure != null)
48-
{
49-
foreach (var keyValue in stateStructure)
50-
{
51-
if (keyValue.Key == OriginalFormatPropertyName && keyValue.Value is string)
52-
continue;
53-
54-
var property = propertyFactory.CreateProperty(keyValue.Key, keyValue.Value);
55-
logEvent.AddPropertyIfAbsent(property);
56-
}
57-
}
45+
scope.Enrich(logEvent, propertyFactory);
5846
}
5947
}
6048

src/Serilog.Extensions.Logging/Extensions/Logging/SerilogLoggerScope.cs

Lines changed: 36 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,46 +2,66 @@
22
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
33

44
using System;
5+
using System.Collections.Generic;
6+
using Serilog.Context;
7+
using Serilog.Core;
8+
using Serilog.Events;
59

610
namespace Serilog.Extensions.Logging
711
{
8-
class SerilogLoggerScope : IDisposable
12+
class SerilogLoggerScope : IDisposable, ILogEventEnricher
913
{
1014
readonly SerilogLoggerProvider _provider;
11-
bool _disposedValue; // To detect redundant calls
15+
readonly object _state;
16+
readonly IDisposable _popSerilogContext;
1217

13-
public SerilogLoggerScope(SerilogLoggerProvider provider, string name, object state)
18+
// An optimization only, no problem if there are data races on this.
19+
bool _disposed;
20+
21+
public SerilogLoggerScope(SerilogLoggerProvider provider, object state)
1422
{
1523
_provider = provider;
16-
Name = name;
17-
State = state;
24+
_state = state;
1825

1926
Parent = _provider.CurrentScope;
2027
_provider.CurrentScope = this;
28+
_popSerilogContext = LogContext.PushProperties(this);
2129
}
2230

2331
public SerilogLoggerScope Parent { get; }
24-
public string Name { get; private set; }
25-
public object State { get; private set; }
26-
27-
public void RemoveScope()
32+
33+
public void Dispose()
2834
{
29-
for (var scan = _provider.CurrentScope; scan != null; scan = scan.Parent)
35+
if (!_disposed)
3036
{
31-
if (ReferenceEquals(scan, this))
37+
_disposed = true;
38+
39+
// In case one of the parent scopes has been disposed out-of-order, don't
40+
// just blindly reinstate our own parent.
41+
for (var scan = _provider.CurrentScope; scan != null; scan = scan.Parent)
3242
{
33-
_provider.CurrentScope = Parent;
43+
if (ReferenceEquals(scan, this))
44+
_provider.CurrentScope = Parent;
3445
}
46+
47+
_popSerilogContext.Dispose();
3548
}
3649
}
3750

38-
public void Dispose()
51+
public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory)
3952
{
40-
if (!_disposedValue)
53+
var stateProperties = _state as IEnumerable<KeyValuePair<string, object>>;
54+
if (stateProperties != null)
4155
{
42-
RemoveScope();
56+
foreach (var stateProperty in stateProperties)
57+
{
58+
if (stateProperty.Key == SerilogLoggerProvider.OriginalFormatPropertyName && stateProperty.Value is string)
59+
continue;
60+
61+
var property = propertyFactory.CreateProperty(stateProperty.Key, stateProperty.Value);
62+
logEvent.AddPropertyIfAbsent(property);
63+
}
4364
}
44-
_disposedValue = true;
4565
}
4666
}
4767
}

0 commit comments

Comments
 (0)