diff --git a/Build.ps1 b/Build.ps1
index 9b2d878..fe080b5 100644
--- a/Build.ps1
+++ b/Build.ps1
@@ -11,7 +11,7 @@ if(Test-Path .\artifacts) {
$branch = @{ $true = $env:APPVEYOR_REPO_BRANCH; $false = $(git symbolic-ref --short -q HEAD) }[$env:APPVEYOR_REPO_BRANCH -ne $NULL];
$revision = @{ $true = "{0:00000}" -f [convert]::ToInt32("0" + $env:APPVEYOR_BUILD_NUMBER, 10); $false = "local" }[$env:APPVEYOR_BUILD_NUMBER -ne $NULL];
-$suffix = @{ $true = ""; $false = "$($branch.Substring(0, [math]::Min(10,$branch.Length)))-$revision"}[$branch -eq "master" -and $revision -ne "local"]
+$suffix = @{ $true = ""; $false = "$($branch.Substring(0, [math]::Min(10,$branch.Length)))-$revision"}[$branch -eq "main" -and $revision -ne "local"]
echo "build: Version suffix is $suffix"
diff --git a/README.md b/README.md
index 7128444..f7b5b93 100644
--- a/README.md
+++ b/README.md
@@ -4,7 +4,7 @@
For an example, see [the _dotnetconf_ deep dive session](https://channel9.msdn.com/Events/dotnetConf/2016/ASPNET-Core--deep-dive-on-building-a-real-website-with-todays-bits).
-
+
This package makes it a one-liner to configure ASP.NET Core logging with Seq.
diff --git a/appveyor.yml b/appveyor.yml
index 489e6fb..80928a3 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -9,7 +9,7 @@ artifacts:
deploy:
- provider: NuGet
api_key:
- secure: 94298ksNMfJ2LkBV3Lw9o4JVzKvVPPMHF91p0XjsBhNWVeMX2NeROX4fpio6BsQy
+ secure: QYBIGd/prsJud8qlJati9FdnXbiA0VvyxO1z0TUiQV3svdpbD7ZaykJFTYKyIdQq
skip_symbols: true
on:
- branch: /^(master|dev)$/
+ branch: /^(main|dev)$/
diff --git a/asset/icon.png b/asset/icon.png
new file mode 100644
index 0000000..ed37092
Binary files /dev/null and b/asset/icon.png differ
diff --git a/example/ConsoleApplication/ConsoleApplication.csproj b/example/ConsoleApplication/ConsoleApplication.csproj
index 25ecd34..b10ddf3 100644
--- a/example/ConsoleApplication/ConsoleApplication.csproj
+++ b/example/ConsoleApplication/ConsoleApplication.csproj
@@ -2,7 +2,7 @@
Exe
- netcoreapp3.0
+ net5.0
diff --git a/example/WebApplication/Startup.cs b/example/WebApplication/Startup.cs
index f80fcaa..7645c57 100644
--- a/example/WebApplication/Startup.cs
+++ b/example/WebApplication/Startup.cs
@@ -1,14 +1,16 @@
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
+using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
namespace WebApplication
{
public class Startup
{
- public Startup(IHostingEnvironment env)
+ public Startup(IWebHostEnvironment env)
{
var builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
@@ -23,6 +25,8 @@ public Startup(IHostingEnvironment env)
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
+ services.Configure(Configuration.GetSection("MvcOptions"));
+
services.AddLogging(loggingBuilder =>
{
// Add the Seq logger, with configuration from appsettings.json
@@ -37,12 +41,11 @@ public void ConfigureServices(IServiceCollection services)
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
- public void Configure(IApplicationBuilder app, IHostingEnvironment env)
+ public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
- app.UseBrowserLink();
}
else
{
diff --git a/example/WebApplication/WebApplication.csproj b/example/WebApplication/WebApplication.csproj
index 3996676..da94f0a 100644
--- a/example/WebApplication/WebApplication.csproj
+++ b/example/WebApplication/WebApplication.csproj
@@ -1,12 +1,10 @@
- netcoreapp2.0
+ net5.0
true
WebApplication
Exe
- WebApplication
- 2.0.0
@@ -19,8 +17,8 @@
-
-
+
+
diff --git a/example/WebApplication/appsettings.json b/example/WebApplication/appsettings.json
index ba11e4d..60f7e58 100644
--- a/example/WebApplication/appsettings.json
+++ b/example/WebApplication/appsettings.json
@@ -7,5 +7,8 @@
"ServerUrl": "http://localhost:5341",
"ApiKey": ""
}
+ },
+ "MvcOptions": {
+ "EnableEndpointRouting": false
}
}
diff --git a/global.json b/global.json
new file mode 100644
index 0000000..52599fd
--- /dev/null
+++ b/global.json
@@ -0,0 +1,6 @@
+{
+ "sdk": {
+ "version": "5.0.100",
+ "rollForward": "latestFeature"
+ }
+}
\ No newline at end of file
diff --git a/seq-extensions-logging.sln b/seq-extensions-logging.sln
index 1d425a7..2e68bf9 100644
--- a/seq-extensions-logging.sln
+++ b/seq-extensions-logging.sln
@@ -11,6 +11,9 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "global", "global", "{B0D573
Build.ps1 = Build.ps1
LICENSE = LICENSE
README.md = README.md
+ global.json = global.json
+ .gitattributes = .gitattributes
+ .gitignore = .gitignore
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{D54DE844-AC36-4872-928F-5F573D41ACAE}"
diff --git a/seq-extensions-logging.sln.DotSettings b/seq-extensions-logging.sln.DotSettings
index 4927542..1c67b9a 100644
--- a/seq-extensions-logging.sln.DotSettings
+++ b/seq-extensions-logging.sln.DotSettings
@@ -1,3 +1,6 @@
<Policy Inspect="True" Prefix="_" Suffix="" Style="aaBb"><ExtraRule Prefix="" Suffix="" Style="AaBb" /></Policy>
+ True
+ True
+ True
True
\ No newline at end of file
diff --git a/src/Seq.Extensions.Logging/Seq.Extensions.Logging.csproj b/src/Seq.Extensions.Logging/Seq.Extensions.Logging.csproj
index 0ffd3fa..7949ffe 100644
--- a/src/Seq.Extensions.Logging/Seq.Extensions.Logging.csproj
+++ b/src/Seq.Extensions.Logging/Seq.Extensions.Logging.csproj
@@ -1,19 +1,20 @@
-
+
Add centralized structured log collection to ASP.NET Core apps with one line of code.
5.0.0
Datalust and Contributors
- net462;netstandard2.0
+ net462;netstandard2.0;net5.0
true
true
../../asset/seqext.snk
true
true
aspnet;logging
- https://datalust.co/images/nuget/seq.png
+ icon.png
https://github.com/datalust/seq-extensions-logging
Apache-2.0
+
@@ -22,4 +23,8 @@
+
+
+
+
diff --git a/src/Seq.Extensions.Logging/Seq/Extensions/Logging/ExceptionDataEnricher.cs b/src/Seq.Extensions.Logging/Seq/Extensions/Logging/ExceptionDataEnricher.cs
index fe0f039..ef2fcd6 100644
--- a/src/Seq.Extensions.Logging/Seq/Extensions/Logging/ExceptionDataEnricher.cs
+++ b/src/Seq.Extensions.Logging/Seq/Extensions/Logging/ExceptionDataEnricher.cs
@@ -1,4 +1,4 @@
-// Copyright 2016 Datalust
+// Copyright 2016-2020 Datalust and Contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -23,15 +23,11 @@ class ExceptionDataEnricher : ILogEventEnricher
{
public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory)
{
- if (logEvent.Exception == null)
+ var exceptionData = logEvent.Exception?.GetBaseException().Data;
+ if (exceptionData == null || exceptionData.Count == 0)
return;
- var exception = logEvent.Exception.GetBaseException();
-
- if (exception.Data == null || exception.Data.Count == 0)
- return;
-
- var data = exception.Data
+ var data = exceptionData
.Cast()
.Where(e => e.Key is string)
.Select(e => propertyFactory.CreateProperty((string)e.Key, e.Value));
diff --git a/src/Seq.Extensions.Logging/Serilog/Extensions/Logging/SerilogLoggerProvider.cs b/src/Seq.Extensions.Logging/Serilog/Extensions/Logging/SerilogLoggerProvider.cs
index 9088b69..4ea3a5f 100644
--- a/src/Seq.Extensions.Logging/Serilog/Extensions/Logging/SerilogLoggerProvider.cs
+++ b/src/Seq.Extensions.Logging/Serilog/Extensions/Logging/SerilogLoggerProvider.cs
@@ -2,7 +2,6 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
-using System.Threading;
using Microsoft.Extensions.Logging;
using Serilog.Core;
using Serilog.Events;
@@ -15,7 +14,7 @@ namespace Serilog.Extensions.Logging
/// An that pipes events through Serilog.
///
[ProviderAlias("Seq")]
- class SerilogLoggerProvider : ILoggerProvider, ILogEventEnricher
+ class SerilogLoggerProvider : ILoggerProvider, ILogEventEnricher, ISupportExternalScope
{
internal const string OriginalFormatPropertyName = "{OriginalFormat}";
internal const string ScopePropertyName = "Scope";
@@ -23,6 +22,8 @@ class SerilogLoggerProvider : ILoggerProvider, ILogEventEnricher
readonly Logger _logger;
readonly Action _dispose;
+ IExternalScopeProvider _scopeProvider;
+
///
/// Construct a .
///
@@ -44,44 +45,39 @@ public FrameworkLogger CreateLogger(string name)
public IDisposable BeginScope(T state)
{
- return new SerilogLoggerScope(this, state);
+ return _scopeProvider?.Push(state);
}
///
public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory)
{
- List scopeItems = null;
- for (var scope = CurrentScope; scope != null; scope = scope.Parent)
- {
- LogEventPropertyValue scopeItem;
- scope.EnrichAndCreateScopeItem(logEvent, propertyFactory, out scopeItem);
+ var scopeItems = new List();
+ _scopeProvider?.ForEachScope((scopeState, state) =>
+ {
+ SerilogLoggerScope.EnrichAndCreateScopeItem(scopeState, state.logEvent, state.propertyFactory, out var scopeItem);
+
if (scopeItem != null)
{
- scopeItems = scopeItems ?? new List();
- scopeItems.Add(scopeItem);
+ state.scopeItems.Add(scopeItem);
}
- }
+ }, (logEvent, propertyFactory, scopeItems));
- if (scopeItems != null)
+ if (scopeItems.Count > 0)
{
- scopeItems.Reverse();
logEvent.AddPropertyIfAbsent(new LogEventProperty(ScopePropertyName, new SequenceValue(scopeItems)));
}
}
- readonly AsyncLocal _value = new AsyncLocal();
-
- internal SerilogLoggerScope CurrentScope
- {
- get => _value.Value;
- set => _value.Value = value;
- }
-
///
public void Dispose()
{
_dispose();
}
+
+ public void SetScopeProvider(IExternalScopeProvider scopeProvider)
+ {
+ _scopeProvider = scopeProvider;
+ }
}
}
diff --git a/src/Seq.Extensions.Logging/Serilog/Extensions/Logging/SerilogLoggerScope.cs b/src/Seq.Extensions.Logging/Serilog/Extensions/Logging/SerilogLoggerScope.cs
index be36a18..62bbe66 100644
--- a/src/Seq.Extensions.Logging/Serilog/Extensions/Logging/SerilogLoggerScope.cs
+++ b/src/Seq.Extensions.Logging/Serilog/Extensions/Logging/SerilogLoggerScope.cs
@@ -1,60 +1,25 @@
// Copyright (c) .NET Foundation. All rights reserved.
-// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+// Modifications Copyright (c) Datalust and Contributors
+// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.
-using System;
using System.Collections.Generic;
using Serilog.Core;
using Serilog.Events;
namespace Serilog.Extensions.Logging
{
- class SerilogLoggerScope : IDisposable
+ static class SerilogLoggerScope
{
const string NoName = "None";
-
- readonly SerilogLoggerProvider _provider;
- readonly object _state;
-
- // An optimization only, no problem if there are data races on this.
- bool _disposed;
-
- public SerilogLoggerScope(SerilogLoggerProvider provider, object state)
- {
- _provider = provider;
- _state = state;
-
- Parent = _provider.CurrentScope;
- _provider.CurrentScope = this;
- }
-
- public SerilogLoggerScope Parent { get; }
-
- public void Dispose()
- {
- if (!_disposed)
- {
- _disposed = true;
-
- // In case one of the parent scopes has been disposed out-of-order, don't
- // just blindly reinstate our own parent.
- for (var scan = _provider.CurrentScope; scan != null; scan = scan.Parent)
- {
- if (ReferenceEquals(scan, this))
- _provider.CurrentScope = Parent;
- }
- }
- }
-
- public void EnrichAndCreateScopeItem(LogEvent logEvent, ILogEventPropertyFactory propertyFactory, out LogEventPropertyValue scopeItem)
+
+ public static void EnrichAndCreateScopeItem(object state, LogEvent logEvent, ILogEventPropertyFactory propertyFactory, out LogEventPropertyValue scopeItem)
{
- if (_state == null)
+ if (state == null)
{
scopeItem = null;
- return;
}
- var stateProperties = _state as IEnumerable>;
- if (stateProperties != null)
+ if (state is IEnumerable> stateProperties)
{
scopeItem = null; // Unless it's `FormattedLogValues`, these are treated as property bags rather than scope items.
@@ -62,7 +27,7 @@ public void EnrichAndCreateScopeItem(LogEvent logEvent, ILogEventPropertyFactory
{
if (stateProperty.Key == SerilogLoggerProvider.OriginalFormatPropertyName && stateProperty.Value is string)
{
- scopeItem = new ScalarValue(_state.ToString());
+ scopeItem = new ScalarValue(state.ToString());
continue;
}
@@ -76,12 +41,12 @@ public void EnrichAndCreateScopeItem(LogEvent logEvent, ILogEventPropertyFactory
}
var property = propertyFactory.CreateProperty(key, stateProperty.Value, destructureObject);
- logEvent.AddPropertyIfAbsent(property);
+ logEvent.AddOrUpdateProperty(property);
}
}
else
{
- scopeItem = propertyFactory.CreateProperty(NoName, _state).Value;
+ scopeItem = propertyFactory.CreateProperty(NoName, state).Value;
}
}
}
diff --git a/test/Seq.Extensions.Logging.Tests/Seq.Extensions.Logging.Tests.csproj b/test/Seq.Extensions.Logging.Tests/Seq.Extensions.Logging.Tests.csproj
index 2643083..05ad0a3 100644
--- a/test/Seq.Extensions.Logging.Tests/Seq.Extensions.Logging.Tests.csproj
+++ b/test/Seq.Extensions.Logging.Tests/Seq.Extensions.Logging.Tests.csproj
@@ -1,7 +1,7 @@
- net472;netcoreapp3.0
+ net472;netcoreapp3.1;net5.0
../../asset/seqext.snk
true
true
@@ -20,8 +20,4 @@
-
-
-
-
diff --git a/test/Seq.Extensions.Logging.Tests/Serilog/Extensions/Logging/SerilogLoggerTests.cs b/test/Seq.Extensions.Logging.Tests/Serilog/Extensions/Logging/SerilogLoggerTests.cs
index 73d91ce..a9fd34a 100644
--- a/test/Seq.Extensions.Logging.Tests/Serilog/Extensions/Logging/SerilogLoggerTests.cs
+++ b/test/Seq.Extensions.Logging.Tests/Serilog/Extensions/Logging/SerilogLoggerTests.cs
@@ -12,7 +12,6 @@
using Serilog.Extensions.Logging;
using Seq.Extensions.Logging;
using Tests.Serilog.Extensions.Logging.Support;
-using Serilog.Core.Enrichers;
namespace Tests.Serilog.Extensions.Logging
{
@@ -28,6 +27,7 @@ private Tuple SetUp(LogLevel logLevel)
var l = new global::Serilog.Core.Logger(new global::Serilog.Core.LoggingLevelSwitch(logLevel), sink);
var provider = new SerilogLoggerProvider(l);
+ provider.SetScopeProvider(new LoggerExternalScopeProvider());
var logger = (SerilogLogger)provider.CreateLogger(Name);
return new Tuple(logger, sink);