diff --git a/README.md b/README.md
index efb5643..eb17258 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,8 @@
# Serilog.Extensions.Hosting [![Build status](https://ci.appveyor.com/api/projects/status/ue4s7htjwj88fulh?svg=true)](https://ci.appveyor.com/project/serilog/serilog-extensions-hosting) [![NuGet Version](http://img.shields.io/nuget/v/Serilog.Extensions.Hosting.svg?style=flat)](https://www.nuget.org/packages/Serilog.Extensions.Hosting/)
-Serilog logging for Microsoft.Extensions.Hosting . This package routes Microsoft.Extensions.Hosting log messages through Serilog, so you can get information about the framework's internal operations logged to the same Serilog sinks as your application events.
+Serilog logging for _Microsoft.Extensions.Hosting_. This package routes framework log messages through Serilog, so you can get information about the framework's internal operations written to the same Serilog sinks as your application events.
+
+**ASP.NET Core** applications should consider [using _Serilog.AspNetCore_ instead](https://github.com/serilog/serilog-aspnetcore), which bundles this package and includes other ASP.NET Core-specific features.
### Instructions
@@ -54,7 +56,7 @@ public class Program
}
```
-**Finally**, clean up by removing the rema `"Logging"` section from _appsettings.json_ files (this can be replaced with [Serilog configuration](https://github.com/serilog/serilog-settings-configuration) as shown in [this example](https://github.com/serilog/serilog-hosting/blob/dev/samples/SimpleServiceSample/Program.cs), if required)
+**Finally**, clean up by removing the remaining `"Logging"` section from _appsettings.json_ files (this can be replaced with [Serilog configuration](https://github.com/serilog/serilog-settings-configuration) as shown in [this example](https://github.com/serilog/serilog-extensions-hosting/blob/dev/samples/SimpleServiceSample/Program.cs), if required)
That's it! You will see log output like:
@@ -63,7 +65,7 @@ That's it! You will see log output like:
[22:10:39 INF] The current time is: 12/05/2018 10:10:39 +00:00
```
-A more complete example, showing _appsettings.json_ configuration, can be found in [the sample project here](https://github.com/serilog/serilog-hostinh/tree/dev/samples/SimpleServiceSample).
+A more complete example, showing _appsettings.json_ configuration, can be found in [the sample project here](https://github.com/serilog/serilog-hosting/tree/dev/samples/SimpleServiceSample).
### Using the package
@@ -78,39 +80,11 @@ You can alternatively configure Serilog using a delegate as shown below:
```csharp
// dotnet add package Serilog.Settings.Configuration
.UseSerilog((hostingContext, loggerConfiguration) => loggerConfiguration
- .ReadFrom.Configuration(hostingContext.Configuration)
- .Enrich.FromLogContext()
- .WriteTo.Console())
+ .ReadFrom.Configuration(hostingContext.Configuration)
+ .Enrich.FromLogContext()
+ .WriteTo.Console())
```
This has the advantage of making the `hostingContext`'s `Configuration` object available for configuration of the logger, but at the expense of recording `Exception`s raised earlier in program startup.
If this method is used, `Log.Logger` is assigned implicitly, and closed when the app is shut down.
-
-### Writing to the Azure Diagnostics Log Stream
-
-The Azure Diagnostic Log Stream ships events from any files in the `D:\home\LogFiles\` folder. To enable this for your app, first install the _Serilog.Sinks.File_ package:
-
-```powershell
-Install-Package Serilog.Sinks.File
-```
-
-Then add a file sink to your `LoggerConfiguration`, taking care to set the `shared` and `flushToDiskInterval` parameters:
-
-```csharp
- public static int Main(string[] args)
- {
- Log.Logger = new LoggerConfiguration()
- .MinimumLevel.Debug()
- .MinimumLevel.Override("Microsoft", LogEventLevel.Information)
- .Enrich.FromLogContext()
- .WriteTo.Console()
- // Add this line:
- .WriteTo.File(
- @"D:\home\LogFiles\Application\myapp.txt",
- fileSizeLimitBytes: 1_000_000,
- rollOnFileSizeLimit: true,
- shared: true,
- flushToDiskInterval: TimeSpan.FromSeconds(1))
- .CreateLogger();
-```
diff --git a/appveyor.yml b/appveyor.yml
index 02761fd..9ca24f7 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -7,10 +7,13 @@ build_script:
- ps: ./Build.ps1
artifacts:
- path: artifacts/Serilog.*.nupkg
+skip_commits:
+ files:
+ - README.md
deploy:
- provider: NuGet
api_key:
- secure: bd9z4P73oltOXudAjPehwp9iDKsPtC+HbgshOrSgoyQKr5xVK+bxJQngrDJkHdY8
+ secure: JAnOxPQMZRp8ousbAW4vYnVtd936AOMp4gDGucCQ1RZrDZW3J+X5QmbLO7OJKtBr
skip_symbols: true
on:
branch: /^(master|dev)$/
diff --git a/global.json b/global.json
index 6b51ddf..0a37afd 100644
--- a/global.json
+++ b/global.json
@@ -1,5 +1,5 @@
{
"sdk": {
- "version": "2.1.300-*"
+ "version": "2.2.105"
}
}
diff --git a/samples/SimpleServiceSample/PrintTimeService.cs b/samples/SimpleServiceSample/PrintTimeService.cs
index aa59fd0..513cace 100644
--- a/samples/SimpleServiceSample/PrintTimeService.cs
+++ b/samples/SimpleServiceSample/PrintTimeService.cs
@@ -4,7 +4,7 @@
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
-namespace SimpleWebSample
+namespace SimpleServiceSample
{
public class PrintTimeService : IHostedService, IDisposable
{
diff --git a/samples/SimpleServiceSample/Program.cs b/samples/SimpleServiceSample/Program.cs
index b357b10..4ff6e7e 100644
--- a/samples/SimpleServiceSample/Program.cs
+++ b/samples/SimpleServiceSample/Program.cs
@@ -1,11 +1,11 @@
using System;
using System.IO;
-using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Configuration;
-using Serilog;
using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
+using Serilog;
-namespace SimpleWebSample
+namespace SimpleServiceSample
{
public class Program
{
diff --git a/samples/SimpleServiceSample/SimpleServiceSample.csproj b/samples/SimpleServiceSample/SimpleServiceSample.csproj
index aadac55..36bbcf2 100644
--- a/samples/SimpleServiceSample/SimpleServiceSample.csproj
+++ b/samples/SimpleServiceSample/SimpleServiceSample.csproj
@@ -13,12 +13,12 @@
-
-
-
-
-
-
+
+
+
+
+
+
diff --git a/serilog-extensions-hosting.sln.DotSettings b/serilog-extensions-hosting.sln.DotSettings
new file mode 100644
index 0000000..87d9b7b
--- /dev/null
+++ b/serilog-extensions-hosting.sln.DotSettings
@@ -0,0 +1,5 @@
+
+ True
+ True
+ True
+ True
\ No newline at end of file
diff --git a/src/Serilog.Extensions.Hosting/Extensions/Hosting/AmbientDiagnosticContextCollector.cs b/src/Serilog.Extensions.Hosting/Extensions/Hosting/AmbientDiagnosticContextCollector.cs
new file mode 100644
index 0000000..68010ee
--- /dev/null
+++ b/src/Serilog.Extensions.Hosting/Extensions/Hosting/AmbientDiagnosticContextCollector.cs
@@ -0,0 +1,46 @@
+// Copyright 2019 Serilog Contributors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+using System;
+using System.Threading;
+
+namespace Serilog.Extensions.Hosting
+{
+ class AmbientDiagnosticContextCollector : IDisposable
+ {
+ static readonly AsyncLocal AmbientCollector =
+ new AsyncLocal();
+
+ // The indirection here ensures that completing collection cleans up the collector in all
+ // execution contexts. Via @benaadams' addition to `HttpContextAccessor` :-)
+ DiagnosticContextCollector _collector;
+
+ public static DiagnosticContextCollector Current => AmbientCollector.Value?._collector;
+
+ public static DiagnosticContextCollector Begin()
+ {
+ var value = new AmbientDiagnosticContextCollector();
+ value._collector = new DiagnosticContextCollector(value);
+ AmbientCollector.Value = value;
+ return value._collector;
+ }
+
+ public void Dispose()
+ {
+ _collector = null;
+ if (AmbientCollector.Value == this)
+ AmbientCollector.Value = null;
+ }
+ }
+}
diff --git a/src/Serilog.Extensions.Hosting/Extensions/Hosting/DiagnosticContext.cs b/src/Serilog.Extensions.Hosting/Extensions/Hosting/DiagnosticContext.cs
new file mode 100644
index 0000000..7c12c19
--- /dev/null
+++ b/src/Serilog.Extensions.Hosting/Extensions/Hosting/DiagnosticContext.cs
@@ -0,0 +1,60 @@
+// Copyright 2019 Serilog Contributors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+using System;
+using System.Threading;
+
+namespace Serilog.Extensions.Hosting
+{
+ ///
+ /// Implements an ambient diagnostic context using .
+ ///
+ /// Consumers should use to set context properties.
+ public sealed class DiagnosticContext : IDiagnosticContext
+ {
+ readonly ILogger _logger;
+
+ ///
+ /// Construct a .
+ ///
+ /// A logger for binding properties in the context, or null to use .
+ public DiagnosticContext(ILogger logger)
+ {
+ _logger = logger;
+ }
+
+ ///
+ /// Start collecting properties to associate with the current diagnostic context. This will replace
+ /// the active collector, if any.
+ ///
+ /// A collector that will receive properties added in the current diagnostic context.
+ public DiagnosticContextCollector BeginCollection()
+ {
+ return AmbientDiagnosticContextCollector.Begin();
+ }
+
+ ///
+ public void Set(string propertyName, object value, bool destructureObjects = false)
+ {
+ if (propertyName == null) throw new ArgumentNullException(nameof(propertyName));
+
+ var collector = AmbientDiagnosticContextCollector.Current;
+ if (collector != null &&
+ (_logger ?? Log.Logger).BindProperty(propertyName, value, destructureObjects, out var property))
+ {
+ collector.AddOrUpdate(property);
+ }
+ }
+ }
+}
diff --git a/src/Serilog.Extensions.Hosting/Extensions/Hosting/DiagnosticContextCollector.cs b/src/Serilog.Extensions.Hosting/Extensions/Hosting/DiagnosticContextCollector.cs
new file mode 100644
index 0000000..d1aba65
--- /dev/null
+++ b/src/Serilog.Extensions.Hosting/Extensions/Hosting/DiagnosticContextCollector.cs
@@ -0,0 +1,65 @@
+using System;
+using System.Collections.Generic;
+using Serilog.Events;
+
+namespace Serilog.Extensions.Hosting
+{
+ ///
+ /// A container that receives properties added to a diagnostic context.
+ ///
+ public sealed class DiagnosticContextCollector : IDisposable
+ {
+ readonly IDisposable _chainedDisposable;
+ readonly object _propertiesLock = new object();
+ Dictionary _properties = new Dictionary();
+
+ ///
+ /// Construct a .
+ ///
+ /// An object that will be disposed to signal completion/disposal of
+ /// the collector.
+ public DiagnosticContextCollector(IDisposable chainedDisposable)
+ {
+ _chainedDisposable = chainedDisposable ?? throw new ArgumentNullException(nameof(chainedDisposable));
+ }
+
+ ///
+ /// Add the property to the context.
+ ///
+ /// The property to add.
+ public void AddOrUpdate(LogEventProperty property)
+ {
+ if (property == null) throw new ArgumentNullException(nameof(property));
+
+ lock (_propertiesLock)
+ {
+ if (_properties == null) return;
+ _properties[property.Name] = property;
+ }
+ }
+
+ ///
+ /// Complete the context and retrieve the properties added to it, if any. This will
+ /// stop collection and remove the collector from the original execution context and
+ /// any of its children.
+ ///
+ /// The collected properties, or null if no collection is active.
+ /// True if properties could be collected.
+ public bool TryComplete(out IEnumerable properties)
+ {
+ lock (_propertiesLock)
+ {
+ properties = _properties?.Values;
+ _properties = null;
+ Dispose();
+ return properties != null;
+ }
+ }
+
+ ///
+ public void Dispose()
+ {
+ _chainedDisposable.Dispose();
+ }
+ }
+}
diff --git a/src/Serilog.Extensions.Hosting/Hosting/SerilogLoggerFactory.cs b/src/Serilog.Extensions.Hosting/Extensions/Hosting/SerilogLoggerFactory.cs
similarity index 87%
rename from src/Serilog.Extensions.Hosting/Hosting/SerilogLoggerFactory.cs
rename to src/Serilog.Extensions.Hosting/Extensions/Hosting/SerilogLoggerFactory.cs
index 1c91166..1b100b9 100644
--- a/src/Serilog.Extensions.Hosting/Hosting/SerilogLoggerFactory.cs
+++ b/src/Serilog.Extensions.Hosting/Extensions/Hosting/SerilogLoggerFactory.cs
@@ -12,18 +12,25 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+using System;
+using System.ComponentModel;
using Microsoft.Extensions.Logging;
using Serilog.Debugging;
using Serilog.Extensions.Logging;
+// To line up with the convention used elsewhere in the *.Extensions libraries, this
+// should have been Serilog.Extensions.Hosting.
+// ReSharper disable once CheckNamespace
namespace Serilog.Hosting
{
///
/// Implements so that we can inject Serilog Logger.
///
+ [Obsolete("Replaced with Serilog.Extensions.Logging.SerilogLoggerFactory")]
+ [EditorBrowsable(EditorBrowsableState.Never)]
public class SerilogLoggerFactory : ILoggerFactory
{
- private readonly SerilogLoggerProvider _provider;
+ readonly SerilogLoggerProvider _provider;
///
/// Initializes a new instance of the class.
diff --git a/src/Serilog.Extensions.Hosting/IDiagnosticContext.cs b/src/Serilog.Extensions.Hosting/IDiagnosticContext.cs
new file mode 100644
index 0000000..468fa84
--- /dev/null
+++ b/src/Serilog.Extensions.Hosting/IDiagnosticContext.cs
@@ -0,0 +1,32 @@
+// Copyright 2019 Serilog Contributors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+namespace Serilog
+{
+ ///
+ /// Collects diagnostic information for packaging into wide events.
+ ///
+ public interface IDiagnosticContext
+ {
+ ///
+ /// Set the specified property on the current diagnostic context. The property will be collected
+ /// and attached to the event emitted at the completion of the context.
+ ///
+ /// The name of the property. Must be non-empty.
+ /// The property value.
+ /// If true, the value will be serialized as structured
+ /// data if possible; if false, the object will be recorded as a scalar or simple array.
+ void Set(string propertyName, object value, bool destructureObjects = false);
+ }
+}
diff --git a/src/Serilog.Extensions.Hosting/Serilog.Extensions.Hosting.csproj b/src/Serilog.Extensions.Hosting/Serilog.Extensions.Hosting.csproj
index b72ded6..1c84fd6 100644
--- a/src/Serilog.Extensions.Hosting/Serilog.Extensions.Hosting.csproj
+++ b/src/Serilog.Extensions.Hosting/Serilog.Extensions.Hosting.csproj
@@ -1,8 +1,8 @@
-
+
Serilog support for .NET Core logging in hosted services
- 2.0.0
+ 3.0.0
Microsoft;Serilog Contributors
netstandard2.0
true
@@ -14,15 +14,17 @@
Serilog.Extensions.Hosting
serilog;aspnet;aspnetcore;hosting
http://serilog.net/images/serilog-extension-nuget.png
- https://github.com/serilog/serilog-hosting
+ https://github.com/serilog/serilog-extensions-hosting
http://www.apache.org/licenses/LICENSE-2.0
+ https://github.com/serilog/serilog-extensions-hosting
+ git
false
Serilog
-
-
+
+
diff --git a/src/Serilog.Extensions.Hosting/SerilogHostBuilderExtensions.cs b/src/Serilog.Extensions.Hosting/SerilogHostBuilderExtensions.cs
index 804b8c3..306eadd 100644
--- a/src/Serilog.Extensions.Hosting/SerilogHostBuilderExtensions.cs
+++ b/src/Serilog.Extensions.Hosting/SerilogHostBuilderExtensions.cs
@@ -1,4 +1,4 @@
-// Copyright 2018 Serilog Contributors
+// Copyright 2019 Serilog Contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -15,8 +15,9 @@
using System;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
-using Serilog.Hosting;
using Microsoft.Extensions.DependencyInjection;
+using Serilog.Extensions.Hosting;
+using Serilog.Extensions.Logging;
namespace Serilog
{
@@ -33,48 +34,126 @@ public static class SerilogHostBuilderExtensions
/// When true, dispose when the framework disposes the provider. If the
/// logger is not specified but is true, the method will be
/// called on the static class instead.
- /// The (generic) host builder.
- public static IHostBuilder UseSerilog(this IHostBuilder builder, Serilog.ILogger logger = null, bool dispose = false)
+ /// A registered in the Serilog pipeline using the
+ /// WriteTo.Providers() configuration method, enabling other s to receive events. By
+ /// default, only Serilog sinks will receive events.
+ /// The host builder.
+ public static IHostBuilder UseSerilog(
+ this IHostBuilder builder,
+ ILogger logger = null,
+ bool dispose = false,
+ LoggerProviderCollection providers = null)
{
if (builder == null) throw new ArgumentNullException(nameof(builder));
- builder.ConfigureServices((context, collection) =>
- collection.AddSingleton(services => new SerilogLoggerFactory(logger, dispose)));
+
+ builder.ConfigureServices((_, collection) =>
+ {
+ if (providers != null)
+ {
+ collection.AddSingleton(services =>
+ {
+ var factory = new SerilogLoggerFactory(logger, dispose, providers);
+
+ foreach (var provider in services.GetServices())
+ factory.AddProvider(provider);
+
+ return factory;
+ });
+ }
+ else
+ {
+ collection.AddSingleton(services => new SerilogLoggerFactory(logger, dispose));
+ }
+
+ ConfigureServices(collection, logger);
+ });
+
return builder;
}
- ///
- /// Sets Serilog as the logging provider.
- ///
+ /// Sets Serilog as the logging provider.
///
/// A is supplied so that configuration and hosting information can be used.
/// The logger will be shut down when application services are disposed.
///
/// The host builder to configure.
- /// The delegate for configuring the that will be used to construct a .
+ /// The delegate for configuring the that will be used to construct a .
/// Indicates whether to preserve the value of .
- /// The (generic) host builder.
- public static IHostBuilder UseSerilog(this IHostBuilder builder, Action configureLogger, bool preserveStaticLogger = false)
+ /// By default, Serilog does not write events to s registered through
+ /// the Microsoft.Extensions.Logging API. Normally, equivalent Serilog sinks are used in place of providers. Specify
+ /// true to write events to all providers.
+ /// The host builder.
+ public static IHostBuilder UseSerilog(
+ this IHostBuilder builder,
+ Action configureLogger,
+ bool preserveStaticLogger = false,
+ bool writeToProviders = false)
{
if (builder == null) throw new ArgumentNullException(nameof(builder));
if (configureLogger == null) throw new ArgumentNullException(nameof(configureLogger));
+
builder.ConfigureServices((context, collection) =>
{
var loggerConfiguration = new LoggerConfiguration();
+
+ LoggerProviderCollection loggerProviders = null;
+ if (writeToProviders)
+ {
+ loggerProviders = new LoggerProviderCollection();
+ loggerConfiguration.WriteTo.Providers(loggerProviders);
+ }
+
configureLogger(context, loggerConfiguration);
var logger = loggerConfiguration.CreateLogger();
+
+ ILogger registeredLogger = null;
if (preserveStaticLogger)
{
- collection.AddSingleton(services => new SerilogLoggerFactory(logger, true));
+ registeredLogger = logger;
}
- else
+ else
{
// Passing a `null` logger to `SerilogLoggerFactory` results in disposal via
// `Log.CloseAndFlush()`, which additionally replaces the static logger with a no-op.
Log.Logger = logger;
- collection.AddSingleton(services => new SerilogLoggerFactory(null, true));
}
+
+ collection.AddSingleton(services =>
+ {
+ var factory = new SerilogLoggerFactory(registeredLogger, true, loggerProviders);
+
+ if (writeToProviders)
+ {
+ foreach (var provider in services.GetServices())
+ factory.AddProvider(provider);
+ }
+
+ return factory;
+ });
+
+ ConfigureServices(collection, logger);
});
return builder;
}
+
+ static void ConfigureServices(IServiceCollection collection, ILogger logger)
+ {
+ if (collection == null) throw new ArgumentNullException(nameof(collection));
+
+ if (logger != null)
+ {
+ // This won't (and shouldn't) take ownership of the logger.
+ collection.AddSingleton(logger);
+ }
+
+ // Registered to provide two services...
+ var diagnosticContext = new DiagnosticContext(logger);
+
+ // Consumed by e.g. middleware
+ collection.AddSingleton(diagnosticContext);
+
+ // Consumed by user code
+ collection.AddSingleton(diagnosticContext);
+ }
}
}
diff --git a/test/Serilog.Extensions.Hosting.Tests/DiagnosticContextTests.cs b/test/Serilog.Extensions.Hosting.Tests/DiagnosticContextTests.cs
new file mode 100644
index 0000000..c32f9ea
--- /dev/null
+++ b/test/Serilog.Extensions.Hosting.Tests/DiagnosticContextTests.cs
@@ -0,0 +1,57 @@
+using System;
+using System.Linq;
+using System.Threading.Tasks;
+using Serilog.Events;
+using Serilog.Extensions.Hosting.Tests.Support;
+using Xunit;
+
+// ReSharper disable PossibleNullReferenceException
+
+namespace Serilog.Extensions.Hosting.Tests
+{
+ public class DiagnosticContextTests
+ {
+ [Fact]
+ public void SetIsSafeWhenNoContextIsActive()
+ {
+ var dc = new DiagnosticContext(Some.Logger());
+ dc.Set(Some.String("name"), Some.Int32());
+ }
+
+ [Fact]
+ public async Task PropertiesAreCollectedInAnActiveContext()
+ {
+ var dc = new DiagnosticContext(Some.Logger());
+
+ var collector = dc.BeginCollection();
+ dc.Set(Some.String("first"), Some.Int32());
+ await Task.Delay(TimeSpan.FromMilliseconds(10));
+ dc.Set(Some.String("second"), Some.Int32());
+
+ Assert.True(collector.TryComplete(out var properties));
+ Assert.Equal(2, properties.Count());
+
+ Assert.False(collector.TryComplete(out _));
+
+ collector.Dispose();
+
+ dc.Set(Some.String("third"), Some.Int32());
+ Assert.False(collector.TryComplete(out _));
+ }
+
+ [Fact]
+ public void ExistingPropertiesCanBeUpdated()
+ {
+ var dc = new DiagnosticContext(Some.Logger());
+
+ var collector = dc.BeginCollection();
+ dc.Set("name", 10);
+ dc.Set("name", 20);
+
+ Assert.True(collector.TryComplete(out var properties));
+ var prop = Assert.Single(properties);
+ var scalar = Assert.IsType(prop.Value);
+ Assert.Equal(20, scalar.Value);
+ }
+ }
+}
diff --git a/test/Serilog.Extensions.Hosting.Tests/Serilog.Extensions.Hosting.Tests.csproj b/test/Serilog.Extensions.Hosting.Tests/Serilog.Extensions.Hosting.Tests.csproj
index bdbdbcc..bb9c750 100644
--- a/test/Serilog.Extensions.Hosting.Tests/Serilog.Extensions.Hosting.Tests.csproj
+++ b/test/Serilog.Extensions.Hosting.Tests/Serilog.Extensions.Hosting.Tests.csproj
@@ -1,7 +1,7 @@
- netcoreapp2.1
+ netcoreapp2.2
Serilog.Extensions.Hosting.Tests
../../assets/Serilog.snk
true
@@ -14,9 +14,12 @@
-
-
-
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
diff --git a/test/Serilog.Extensions.Hosting.Tests/SerilogHostBuilderExtensionsTests.cs b/test/Serilog.Extensions.Hosting.Tests/SerilogHostBuilderExtensionsTests.cs
deleted file mode 100644
index 3341f1d..0000000
--- a/test/Serilog.Extensions.Hosting.Tests/SerilogHostBuilderExtensionsTests.cs
+++ /dev/null
@@ -1,16 +0,0 @@
-// 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.
-
-using Xunit;
-
-namespace Serilog.Extensions.Hosting.Tests
-{
- public class SerilogHostBuilderExtensionsTests
- {
- [Fact]
- public void Todo()
- {
-
- }
- }
-}
\ No newline at end of file
diff --git a/test/Serilog.Extensions.Hosting.Tests/Support/Some.cs b/test/Serilog.Extensions.Hosting.Tests/Support/Some.cs
new file mode 100644
index 0000000..5137cef
--- /dev/null
+++ b/test/Serilog.Extensions.Hosting.Tests/Support/Some.cs
@@ -0,0 +1,21 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Threading;
+using Serilog.Events;
+
+namespace Serilog.Extensions.Hosting.Tests.Support
+{
+ static class Some
+ {
+ static int _next;
+
+ public static int Int32() => Interlocked.Increment(ref _next);
+
+ public static string String(string tag = null) => $"s_{tag}{Int32()}";
+
+ public static LogEventProperty LogEventProperty() => new LogEventProperty(String("name"), new ScalarValue(Int32()));
+
+ public static ILogger Logger() => new LoggerConfiguration().CreateLogger();
+ }
+}