diff --git a/.idea/.idea.serilog-sinks-console/.idea/.gitignore b/.idea/.idea.serilog-sinks-console/.idea/.gitignore
new file mode 100644
index 0000000..c239f02
--- /dev/null
+++ b/.idea/.idea.serilog-sinks-console/.idea/.gitignore
@@ -0,0 +1,13 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Rider ignored files
+/contentModel.xml
+/.idea.serilog-sinks-console.iml
+/modules.xml
+/projectSettingsUpdater.xml
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
+# Editor-based HTTP Client requests
+/httpRequests/
diff --git a/.idea/.idea.serilog-sinks-console/.idea/encodings.xml b/.idea/.idea.serilog-sinks-console/.idea/encodings.xml
new file mode 100644
index 0000000..df87cf9
--- /dev/null
+++ b/.idea/.idea.serilog-sinks-console/.idea/encodings.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/.idea/.idea.serilog-sinks-console/.idea/indexLayout.xml b/.idea/.idea.serilog-sinks-console/.idea/indexLayout.xml
new file mode 100644
index 0000000..7b08163
--- /dev/null
+++ b/.idea/.idea.serilog-sinks-console/.idea/indexLayout.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/.idea.serilog-sinks-console/.idea/vcs.xml b/.idea/.idea.serilog-sinks-console/.idea/vcs.xml
new file mode 100644
index 0000000..94a25f7
--- /dev/null
+++ b/.idea/.idea.serilog-sinks-console/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.travis.yml b/.travis.yml
index 10b9e57..2ed804c 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -3,9 +3,10 @@ language: csharp
matrix:
include:
- os: linux # Ubuntu 14.04
- dist: trusty
+ dist: xenial
sudo: required
- dotnet: 1.0.4
+ dotnet: 2.2.401
+ mono: none
group: edge
script:
diff --git a/Build.ps1 b/Build.ps1
index ee4117d..b0ac93a 100644
--- a/Build.ps1
+++ b/Build.ps1
@@ -1,9 +1,12 @@
-echo "build: Build started"
+Write-Output "build: Build started"
+
+& dotnet --info
+& dotnet --list-sdks
Push-Location $PSScriptRoot
if(Test-Path .\artifacts) {
- echo "build: Cleaning .\artifacts"
+ Write-Output "build: Cleaning .\artifacts"
Remove-Item .\artifacts -Force -Recurse
}
@@ -11,17 +14,17 @@ 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"]
$commitHash = $(git rev-parse --short HEAD)
$buildSuffix = @{ $true = "$($suffix)-$($commitHash)"; $false = "$($branch)-$($commitHash)" }[$suffix -ne ""]
-echo "build: Package version suffix is $suffix"
-echo "build: Build version suffix is $buildSuffix"
+Write-Output "build: Package version suffix is $suffix"
+Write-Output "build: Build version suffix is $buildSuffix"
-foreach ($src in ls src/*) {
+foreach ($src in Get-ChildItem src/*) {
Push-Location $src
- echo "build: Packaging project in $src"
+ Write-Output "build: Packaging project in $src"
& dotnet build -c Release --version-suffix=$buildSuffix
if ($suffix) {
@@ -34,10 +37,21 @@ foreach ($src in ls src/*) {
Pop-Location
}
-foreach ($test in ls test/*.Tests) {
+foreach ($sample in Get-ChildItem sample/*) {
+ Push-Location $sample
+
+ Write-Output "build: Testing project in $sample"
+
+ & dotnet build -c Release --version-suffix=$buildSuffix
+ if($LASTEXITCODE -ne 0) { exit 3 }
+
+ Pop-Location
+}
+
+foreach ($test in Get-ChildItem test/*.Tests) {
Push-Location $test
- echo "build: Testing project in $test"
+ Write-Output "build: Testing project in $test"
& dotnet test -c Release
if($LASTEXITCODE -ne 0) { exit 3 }
diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md
index caea530..8fbb2ed 100644
--- a/CODE_OF_CONDUCT.md
+++ b/CODE_OF_CONDUCT.md
@@ -1,3 +1,3 @@
# Code of Conduct
-Please refer to the [Serilog Code of Conduct](https://github.com/serilog/serilog/blob/dev/CONTRIBUTING.md) which covers all repositories within the Serilog Organisation.
\ No newline at end of file
+Please refer to the [Serilog Code of Conduct](https://github.com/serilog/serilog/blob/dev/CODE_OF_CONDUCT.md) which covers all repositories within the Serilog Organization.
diff --git a/README.md b/README.md
index 0ba2bc0..b380b56 100644
--- a/README.md
+++ b/README.md
@@ -6,8 +6,8 @@ A Serilog sink that writes log events to the Windows Console or an ANSI terminal
To use the console sink, first install the [NuGet package](https://nuget.org/packages/serilog.sinks.console):
-```powershell
-Install-Package Serilog.Sinks.Console
+```shell
+dotnet add package Serilog.Sinks.Console
```
Then enable the sink using `WriteTo.Console()`:
@@ -64,14 +64,14 @@ The default template, shown in the example above, uses built-in properties like
The sink can write JSON output instead of plain text. `CompactJsonFormatter` or `RenderedCompactJsonFormatter` from [Serilog.Formatting.Compact](https://github.com/serilog/serilog-formatting-compact) is recommended:
-```powershell
-Install-Package Serilog.Formatting.Compact
+```shell
+dotnet add package Serilog.Formatting.Compact
```
Pass a formatter to the `Console()` configuration method:
```csharp
- .WriteTo.Console(new CompactJsonFormatter())
+ .WriteTo.Console(new RenderedCompactJsonFormatter())
```
Output theming is not available when custom formatters are used.
@@ -80,8 +80,8 @@ Output theming is not available when custom formatters are used.
To use the console sink with the [Serilog.Settings.AppSettings](https://github.com/serilog/serilog-settings-appsettings) package, first install that package if you haven't already done so:
-```powershell
-Install-Package Serilog.Settings.AppSettings
+```shell
+dotnet add package Serilog.Settings.AppSettings
```
Instead of configuring the logger in code, call `ReadFrom.AppSettings()`:
@@ -101,12 +101,21 @@ In your application's `App.config` or `Web.config` file, specify the console sin
```
+To configure the console sink with a different theme and include the `SourceContext` in the output, change your `App.config`/`Web.config` to:
+```xml
+
+
+
+
+
+```
+
### JSON `appsettings.json` configuration
To use the console sink with _Microsoft.Extensions.Configuration_, for example with ASP.NET Core or .NET Core, use the [Serilog.Settings.Configuration](https://github.com/serilog/serilog-settings-configuration) package. First install that package if you have not already done so:
-```powershell
-Install-Package Serilog.Settings.Configuration
+```shell
+dotnet add package Serilog.Settings.Configuration
```
Instead of configuring the sink directly in code, call `ReadFrom.Configuration()`:
@@ -122,7 +131,6 @@ var logger = new LoggerConfiguration()
```
In your `appsettings.json` file, under the `Serilog` node, :
-
```json
{
"Serilog": {
@@ -131,18 +139,23 @@ In your `appsettings.json` file, under the `Serilog` node, :
}
```
-### Upgrading from _Serilog.Sinks.Console_ 2.x
-
-To achieve output identical to version 2 of this sink, specify a formatter and output template explicitly:
-
-```csharp
- .WriteTo.Console(new MessageTemplateTextFormatter(
- "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level}] {Message}{NewLine}{Exception}",
- null))
+To configure the console sink with a different theme and include the `SourceContext` in the output, change your `appsettings.json` to:
+```json
+{
+ "Serilog": {
+ "WriteTo": [
+ {
+ "Name": "Console",
+ "Args": {
+ "theme": "Serilog.Sinks.SystemConsole.Themes.AnsiConsoleTheme::Code, Serilog.Sinks.Console",
+ "outputTemplate": "[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj} {NewLine}{Exception}"
+ }
+ }
+ ]
+ }
+}
```
-This will bypass theming and use Serilog's built-in message template formatting.
-
### Contributing
Would you like to help make the Serilog console sink even better? We keep a list of issues that are approachable for newcomers under the [up-for-grabs](https://github.com/serilog/serilog-sinks-console/issues?labels=up-for-grabs&state=open) label. Before starting work on a pull request, we suggest commenting on, or raising, an issue on the issue tracker so that we can help and coordinate efforts. For more details check out our [contributing guide](CONTRIBUTING.md).
@@ -155,7 +168,7 @@ When contributing please keep in mind our [Code of Conduct](CODE_OF_CONDUCT.md).
Branch | AppVeyor | Travis
------------- | ------------- |-------------
dev | [![Build status](https://ci.appveyor.com/api/projects/status/w1w3m1wyk3in1c96/branch/dev?svg=true)](https://ci.appveyor.com/project/serilog/serilog-sinks-console/branch/dev) | [![Build Status](https://travis-ci.org/serilog/serilog-sinks-console.svg?branch=dev)](https://travis-ci.org/serilog/serilog-sinks-console)
-master | [![Build status](https://ci.appveyor.com/api/projects/status/w1w3m1wyk3in1c96/branch/master?svg=true)](https://ci.appveyor.com/project/serilog/serilog-sinks-console/branch/master) | [![Build Status](https://travis-ci.org/serilog/serilog-sinks-console.svg?branch=master)](https://travis-ci.org/serilog/serilog-sinks-console)
+main | [![Build status](https://ci.appveyor.com/api/projects/status/w1w3m1wyk3in1c96/branch/main?svg=true)](https://ci.appveyor.com/project/serilog/serilog-sinks-console/branch/main) | [![Build Status](https://travis-ci.org/serilog/serilog-sinks-console.svg?branch=main)](https://travis-ci.org/serilog/serilog-sinks-console)
-_Copyright © 2017 Serilog Contributors - Provided under the [Apache License, Version 2.0](http://apache.org/licenses/LICENSE-2.0.html)._
+_Copyright © Serilog Contributors - Provided under the [Apache License, Version 2.0](http://apache.org/licenses/LICENSE-2.0.html)._
diff --git a/appveyor.yml b/appveyor.yml
index 7df8c2f..3c57f91 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -1,7 +1,6 @@
version: '{build}'
skip_tags: true
-image: Visual Studio 2017
-configuration: Release
+image: Visual Studio 2019
test: off
build_script:
- ps: ./Build.ps1
@@ -10,14 +9,14 @@ artifacts:
deploy:
- provider: NuGet
api_key:
- secure: nvZ/z+pMS91b3kG4DgfES5AcmwwGoBYQxr9kp4XiJHj25SAlgdIxFx++1N0lFH2x
+ secure: rbdBqxBpLt4MkB+mrDOYNDOd8aVZ1zMkysaVNAXNKnC41FYifzX3l9LM8DCrUWU5
skip_symbols: true
on:
- branch: /^(master|dev)$/
+ branch: /^(main|dev)$/
- provider: GitHub
auth_token:
secure: p4LpVhBKxGS5WqucHxFQ5c7C8cP74kbNB0Z8k9Oxx/PMaDQ1+ibmoexNqVU5ZlmX
artifact: /Serilog.*\.nupkg/
tag: v$(appveyor_build_version)
on:
- branch: master
+ branch: main
diff --git a/assets/icon.png b/assets/icon.png
new file mode 100644
index 0000000..9bf45a3
Binary files /dev/null and b/assets/icon.png differ
diff --git a/build.sh b/build.sh
index b2dc450..64d87ea 100755
--- a/build.sh
+++ b/build.sh
@@ -5,15 +5,14 @@ dotnet --info
dotnet restore
for path in src/**/*.csproj; do
- dotnet build -f netstandard1.3 -c Release ${path}
- dotnet build -f netcoreapp1.1 -c Release ${path}
+ dotnet build -f netstandard2.0 -c Release ${path}
done
for path in test/*.Tests/*.csproj; do
- dotnet test -f netcoreapp1.1 -c Release ${path}
+ dotnet test -f netcoreapp2.2 -c Release ${path}
done
for path in sample/ConsoleDemo/*.csproj; do
- dotnet build -f netcoreapp1.1 -c Release ${path}
- dotnet run -f netcoreapp1.1 --project ${path}
+ dotnet build -f netcoreapp2.2 -c Release ${path}
+ dotnet run -f netcoreapp2.2 --project ${path}
done
diff --git a/sample/ConsoleDemo/ConsoleDemo.csproj b/sample/ConsoleDemo/ConsoleDemo.csproj
index 3a2245a..81b1a1f 100644
--- a/sample/ConsoleDemo/ConsoleDemo.csproj
+++ b/sample/ConsoleDemo/ConsoleDemo.csproj
@@ -2,7 +2,7 @@
Exe
- netcoreapp1.1;net45
+ netcoreapp2.1;netcoreapp2.2;netcoreapp3.0;netcoreapp3.1;net452;net462;net472;net48;net5.0
diff --git a/sample/ConsoleDemo/Program.cs b/sample/ConsoleDemo/Program.cs
index dcd9d75..73d50d8 100644
--- a/sample/ConsoleDemo/Program.cs
+++ b/sample/ConsoleDemo/Program.cs
@@ -1,11 +1,11 @@
using Serilog;
+using Serilog.Sinks.SystemConsole.Themes;
using System;
using System.Threading;
-using Serilog.Sinks.SystemConsole.Themes;
namespace ConsoleDemo
{
- public class Program
+ public static class Program
{
public static void Main()
{
diff --git a/sample/SyncWritesDemo/Program.cs b/sample/SyncWritesDemo/Program.cs
new file mode 100644
index 0000000..5120393
--- /dev/null
+++ b/sample/SyncWritesDemo/Program.cs
@@ -0,0 +1,57 @@
+using Serilog;
+using Serilog.Sinks.SystemConsole.Themes;
+using System;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace SyncWritesDemo
+{
+ public static class Program
+ {
+ public static void Main(string[] args)
+ {
+ Console.WriteLine("A sample of how to sync writes to the console sink.");
+
+ if (args != null && args.Length == 1)
+ {
+ switch (args[0])
+ {
+ case "--sync-root-default":
+ SystemConsoleSyncTest(syncRootForLogger1: null, syncRootForLogger2: null);
+ return;
+ case "--sync-root-separate":
+ SystemConsoleSyncTest(syncRootForLogger1: new object(), syncRootForLogger2: new object());
+ return;
+ case "--sync-root-same":
+ var sameSyncRoot = new object();
+ SystemConsoleSyncTest(syncRootForLogger1: sameSyncRoot, syncRootForLogger2: sameSyncRoot);
+ return;
+ }
+ }
+
+ Console.WriteLine("Expecting one of the following arguments:{0}--sync-root-default{0}--sync-root-separate{0}--sync-root-same", Environment.NewLine);
+ }
+
+ static void SystemConsoleSyncTest(object syncRootForLogger1, object syncRootForLogger2)
+ {
+ var logger1 = new LoggerConfiguration()
+ .MinimumLevel.Verbose()
+ .Enrich.WithProperty("Logger", "logger1")
+ .WriteTo.Console(theme: SystemConsoleTheme.Literate, syncRoot: syncRootForLogger1)
+ .CreateLogger();
+
+ var logger2 = new LoggerConfiguration()
+ .MinimumLevel.Verbose()
+ .Enrich.WithProperty("Logger", "logger2")
+ .WriteTo.Console(theme: SystemConsoleTheme.Literate, syncRoot: syncRootForLogger2)
+ .CreateLogger();
+
+ var options = new ParallelOptions { MaxDegreeOfParallelism = 8 };
+ Parallel.For(0, 1000, options, (i, loopState) =>
+ {
+ var logger = (i % 2 == 0) ? logger1 : logger2;
+ logger.Information("Event {Iteration} generated by {ThreadId}", i, Thread.CurrentThread.ManagedThreadId);
+ });
+ }
+ }
+}
diff --git a/sample/SyncWritesDemo/SyncWritesDemo.csproj b/sample/SyncWritesDemo/SyncWritesDemo.csproj
new file mode 100644
index 0000000..a72595e
--- /dev/null
+++ b/sample/SyncWritesDemo/SyncWritesDemo.csproj
@@ -0,0 +1,12 @@
+
+
+
+ Exe
+ net5.0
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/serilog-sinks-console.sln b/serilog-sinks-console.sln
index 6a6a8d4..e223156 100644
--- a/serilog-sinks-console.sln
+++ b/serilog-sinks-console.sln
@@ -13,7 +13,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "assets", "assets", "{E9D1B5
Build.ps1 = Build.ps1
CHANGES.md = CHANGES.md
LICENSE = LICENSE
- NuGet.Config = NuGet.Config
README.md = README.md
assets\Serilog.snk = assets\Serilog.snk
EndProjectSection
@@ -26,7 +25,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Serilog.Sinks.Console.Tests
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "sample", "sample", "{CF817664-4CEC-4B6A-9C57-A0D687757D82}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ConsoleDemo", "sample\ConsoleDemo\ConsoleDemo.csproj", "{DBF4907A-63A2-4895-8DEF-59F90C20380B}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ConsoleDemo", "sample\ConsoleDemo\ConsoleDemo.csproj", "{DBF4907A-63A2-4895-8DEF-59F90C20380B}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SyncWritesDemo", "sample\SyncWritesDemo\SyncWritesDemo.csproj", "{633AE0AD-C9D4-440D-874A-C0F4632DB75F}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -46,6 +47,10 @@ Global
{DBF4907A-63A2-4895-8DEF-59F90C20380B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DBF4907A-63A2-4895-8DEF-59F90C20380B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DBF4907A-63A2-4895-8DEF-59F90C20380B}.Release|Any CPU.Build.0 = Release|Any CPU
+ {633AE0AD-C9D4-440D-874A-C0F4632DB75F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {633AE0AD-C9D4-440D-874A-C0F4632DB75F}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {633AE0AD-C9D4-440D-874A-C0F4632DB75F}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {633AE0AD-C9D4-440D-874A-C0F4632DB75F}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -54,5 +59,9 @@ Global
{866A028E-27DB-49A0-AC78-E5FEF247C099} = {037440DE-440B-4129-9F7A-09B42D00397E}
{1D56534C-4009-42C2-A573-789CAE6B8AA9} = {7D0692CD-F95D-4BF9-8C63-B4A1C078DF23}
{DBF4907A-63A2-4895-8DEF-59F90C20380B} = {CF817664-4CEC-4B6A-9C57-A0D687757D82}
+ {633AE0AD-C9D4-440D-874A-C0F4632DB75F} = {CF817664-4CEC-4B6A-9C57-A0D687757D82}
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {43C32ED4-D39A-4E27-AE99-7BB8C883833C}
EndGlobalSection
EndGlobal
diff --git a/src/Serilog.Sinks.Console/ConsoleLoggerConfigurationExtensions.cs b/src/Serilog.Sinks.Console/ConsoleLoggerConfigurationExtensions.cs
index 8c6fce8..e55f7a2 100644
--- a/src/Serilog.Sinks.Console/ConsoleLoggerConfigurationExtensions.cs
+++ b/src/Serilog.Sinks.Console/ConsoleLoggerConfigurationExtensions.cs
@@ -12,14 +12,14 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-using System;
using Serilog.Configuration;
using Serilog.Core;
using Serilog.Events;
using Serilog.Formatting;
using Serilog.Sinks.SystemConsole;
-using Serilog.Sinks.SystemConsole.Themes;
using Serilog.Sinks.SystemConsole.Output;
+using Serilog.Sinks.SystemConsole.Themes;
+using System;
namespace Serilog
{
@@ -28,6 +28,7 @@ namespace Serilog
///
public static class ConsoleLoggerConfigurationExtensions
{
+ static readonly object DefaultSyncRoot = new object();
const string DefaultConsoleOutputTemplate = "[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj}{NewLine}{Exception}";
///
@@ -36,33 +37,43 @@ public static class ConsoleLoggerConfigurationExtensions
/// Logger sink configuration.
/// The minimum level for
/// events passed through the sink. Ignored when is specified.
- /// A switch allowing the pass-through minimum level
- /// to be changed at runtime.
/// A message template describing the format used to write to the sink.
- /// the default is "[{Timestamp:HH:mm:ss} {Level:u3}] {Message}{NewLine}{Exception}"
.
+ /// The default is "[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj}{NewLine}{Exception}"
.
+ /// An object that will be used to `lock` (sync) access to the console output. If you specify this, you
+ /// will have the ability to lock on this object, and guarantee that the console sink will not be about to output anything while
+ /// the lock is held.
/// Supplies culture-specific formatting information, or null.
+ /// A switch allowing the pass-through minimum level
+ /// to be changed at runtime.
/// Specifies the level at which events will be written to standard error.
/// The theme to apply to the styled output. If not specified,
/// uses .
+ /// Applies the selected or default theme even when output redirection is detected.
/// Configuration object allowing method chaining.
+ /// When is null
+ /// When is null
public static LoggerConfiguration Console(
this LoggerSinkConfiguration sinkConfiguration,
LogEventLevel restrictedToMinimumLevel = LevelAlias.Minimum,
string outputTemplate = DefaultConsoleOutputTemplate,
- IFormatProvider formatProvider = null,
- LoggingLevelSwitch levelSwitch = null,
+ IFormatProvider? formatProvider = null,
+ LoggingLevelSwitch? levelSwitch = null,
LogEventLevel? standardErrorFromLevel = null,
- ConsoleTheme theme = null)
+ ConsoleTheme? theme = null,
+ bool applyThemeToRedirectedOutput = false,
+ object? syncRoot = null)
{
- if (sinkConfiguration == null) throw new ArgumentNullException(nameof(sinkConfiguration));
- if (outputTemplate == null) throw new ArgumentNullException(nameof(outputTemplate));
+ if (sinkConfiguration is null) throw new ArgumentNullException(nameof(sinkConfiguration));
+ if (outputTemplate is null) throw new ArgumentNullException(nameof(outputTemplate));
- var appliedTheme = System.Console.IsOutputRedirected || System.Console.IsErrorRedirected ?
+ var appliedTheme = !applyThemeToRedirectedOutput && (System.Console.IsOutputRedirected || System.Console.IsErrorRedirected) ?
ConsoleTheme.None :
theme ?? SystemConsoleThemes.Literate;
+ syncRoot ??= DefaultSyncRoot;
+
var formatter = new OutputTemplateRenderer(appliedTheme, outputTemplate, formatProvider);
- return sinkConfiguration.Sink(new ConsoleSink(appliedTheme, formatter, standardErrorFromLevel), restrictedToMinimumLevel, levelSwitch);
+ return sinkConfiguration.Sink(new ConsoleSink(appliedTheme, formatter, standardErrorFromLevel, syncRoot), restrictedToMinimumLevel, levelSwitch);
}
///
@@ -71,23 +82,31 @@ public static LoggerConfiguration Console(
/// Logger sink configuration.
/// Controls the rendering of log events into text, for example to log JSON. To
/// control plain text formatting, use the overload that accepts an output template.
+ /// An object that will be used to `lock` (sync) access to the console output. If you specify this, you
+ /// will have the ability to lock on this object, and guarantee that the console sink will not be about to output anything while
+ /// the lock is held.
/// The minimum level for
/// events passed through the sink. Ignored when is specified.
/// A switch allowing the pass-through minimum level
/// to be changed at runtime.
/// Specifies the level at which events will be written to standard error.
/// Configuration object allowing method chaining.
+ /// When is null
+ /// When is null
public static LoggerConfiguration Console(
this LoggerSinkConfiguration sinkConfiguration,
ITextFormatter formatter,
LogEventLevel restrictedToMinimumLevel = LevelAlias.Minimum,
- LoggingLevelSwitch levelSwitch = null,
- LogEventLevel? standardErrorFromLevel = null)
+ LoggingLevelSwitch? levelSwitch = null,
+ LogEventLevel? standardErrorFromLevel = null,
+ object? syncRoot = null)
{
- if (sinkConfiguration == null) throw new ArgumentNullException(nameof(sinkConfiguration));
- if (formatter == null) throw new ArgumentNullException(nameof(formatter));
+ if (sinkConfiguration is null) throw new ArgumentNullException(nameof(sinkConfiguration));
+ if (formatter is null) throw new ArgumentNullException(nameof(formatter));
+
+ syncRoot ??= DefaultSyncRoot;
- return sinkConfiguration.Sink(new ConsoleSink(ConsoleTheme.None, formatter, standardErrorFromLevel), restrictedToMinimumLevel, levelSwitch);
+ return sinkConfiguration.Sink(new ConsoleSink(ConsoleTheme.None, formatter, standardErrorFromLevel, syncRoot), restrictedToMinimumLevel, levelSwitch);
}
}
}
diff --git a/src/Serilog.Sinks.Console/Properties/AssemblyInfo.cs b/src/Serilog.Sinks.Console/Properties/AssemblyInfo.cs
index 3ecea3a..34ef2fa 100644
--- a/src/Serilog.Sinks.Console/Properties/AssemblyInfo.cs
+++ b/src/Serilog.Sinks.Console/Properties/AssemblyInfo.cs
@@ -17,7 +17,7 @@
[assembly: CLSCompliant(true)]
-[assembly: InternalsVisibleTo("Serilog.Sinks.SystemConsole.Tests, PublicKey=" +
+[assembly: InternalsVisibleTo("Serilog.Sinks.Console.Tests, PublicKey=" +
"0024000004800000940000000602000000240000525341310004000001000100fb8d13fd344a1c" +
"6fe0fe83ef33c1080bf30690765bc6eb0df26ebfdf8f21670c64265b30db09f73a0dea5b3db4c9" +
"d18dbf6d5a25af5ce9016f281014d79dc3b4201ac646c451830fc7e61a2dfd633d34c39f87b818" +
diff --git a/src/Serilog.Sinks.Console/Serilog.Sinks.Console.csproj b/src/Serilog.Sinks.Console/Serilog.Sinks.Console.csproj
index 693b36a..4a93619 100644
--- a/src/Serilog.Sinks.Console/Serilog.Sinks.Console.csproj
+++ b/src/Serilog.Sinks.Console/Serilog.Sinks.Console.csproj
@@ -1,55 +1,37 @@
-
+
A Serilog sink that writes log events to the console/terminal.
- 3.1.1
+ 4.0.0
Serilog Contributors
- net45;netstandard1.3;netcoreapp1.1
- Serilog.Sinks.Console
+ net45;netstandard1.3;netstandard2.0;net5.0
+ 8.0
+ enable
../../assets/Serilog.snk
true
true
- Serilog.Sinks.Console
serilog;console;terminal
- http://serilog.net/images/serilog-sink-nuget.png
+ icon.png
https://github.com/serilog/serilog-sinks-console
- https://www.apache.org/licenses/LICENSE-2.0
- true
- true
+ Apache-2.0
+ https://github.com/serilog/serilog-sinks-console
+ git
true
-
- true
True
Serilog
-
- $(DefineConstants);PINVOKE
-
-
-
- $(DefineConstants);PINVOKE;RUNTIME_INFORMATION
+
+ $(DefineConstants);RUNTIME_INFORMATION
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
-
diff --git a/src/Serilog.Sinks.Console/Sinks/SystemConsole/ConsoleSink.cs b/src/Serilog.Sinks.Console/Sinks/SystemConsole/ConsoleSink.cs
index 0aedb49..e1c1bea 100644
--- a/src/Serilog.Sinks.Console/Sinks/SystemConsole/ConsoleSink.cs
+++ b/src/Serilog.Sinks.Console/Sinks/SystemConsole/ConsoleSink.cs
@@ -12,14 +12,14 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-using System;
-using System.IO;
-using System.Text;
using Serilog.Core;
using Serilog.Events;
-using Serilog.Sinks.SystemConsole.Themes;
using Serilog.Formatting;
using Serilog.Sinks.SystemConsole.Platform;
+using Serilog.Sinks.SystemConsole.Themes;
+using System;
+using System.IO;
+using System.Text;
namespace Serilog.Sinks.SystemConsole
{
@@ -28,9 +28,9 @@ class ConsoleSink : ILogEventSink
readonly LogEventLevel? _standardErrorFromLevel;
readonly ConsoleTheme _theme;
readonly ITextFormatter _formatter;
- readonly object _syncRoot = new object();
+ readonly object _syncRoot;
- const int DefaultWriteBuffer = 256;
+ const int DefaultWriteBufferCapacity = 256;
static ConsoleSink()
{
@@ -40,11 +40,13 @@ static ConsoleSink()
public ConsoleSink(
ConsoleTheme theme,
ITextFormatter formatter,
- LogEventLevel? standardErrorFromLevel)
+ LogEventLevel? standardErrorFromLevel,
+ object syncRoot)
{
_standardErrorFromLevel = standardErrorFromLevel;
_theme = theme ?? throw new ArgumentNullException(nameof(theme));
_formatter = formatter;
+ _syncRoot = syncRoot ?? throw new ArgumentNullException(nameof(syncRoot));
}
public void Emit(LogEvent logEvent)
@@ -56,11 +58,12 @@ public void Emit(LogEvent logEvent)
// buffered write here and have no effect when the line is actually written out.
if (_theme.CanBuffer)
{
- var buffer = new StringWriter(new StringBuilder(DefaultWriteBuffer));
+ var buffer = new StringWriter(new StringBuilder(DefaultWriteBufferCapacity));
_formatter.Format(logEvent, buffer);
+ var formattedLogEventText = buffer.ToString();
lock (_syncRoot)
{
- output.Write(buffer.ToString());
+ output.Write(formattedLogEventText);
output.Flush();
}
}
@@ -76,7 +79,7 @@ public void Emit(LogEvent logEvent)
TextWriter SelectOutputStream(LogEventLevel logEventLevel)
{
- if (!_standardErrorFromLevel.HasValue)
+ if (_standardErrorFromLevel is null)
return Console.Out;
return logEventLevel < _standardErrorFromLevel ? Console.Out : Console.Error;
diff --git a/src/Serilog.Sinks.Console/Sinks/SystemConsole/Formatting/ThemedDisplayValueFormatter.cs b/src/Serilog.Sinks.Console/Sinks/SystemConsole/Formatting/ThemedDisplayValueFormatter.cs
index e6b3659..3093bd6 100644
--- a/src/Serilog.Sinks.Console/Sinks/SystemConsole/Formatting/ThemedDisplayValueFormatter.cs
+++ b/src/Serilog.Sinks.Console/Sinks/SystemConsole/Formatting/ThemedDisplayValueFormatter.cs
@@ -22,9 +22,9 @@ namespace Serilog.Sinks.SystemConsole.Formatting
{
class ThemedDisplayValueFormatter : ThemedValueFormatter
{
- readonly IFormatProvider _formatProvider;
+ readonly IFormatProvider? _formatProvider;
- public ThemedDisplayValueFormatter(ConsoleTheme theme, IFormatProvider formatProvider)
+ public ThemedDisplayValueFormatter(ConsoleTheme theme, IFormatProvider? formatProvider)
: base(theme)
{
_formatProvider = formatProvider;
@@ -37,14 +37,14 @@ public override ThemedValueFormatter SwitchTheme(ConsoleTheme theme)
protected override int VisitScalarValue(ThemedValueFormatterState state, ScalarValue scalar)
{
- if (scalar == null)
+ if (scalar is null)
throw new ArgumentNullException(nameof(scalar));
return FormatLiteralValue(scalar, state.Output, state.Format);
}
protected override int VisitSequenceValue(ThemedValueFormatterState state, SequenceValue sequence)
{
- if (sequence == null)
+ if (sequence is null)
throw new ArgumentNullException(nameof(sequence));
var count = 0;
@@ -52,12 +52,14 @@ protected override int VisitSequenceValue(ThemedValueFormatterState state, Seque
using (ApplyStyle(state.Output, ConsoleThemeStyle.TertiaryText, ref count))
state.Output.Write('[');
- var delim = "";
+ var delim = string.Empty;
for (var index = 0; index < sequence.Elements.Count; ++index)
{
if (delim.Length != 0)
+ {
using (ApplyStyle(state.Output, ConsoleThemeStyle.TertiaryText, ref count))
state.Output.Write(delim);
+ }
delim = ", ";
Visit(state, sequence.Elements[index]);
@@ -84,12 +86,14 @@ protected override int VisitStructureValue(ThemedValueFormatterState state, Stru
using (ApplyStyle(state.Output, ConsoleThemeStyle.TertiaryText, ref count))
state.Output.Write('{');
- var delim = "";
+ var delim = string.Empty;
for (var index = 0; index < structure.Properties.Count; ++index)
{
if (delim.Length != 0)
+ {
using (ApplyStyle(state.Output, ConsoleThemeStyle.TertiaryText, ref count))
state.Output.Write(delim);
+ }
delim = ", ";
@@ -117,12 +121,14 @@ protected override int VisitDictionaryValue(ThemedValueFormatterState state, Dic
using (ApplyStyle(state.Output, ConsoleThemeStyle.TertiaryText, ref count))
state.Output.Write('{');
- var delim = "";
+ var delim = string.Empty;
foreach (var element in dictionary.Elements)
{
if (delim.Length != 0)
+ {
using (ApplyStyle(state.Output, ConsoleThemeStyle.TertiaryText, ref count))
state.Output.Write(delim);
+ }
delim = ", ";
@@ -144,12 +150,12 @@ protected override int VisitDictionaryValue(ThemedValueFormatterState state, Dic
return count;
}
- public int FormatLiteralValue(ScalarValue scalar, TextWriter output, string format)
+ public int FormatLiteralValue(ScalarValue scalar, TextWriter output, string? format)
{
var value = scalar.Value;
var count = 0;
- if (value == null)
+ if (value is null)
{
using (ApplyStyle(output, ConsoleThemeStyle.Null, ref count))
output.Write("null");
diff --git a/src/Serilog.Sinks.Console/Sinks/SystemConsole/Formatting/ThemedJsonValueFormatter.cs b/src/Serilog.Sinks.Console/Sinks/SystemConsole/Formatting/ThemedJsonValueFormatter.cs
index a8c7ec8..ec6d5d1 100644
--- a/src/Serilog.Sinks.Console/Sinks/SystemConsole/Formatting/ThemedJsonValueFormatter.cs
+++ b/src/Serilog.Sinks.Console/Sinks/SystemConsole/Formatting/ThemedJsonValueFormatter.cs
@@ -24,9 +24,9 @@ namespace Serilog.Sinks.SystemConsole.Formatting
class ThemedJsonValueFormatter : ThemedValueFormatter
{
readonly ThemedDisplayValueFormatter _displayFormatter;
- readonly IFormatProvider _formatProvider;
+ readonly IFormatProvider? _formatProvider;
- public ThemedJsonValueFormatter(ConsoleTheme theme, IFormatProvider formatProvider)
+ public ThemedJsonValueFormatter(ConsoleTheme theme, IFormatProvider? formatProvider)
: base(theme)
{
_displayFormatter = new ThemedDisplayValueFormatter(theme, formatProvider);
@@ -40,7 +40,7 @@ public override ThemedValueFormatter SwitchTheme(ConsoleTheme theme)
protected override int VisitScalarValue(ThemedValueFormatterState state, ScalarValue scalar)
{
- if (scalar == null)
+ if (scalar is null)
throw new ArgumentNullException(nameof(scalar));
// At the top level, for scalar values, use "display" rendering.
@@ -60,12 +60,14 @@ protected override int VisitSequenceValue(ThemedValueFormatterState state, Seque
using (ApplyStyle(state.Output, ConsoleThemeStyle.TertiaryText, ref count))
state.Output.Write('[');
- var delim = "";
+ var delim = string.Empty;
for (var index = 0; index < sequence.Elements.Count; ++index)
{
if (delim.Length != 0)
+ {
using (ApplyStyle(state.Output, ConsoleThemeStyle.TertiaryText, ref count))
state.Output.Write(delim);
+ }
delim = ", ";
Visit(state.Nest(), sequence.Elements[index]);
@@ -84,12 +86,14 @@ protected override int VisitStructureValue(ThemedValueFormatterState state, Stru
using (ApplyStyle(state.Output, ConsoleThemeStyle.TertiaryText, ref count))
state.Output.Write('{');
- var delim = "";
+ var delim = string.Empty;
for (var index = 0; index < structure.Properties.Count; ++index)
{
if (delim.Length != 0)
+ {
using (ApplyStyle(state.Output, ConsoleThemeStyle.TertiaryText, ref count))
state.Output.Write(delim);
+ }
delim = ", ";
@@ -132,12 +136,14 @@ protected override int VisitDictionaryValue(ThemedValueFormatterState state, Dic
using (ApplyStyle(state.Output, ConsoleThemeStyle.TertiaryText, ref count))
state.Output.Write('{');
- var delim = "";
+ var delim = string.Empty;
foreach (var element in dictionary.Elements)
{
if (delim.Length != 0)
+ {
using (ApplyStyle(state.Output, ConsoleThemeStyle.TertiaryText, ref count))
state.Output.Write(delim);
+ }
delim = ", ";
@@ -148,7 +154,7 @@ protected override int VisitDictionaryValue(ThemedValueFormatterState state, Dic
: ConsoleThemeStyle.Scalar;
using (ApplyStyle(state.Output, style, ref count))
- JsonValueFormatter.WriteQuotedJsonString((element.Key.Value ?? "null").ToString(), state.Output);
+ JsonValueFormatter.WriteQuotedJsonString((element.Key.Value ?? "null").ToString() ?? "", state.Output);
using (ApplyStyle(state.Output, ConsoleThemeStyle.TertiaryText, ref count))
state.Output.Write(": ");
@@ -242,7 +248,7 @@ int FormatLiteralValue(ScalarValue scalar, TextWriter output)
}
using (ApplyStyle(output, ConsoleThemeStyle.Scalar, ref count))
- JsonValueFormatter.WriteQuotedJsonString(value.ToString(), output);
+ JsonValueFormatter.WriteQuotedJsonString(value.ToString() ?? "", output);
return count;
}
diff --git a/src/Serilog.Sinks.Console/Sinks/SystemConsole/Formatting/ThemedValueFormatter.cs b/src/Serilog.Sinks.Console/Sinks/SystemConsole/Formatting/ThemedValueFormatter.cs
index ea780e0..34be339 100644
--- a/src/Serilog.Sinks.Console/Sinks/SystemConsole/Formatting/ThemedValueFormatter.cs
+++ b/src/Serilog.Sinks.Console/Sinks/SystemConsole/Formatting/ThemedValueFormatter.cs
@@ -34,7 +34,7 @@ protected StyleReset ApplyStyle(TextWriter output, ConsoleThemeStyle style, ref
return _theme.Apply(output, style, ref invisibleCharacterCount);
}
- public int Format(LogEventPropertyValue value, TextWriter output, string format, bool literalTopLevel = false)
+ public int Format(LogEventPropertyValue value, TextWriter output, string? format, bool literalTopLevel = false)
{
return Visit(new ThemedValueFormatterState { Output = output, Format = format, IsTopLevel = literalTopLevel }, value);
}
diff --git a/src/Serilog.Sinks.Console/Sinks/SystemConsole/Formatting/ThemedValueFormatterState.cs b/src/Serilog.Sinks.Console/Sinks/SystemConsole/Formatting/ThemedValueFormatterState.cs
index 1c720c0..a5f5a86 100644
--- a/src/Serilog.Sinks.Console/Sinks/SystemConsole/Formatting/ThemedValueFormatterState.cs
+++ b/src/Serilog.Sinks.Console/Sinks/SystemConsole/Formatting/ThemedValueFormatterState.cs
@@ -19,12 +19,9 @@ namespace Serilog.Sinks.SystemConsole.Formatting
struct ThemedValueFormatterState
{
public TextWriter Output;
- public string Format;
+ public string? Format;
public bool IsTopLevel;
- public ThemedValueFormatterState Nest()
- {
- return new ThemedValueFormatterState {Output = Output};
- }
+ public ThemedValueFormatterState Nest() => new ThemedValueFormatterState { Output = Output };
}
}
diff --git a/src/Serilog.Sinks.Console/Sinks/SystemConsole/Output/EventPropertyTokenRenderer.cs b/src/Serilog.Sinks.Console/Sinks/SystemConsole/Output/EventPropertyTokenRenderer.cs
index e2ea4dc..d4fe511 100644
--- a/src/Serilog.Sinks.Console/Sinks/SystemConsole/Output/EventPropertyTokenRenderer.cs
+++ b/src/Serilog.Sinks.Console/Sinks/SystemConsole/Output/EventPropertyTokenRenderer.cs
@@ -25,9 +25,9 @@ class EventPropertyTokenRenderer : OutputTemplateTokenRenderer
{
readonly ConsoleTheme _theme;
readonly PropertyToken _token;
- readonly IFormatProvider _formatProvider;
+ readonly IFormatProvider? _formatProvider;
- public EventPropertyTokenRenderer(ConsoleTheme theme, PropertyToken token, IFormatProvider formatProvider)
+ public EventPropertyTokenRenderer(ConsoleTheme theme, PropertyToken token, IFormatProvider? formatProvider)
{
_theme = theme;
_token = token;
@@ -37,10 +37,9 @@ public EventPropertyTokenRenderer(ConsoleTheme theme, PropertyToken token, IForm
public override void Render(LogEvent logEvent, TextWriter output)
{
// If a property is missing, don't render anything (message templates render the raw token here).
- LogEventPropertyValue propertyValue;
- if (!logEvent.Properties.TryGetValue(_token.PropertyName, out propertyValue))
+ if (!logEvent.Properties.TryGetValue(_token.PropertyName, out var propertyValue))
{
- Padding.Apply(output, "", _token.Alignment);
+ Padding.Apply(output, string.Empty, _token.Alignment);
return;
}
@@ -63,7 +62,7 @@ public override void Render(LogEvent logEvent, TextWriter output)
if (_token.Alignment.HasValue)
{
- var str = writer.ToString();
+ var str = writer.ToString()!;
Padding.Apply(output, str, _token.Alignment);
}
}
diff --git a/src/Serilog.Sinks.Console/Sinks/SystemConsole/Output/ExceptionTokenRenderer.cs b/src/Serilog.Sinks.Console/Sinks/SystemConsole/Output/ExceptionTokenRenderer.cs
index 31aa4c2..b3db007 100644
--- a/src/Serilog.Sinks.Console/Sinks/SystemConsole/Output/ExceptionTokenRenderer.cs
+++ b/src/Serilog.Sinks.Console/Sinks/SystemConsole/Output/ExceptionTokenRenderer.cs
@@ -34,11 +34,11 @@ public override void Render(LogEvent logEvent, TextWriter output)
{
// Padding is never applied by this renderer.
- if (logEvent.Exception == null)
+ if (logEvent.Exception is null)
return;
var lines = new StringReader(logEvent.Exception.ToString());
- string nextLine;
+ string? nextLine;
while ((nextLine = lines.ReadLine()) != null)
{
var style = nextLine.StartsWith(StackFrameLinePrefix) ? ConsoleThemeStyle.SecondaryText : ConsoleThemeStyle.Text;
diff --git a/src/Serilog.Sinks.Console/Sinks/SystemConsole/Output/LevelOutputFormat.cs b/src/Serilog.Sinks.Console/Sinks/SystemConsole/Output/LevelOutputFormat.cs
index 1d4f59f..d703bb8 100644
--- a/src/Serilog.Sinks.Console/Sinks/SystemConsole/Output/LevelOutputFormat.cs
+++ b/src/Serilog.Sinks.Console/Sinks/SystemConsole/Output/LevelOutputFormat.cs
@@ -25,36 +25,39 @@ namespace Serilog.Sinks.SystemConsole.Output
///
static class LevelOutputFormat
{
- static readonly string[][] TitleCaseLevelMap = {
- new []{ "V", "Vb", "Vrb", "Verb" },
- new []{ "D", "De", "Dbg", "Dbug" },
- new []{ "I", "In", "Inf", "Info" },
- new []{ "W", "Wn", "Wrn", "Warn" },
- new []{ "E", "Er", "Err", "Eror" },
- new []{ "F", "Fa", "Ftl", "Fatl" }
+ static readonly string[][] TitleCaseLevelMap =
+ {
+ new[] { "V", "Vb", "Vrb", "Verb" },
+ new[] { "D", "De", "Dbg", "Dbug" },
+ new[] { "I", "In", "Inf", "Info" },
+ new[] { "W", "Wn", "Wrn", "Warn" },
+ new[] { "E", "Er", "Err", "Eror" },
+ new[] { "F", "Fa", "Ftl", "Fatl" },
};
- static readonly string[][] LowercaseLevelMap = {
- new []{ "v", "vb", "vrb", "verb" },
- new []{ "d", "de", "dbg", "dbug" },
- new []{ "i", "in", "inf", "info" },
- new []{ "w", "wn", "wrn", "warn" },
- new []{ "e", "er", "err", "eror" },
- new []{ "f", "fa", "ftl", "fatl" }
+ static readonly string[][] LowercaseLevelMap =
+ {
+ new[] { "v", "vb", "vrb", "verb" },
+ new[] { "d", "de", "dbg", "dbug" },
+ new[] { "i", "in", "inf", "info" },
+ new[] { "w", "wn", "wrn", "warn" },
+ new[] { "e", "er", "err", "eror" },
+ new[] { "f", "fa", "ftl", "fatl" },
};
- static readonly string[][] UppercaseLevelMap = {
- new []{ "V", "VB", "VRB", "VERB" },
- new []{ "D", "DE", "DBG", "DBUG" },
- new []{ "I", "IN", "INF", "INFO" },
- new []{ "W", "WN", "WRN", "WARN" },
- new []{ "E", "ER", "ERR", "EROR" },
- new []{ "F", "FA", "FTL", "FATL" }
+ static readonly string[][] UppercaseLevelMap =
+ {
+ new[] { "V", "VB", "VRB", "VERB" },
+ new[] { "D", "DE", "DBG", "DBUG" },
+ new[] { "I", "IN", "INF", "INFO" },
+ new[] { "W", "WN", "WRN", "WARN" },
+ new[] { "E", "ER", "ERR", "EROR" },
+ new[] { "F", "FA", "FTL", "FATL" },
};
- public static string GetLevelMoniker(LogEventLevel value, string format = null)
+ public static string GetLevelMoniker(LogEventLevel value, string? format = null)
{
- if (format == null || format.Length != 2 && format.Length != 3)
+ if (format is null || format.Length != 2 && format.Length != 3)
return Casing.Format(value.ToString(), format);
// Using int.Parse() here requires allocating a string to exclude the first character prefix.
@@ -78,7 +81,7 @@ public static string GetLevelMoniker(LogEventLevel value, string format = null)
}
var index = (int)value;
- if (index >= 0 && index <= (int) LogEventLevel.Fatal)
+ if (index >= 0 && index <= (int)LogEventLevel.Fatal)
{
switch (format[0])
{
diff --git a/src/Serilog.Sinks.Console/Sinks/SystemConsole/Output/LevelTokenRenderer.cs b/src/Serilog.Sinks.Console/Sinks/SystemConsole/Output/LevelTokenRenderer.cs
index 466632d..9cb9ed1 100644
--- a/src/Serilog.Sinks.Console/Sinks/SystemConsole/Output/LevelTokenRenderer.cs
+++ b/src/Serilog.Sinks.Console/Sinks/SystemConsole/Output/LevelTokenRenderer.cs
@@ -25,6 +25,7 @@ class LevelTokenRenderer : OutputTemplateTokenRenderer
{
readonly ConsoleTheme _theme;
readonly PropertyToken _levelToken;
+
static readonly Dictionary Levels = new Dictionary
{
{ LogEventLevel.Verbose, ConsoleThemeStyle.LevelVerbose },
@@ -32,7 +33,7 @@ class LevelTokenRenderer : OutputTemplateTokenRenderer
{ LogEventLevel.Information, ConsoleThemeStyle.LevelInformation },
{ LogEventLevel.Warning, ConsoleThemeStyle.LevelWarning },
{ LogEventLevel.Error, ConsoleThemeStyle.LevelError },
- { LogEventLevel.Fatal, ConsoleThemeStyle.LevelFatal }
+ { LogEventLevel.Fatal, ConsoleThemeStyle.LevelFatal },
};
public LevelTokenRenderer(ConsoleTheme theme, PropertyToken levelToken)
@@ -41,10 +42,6 @@ public LevelTokenRenderer(ConsoleTheme theme, PropertyToken levelToken)
_levelToken = levelToken;
}
- protected LevelTokenRenderer()
- {
- }
-
public override void Render(LogEvent logEvent, TextWriter output)
{
var moniker = LevelOutputFormat.GetLevelMoniker(logEvent.Level, _levelToken.Format);
diff --git a/src/Serilog.Sinks.Console/Sinks/SystemConsole/Output/MessageTemplateOutputTokenRenderer.cs b/src/Serilog.Sinks.Console/Sinks/SystemConsole/Output/MessageTemplateOutputTokenRenderer.cs
index 6ca5fb4..9f0997b 100644
--- a/src/Serilog.Sinks.Console/Sinks/SystemConsole/Output/MessageTemplateOutputTokenRenderer.cs
+++ b/src/Serilog.Sinks.Console/Sinks/SystemConsole/Output/MessageTemplateOutputTokenRenderer.cs
@@ -28,10 +28,11 @@ class MessageTemplateOutputTokenRenderer : OutputTemplateTokenRenderer
readonly PropertyToken _token;
readonly ThemedMessageTemplateRenderer _renderer;
- public MessageTemplateOutputTokenRenderer(ConsoleTheme theme, PropertyToken token, IFormatProvider formatProvider)
+ public MessageTemplateOutputTokenRenderer(ConsoleTheme theme, PropertyToken token, IFormatProvider? formatProvider)
{
_theme = theme ?? throw new ArgumentNullException(nameof(theme));
_token = token ?? throw new ArgumentNullException(nameof(token));
+
bool isLiteral = false, isJson = false;
if (token.Format != null)
@@ -54,7 +55,7 @@ public MessageTemplateOutputTokenRenderer(ConsoleTheme theme, PropertyToken toke
public override void Render(LogEvent logEvent, TextWriter output)
{
- if (_token.Alignment == null || !_theme.CanBuffer)
+ if (_token.Alignment is null || !_theme.CanBuffer)
{
_renderer.Render(logEvent.MessageTemplate, logEvent.Properties, output);
return;
diff --git a/src/Serilog.Sinks.Console/Sinks/SystemConsole/Output/OutputTemplateRenderer.cs b/src/Serilog.Sinks.Console/Sinks/SystemConsole/Output/OutputTemplateRenderer.cs
index c2ef206..c62ab67 100644
--- a/src/Serilog.Sinks.Console/Sinks/SystemConsole/Output/OutputTemplateRenderer.cs
+++ b/src/Serilog.Sinks.Console/Sinks/SystemConsole/Output/OutputTemplateRenderer.cs
@@ -27,9 +27,9 @@ class OutputTemplateRenderer : ITextFormatter
{
readonly OutputTemplateTokenRenderer[] _renderers;
- public OutputTemplateRenderer(ConsoleTheme theme, string outputTemplate, IFormatProvider formatProvider)
+ public OutputTemplateRenderer(ConsoleTheme theme, string outputTemplate, IFormatProvider? formatProvider)
{
- if (outputTemplate == null) throw new ArgumentNullException(nameof(outputTemplate));
+ if (outputTemplate is null) throw new ArgumentNullException(nameof(outputTemplate));
var template = new MessageTemplateParser().Parse(outputTemplate);
var renderers = new List();
@@ -77,8 +77,8 @@ public OutputTemplateRenderer(ConsoleTheme theme, string outputTemplate, IFormat
public void Format(LogEvent logEvent, TextWriter output)
{
- if (logEvent == null) throw new ArgumentNullException(nameof(logEvent));
- if (output == null) throw new ArgumentNullException(nameof(output));
+ if (logEvent is null) throw new ArgumentNullException(nameof(logEvent));
+ if (output is null) throw new ArgumentNullException(nameof(output));
foreach (var renderer in _renderers)
renderer.Render(logEvent, output);
diff --git a/src/Serilog.Sinks.Console/Sinks/SystemConsole/Output/PropertiesTokenRenderer.cs b/src/Serilog.Sinks.Console/Sinks/SystemConsole/Output/PropertiesTokenRenderer.cs
index 8bfe16e..8e48fd0 100644
--- a/src/Serilog.Sinks.Console/Sinks/SystemConsole/Output/PropertiesTokenRenderer.cs
+++ b/src/Serilog.Sinks.Console/Sinks/SystemConsole/Output/PropertiesTokenRenderer.cs
@@ -31,11 +31,12 @@ class PropertiesTokenRenderer : OutputTemplateTokenRenderer
readonly PropertyToken _token;
readonly ThemedValueFormatter _valueFormatter;
- public PropertiesTokenRenderer(ConsoleTheme theme, PropertyToken token, MessageTemplate outputTemplate, IFormatProvider formatProvider)
+ public PropertiesTokenRenderer(ConsoleTheme theme, PropertyToken token, MessageTemplate outputTemplate, IFormatProvider? formatProvider)
{
_outputTemplate = outputTemplate;
_theme = theme ?? throw new ArgumentNullException(nameof(theme));
_token = token ?? throw new ArgumentNullException(nameof(token));
+
var isJson = false;
if (token.Format != null)
@@ -61,7 +62,7 @@ public override void Render(LogEvent logEvent, TextWriter output)
var value = new StructureValue(included);
- if (_token.Alignment == null || !_theme.CanBuffer)
+ if (_token.Alignment is null || !_theme.CanBuffer)
{
_valueFormatter.Format(value, output, null);
return;
diff --git a/src/Serilog.Sinks.Console/Sinks/SystemConsole/Output/TimestampTokenRenderer.cs b/src/Serilog.Sinks.Console/Sinks/SystemConsole/Output/TimestampTokenRenderer.cs
index 409a230..c763279 100644
--- a/src/Serilog.Sinks.Console/Sinks/SystemConsole/Output/TimestampTokenRenderer.cs
+++ b/src/Serilog.Sinks.Console/Sinks/SystemConsole/Output/TimestampTokenRenderer.cs
@@ -25,9 +25,9 @@ class TimestampTokenRenderer : OutputTemplateTokenRenderer
{
readonly ConsoleTheme _theme;
readonly PropertyToken _token;
- readonly IFormatProvider _formatProvider;
+ readonly IFormatProvider? _formatProvider;
- public TimestampTokenRenderer(ConsoleTheme theme, PropertyToken token, IFormatProvider formatProvider)
+ public TimestampTokenRenderer(ConsoleTheme theme, PropertyToken token, IFormatProvider? formatProvider)
{
_theme = theme;
_token = token;
@@ -43,8 +43,10 @@ public override void Render(LogEvent logEvent, TextWriter output)
var _ = 0;
using (_theme.Apply(output, ConsoleThemeStyle.SecondaryText, ref _))
{
- if (_token.Alignment == null)
+ if (_token.Alignment is null)
+ {
sv.Render(output, _token.Format, _formatProvider);
+ }
else
{
var buffer = new StringWriter();
diff --git a/src/Serilog.Sinks.Console/Sinks/SystemConsole/Platform/WindowsConsole.cs b/src/Serilog.Sinks.Console/Sinks/SystemConsole/Platform/WindowsConsole.cs
index f50af78..fce3ecf 100644
--- a/src/Serilog.Sinks.Console/Sinks/SystemConsole/Platform/WindowsConsole.cs
+++ b/src/Serilog.Sinks.Console/Sinks/SystemConsole/Platform/WindowsConsole.cs
@@ -12,18 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#if PINVOKE
using System;
using System.Runtime.InteropServices;
-#endif
namespace Serilog.Sinks.SystemConsole.Platform
{
static class WindowsConsole
{
-#if PINVOKE
public static void EnableVirtualTerminalProcessing()
- {
+ {
#if RUNTIME_INFORMATION
if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
return;
@@ -49,11 +46,6 @@ public static void EnableVirtualTerminalProcessing()
static extern bool GetConsoleMode(IntPtr handle, out uint mode);
[DllImport("kernel32.dll", SetLastError = true)]
- static extern bool SetConsoleMode(IntPtr handle, uint mode);
-#else
- public static void EnableVirtualTerminalProcessing()
- {
- }
-#endif
+ static extern bool SetConsoleMode(IntPtr handle, uint mode);
}
}
diff --git a/src/Serilog.Sinks.Console/Sinks/SystemConsole/Rendering/Casing.cs b/src/Serilog.Sinks.Console/Sinks/SystemConsole/Rendering/Casing.cs
index 27e866c..66ce179 100644
--- a/src/Serilog.Sinks.Console/Sinks/SystemConsole/Rendering/Casing.cs
+++ b/src/Serilog.Sinks.Console/Sinks/SystemConsole/Rendering/Casing.cs
@@ -18,10 +18,12 @@ static class Casing
{
///
/// Apply upper or lower casing to when is provided.
- /// Returns when no or invalid format provided
+ /// Returns when no or invalid format provided.
///
- /// The provided with formatting applied
- public static string Format(string value, string format = null)
+ /// Provided string for formatting.
+ /// Format string.
+ /// The provided with formatting applied.
+ public static string Format(string value, string? format = null)
{
switch (format)
{
diff --git a/src/Serilog.Sinks.Console/Sinks/SystemConsole/Rendering/Padding.cs b/src/Serilog.Sinks.Console/Sinks/SystemConsole/Rendering/Padding.cs
index 4d6451e..12d2595 100644
--- a/src/Serilog.Sinks.Console/Sinks/SystemConsole/Rendering/Padding.cs
+++ b/src/Serilog.Sinks.Console/Sinks/SystemConsole/Rendering/Padding.cs
@@ -24,9 +24,12 @@ static class Padding
///
/// Writes the provided value to the output, applying direction-based padding when is provided.
///
+ /// Output object to write result.
+ /// Provided value.
+ /// The alignment settings to apply when rendering .
public static void Apply(TextWriter output, string value, Alignment? alignment)
{
- if (!alignment.HasValue || value.Length >= alignment.Value.Width)
+ if (alignment is null || value.Length >= alignment.Value.Width)
{
output.Write(value);
return;
diff --git a/src/Serilog.Sinks.Console/Sinks/SystemConsole/Rendering/ThemedMessageTemplateRenderer.cs b/src/Serilog.Sinks.Console/Sinks/SystemConsole/Rendering/ThemedMessageTemplateRenderer.cs
index 9fa9ca4..c4ef9f1 100644
--- a/src/Serilog.Sinks.Console/Sinks/SystemConsole/Rendering/ThemedMessageTemplateRenderer.cs
+++ b/src/Serilog.Sinks.Console/Sinks/SystemConsole/Rendering/ThemedMessageTemplateRenderer.cs
@@ -66,8 +66,7 @@ int RenderTextToken(TextToken tt, TextWriter output)
int RenderPropertyToken(PropertyToken pt, IReadOnlyDictionary properties, TextWriter output)
{
- LogEventPropertyValue propertyValue;
- if (!properties.TryGetValue(pt.PropertyName, out propertyValue))
+ if (!properties.TryGetValue(pt.PropertyName, out var propertyValue))
{
var count = 0;
using (_theme.Apply(output, ConsoleThemeStyle.Invalid, ref count))
@@ -103,11 +102,12 @@ int RenderPropertyToken(PropertyToken pt, IReadOnlyDictionary= pt.Alignment.Value.Width)
{
return RenderValue(_theme, _valueFormatter, propertyValue, output, pt.Format);
@@ -116,15 +116,15 @@ int RenderAlignedPropertyTokenUnbuffered(PropertyToken pt, TextWriter output, Lo
if (pt.Alignment.Value.Direction == AlignmentDirection.Left)
{
var invisible = RenderValue(_theme, _valueFormatter, propertyValue, output, pt.Format);
- Padding.Apply(output, "", pt.Alignment.Value.Widen(-valueLength));
+ Padding.Apply(output, string.Empty, pt.Alignment.Value.Widen(-valueLength));
return invisible;
}
- Padding.Apply(output, "", pt.Alignment.Value.Widen(-valueLength));
+ Padding.Apply(output, string.Empty, pt.Alignment.Value.Widen(-valueLength));
return RenderValue(_theme, _valueFormatter, propertyValue, output, pt.Format);
}
- int RenderValue(ConsoleTheme theme, ThemedValueFormatter valueFormatter, LogEventPropertyValue propertyValue, TextWriter output, string format)
+ int RenderValue(ConsoleTheme theme, ThemedValueFormatter valueFormatter, LogEventPropertyValue propertyValue, TextWriter output, string? format)
{
if (_isLiteral && propertyValue is ScalarValue sv && sv.Value is string)
{
diff --git a/src/Serilog.Sinks.Console/Sinks/SystemConsole/Themes/AnsiConsoleTheme.cs b/src/Serilog.Sinks.Console/Sinks/SystemConsole/Themes/AnsiConsoleTheme.cs
index 77345da..ea95ee3 100644
--- a/src/Serilog.Sinks.Console/Sinks/SystemConsole/Themes/AnsiConsoleTheme.cs
+++ b/src/Serilog.Sinks.Console/Sinks/SystemConsole/Themes/AnsiConsoleTheme.cs
@@ -36,7 +36,7 @@ public class AnsiConsoleTheme : ConsoleTheme
public static AnsiConsoleTheme Grayscale { get; } = AnsiConsoleThemes.Grayscale;
///
- /// A theme in the syle of the original Serilog.Sinks.Literate.
+ /// A theme in the style of the original Serilog.Sinks.Literate.
///
public static AnsiConsoleTheme Literate { get; } = AnsiConsoleThemes.Literate;
@@ -47,9 +47,10 @@ public class AnsiConsoleTheme : ConsoleTheme
/// Construct a theme given a set of styles.
///
/// Styles to apply within the theme.
+ /// When is null
public AnsiConsoleTheme(IReadOnlyDictionary styles)
{
- if (styles == null) throw new ArgumentNullException(nameof(styles));
+ if (styles is null) throw new ArgumentNullException(nameof(styles));
_styles = styles.ToDictionary(kv => kv.Key, kv => kv.Value);
}
diff --git a/src/Serilog.Sinks.Console/Sinks/SystemConsole/Themes/AnsiConsoleThemes.cs b/src/Serilog.Sinks.Console/Sinks/SystemConsole/Themes/AnsiConsoleThemes.cs
index 997143f..5cbb051 100644
--- a/src/Serilog.Sinks.Console/Sinks/SystemConsole/Themes/AnsiConsoleThemes.cs
+++ b/src/Serilog.Sinks.Console/Sinks/SystemConsole/Themes/AnsiConsoleThemes.cs
@@ -36,7 +36,7 @@ static class AnsiConsoleThemes
[ConsoleThemeStyle.LevelInformation] = "\x1b[38;5;0015m",
[ConsoleThemeStyle.LevelWarning] = "\x1b[38;5;0011m",
[ConsoleThemeStyle.LevelError] = "\x1b[38;5;0015m\x1b[48;5;0196m",
- [ConsoleThemeStyle.LevelFatal] = "\x1b[38;5;0015m\x1b[48;5;0196m"
+ [ConsoleThemeStyle.LevelFatal] = "\x1b[38;5;0015m\x1b[48;5;0196m",
});
public static AnsiConsoleTheme Grayscale { get; } = new AnsiConsoleTheme(
@@ -54,10 +54,10 @@ static class AnsiConsoleThemes
[ConsoleThemeStyle.Scalar] = "\x1b[1m\x1b[37;1m",
[ConsoleThemeStyle.LevelVerbose] = "\x1b[30;1m",
[ConsoleThemeStyle.LevelDebug] = "\x1b[30;1m",
- [ConsoleThemeStyle.LevelInformation] ="\x1b[37;1m",
+ [ConsoleThemeStyle.LevelInformation] = "\x1b[37;1m",
[ConsoleThemeStyle.LevelWarning] = "\x1b[37;1m\x1b[47m",
[ConsoleThemeStyle.LevelError] = "\x1b[30m\x1b[47m",
- [ConsoleThemeStyle.LevelFatal] = "\x1b[30m\x1b[47m"
+ [ConsoleThemeStyle.LevelFatal] = "\x1b[30m\x1b[47m",
});
public static AnsiConsoleTheme Code { get; } = new AnsiConsoleTheme(
@@ -65,7 +65,7 @@ static class AnsiConsoleThemes
{
[ConsoleThemeStyle.Text] = "\x1b[38;5;0253m",
[ConsoleThemeStyle.SecondaryText] = "\x1b[38;5;0246m",
- [ConsoleThemeStyle.TertiaryText] = "\x1b[38;5;0253m",
+ [ConsoleThemeStyle.TertiaryText] = "\x1b[38;5;0242m",
[ConsoleThemeStyle.Invalid] = "\x1b[33;1m",
[ConsoleThemeStyle.Null] = "\x1b[38;5;0038m",
[ConsoleThemeStyle.Name] = "\x1b[38;5;0081m",
@@ -78,7 +78,7 @@ static class AnsiConsoleThemes
[ConsoleThemeStyle.LevelInformation] = "\x1b[37;1m",
[ConsoleThemeStyle.LevelWarning] = "\x1b[38;5;0229m",
[ConsoleThemeStyle.LevelError] = "\x1b[38;5;0197m\x1b[48;5;0238m",
- [ConsoleThemeStyle.LevelFatal] = "\x1b[38;5;0197m\x1b[48;5;0238m"
+ [ConsoleThemeStyle.LevelFatal] = "\x1b[38;5;0197m\x1b[48;5;0238m",
});
}
}
diff --git a/src/Serilog.Sinks.Console/Sinks/SystemConsole/Themes/ConsoleTheme.cs b/src/Serilog.Sinks.Console/Sinks/SystemConsole/Themes/ConsoleTheme.cs
index d220cdb..b3921bf 100644
--- a/src/Serilog.Sinks.Console/Sinks/SystemConsole/Themes/ConsoleTheme.cs
+++ b/src/Serilog.Sinks.Console/Sinks/SystemConsole/Themes/ConsoleTheme.cs
@@ -37,13 +37,13 @@ public abstract class ConsoleTheme
///
/// Output destination.
/// Style to apply.
- ///
+ /// The number of characters written to .
public abstract int Set(TextWriter output, ConsoleThemeStyle style);
///
/// Reset the output to un-styled colors.
///
- /// The output.
+ /// Output destination.
public abstract void Reset(TextWriter output);
///
diff --git a/src/Serilog.Sinks.Console/Sinks/SystemConsole/Themes/ConsoleThemeStyle.cs b/src/Serilog.Sinks.Console/Sinks/SystemConsole/Themes/ConsoleThemeStyle.cs
index 2106801..69d231f 100644
--- a/src/Serilog.Sinks.Console/Sinks/SystemConsole/Themes/ConsoleThemeStyle.cs
+++ b/src/Serilog.Sinks.Console/Sinks/SystemConsole/Themes/ConsoleThemeStyle.cs
@@ -33,7 +33,7 @@ public enum ConsoleThemeStyle
SecondaryText,
///
- /// De-emphasized text, for example literal text in output templates and
+ /// De-emphasized text, for example literal text in output templates and
/// punctuation used when writing structured data.
///
TertiaryText,
@@ -63,9 +63,9 @@ public enum ConsoleThemeStyle
/// Numbers.
///
Number,
-
+
///
- /// values.
+ /// values.
///
Boolean,
@@ -75,9 +75,10 @@ public enum ConsoleThemeStyle
Scalar,
///
- /// Unrecogized literal values, e.g. instances.
+ /// Unrecognized literal values, e.g. instances.
///
- [Obsolete("Use ConsoleThemeStyle.Scalar instead"), EditorBrowsable(EditorBrowsableState.Never)]
+ [Obsolete("Use ConsoleThemeStyle.Scalar instead")]
+ [EditorBrowsable(EditorBrowsableState.Never)]
Object = Scalar,
///
@@ -108,6 +109,6 @@ public enum ConsoleThemeStyle
///
/// Level indicator.
///
- LevelFatal
+ LevelFatal,
}
}
\ No newline at end of file
diff --git a/src/Serilog.Sinks.Console/Sinks/SystemConsole/Themes/EmptyConsoleTheme.cs b/src/Serilog.Sinks.Console/Sinks/SystemConsole/Themes/EmptyConsoleTheme.cs
index 7be5ef4..de74f8c 100644
--- a/src/Serilog.Sinks.Console/Sinks/SystemConsole/Themes/EmptyConsoleTheme.cs
+++ b/src/Serilog.Sinks.Console/Sinks/SystemConsole/Themes/EmptyConsoleTheme.cs
@@ -20,12 +20,9 @@ class EmptyConsoleTheme : ConsoleTheme
{
public override bool CanBuffer => true;
- protected override int ResetCharCount { get; } = 0;
+ protected override int ResetCharCount { get; }
- public override int Set(TextWriter output, ConsoleThemeStyle style)
- {
- return 0;
- }
+ public override int Set(TextWriter output, ConsoleThemeStyle style) => 0;
public override void Reset(TextWriter output)
{
diff --git a/src/Serilog.Sinks.Console/Sinks/SystemConsole/Themes/SystemConsoleTheme.cs b/src/Serilog.Sinks.Console/Sinks/SystemConsole/Themes/SystemConsoleTheme.cs
index 828cf07..a4518c8 100644
--- a/src/Serilog.Sinks.Console/Sinks/SystemConsole/Themes/SystemConsoleTheme.cs
+++ b/src/Serilog.Sinks.Console/Sinks/SystemConsole/Themes/SystemConsoleTheme.cs
@@ -31,7 +31,7 @@ public class SystemConsoleTheme : ConsoleTheme
public static SystemConsoleTheme Grayscale { get; } = SystemConsoleThemes.Grayscale;
///
- /// A theme in the syle of the original Serilog.Sinks.Literate.
+ /// A theme in the style of the original Serilog.Sinks.Literate.
///
public static SystemConsoleTheme Literate { get; } = SystemConsoleThemes.Literate;
@@ -40,31 +40,30 @@ public class SystemConsoleTheme : ConsoleTheme
///
public static SystemConsoleTheme Colored { get; } = SystemConsoleThemes.Colored;
- readonly IReadOnlyDictionary _styles;
-
///
/// Construct a theme given a set of styles.
///
/// Styles to apply within the theme.
+ /// When is null
public SystemConsoleTheme(IReadOnlyDictionary styles)
{
- if (styles == null) throw new ArgumentNullException(nameof(styles));
- _styles = styles.ToDictionary(kv => kv.Key, kv => kv.Value);
+ if (styles is null) throw new ArgumentNullException(nameof(styles));
+ Styles = styles.ToDictionary(kv => kv.Key, kv => kv.Value);
}
///
- public IReadOnlyDictionary Styles => _styles;
+ public IReadOnlyDictionary Styles { get; }
///
public override bool CanBuffer => false;
///
- protected override int ResetCharCount { get; } = 0;
+ protected override int ResetCharCount { get; }
///
public override int Set(TextWriter output, ConsoleThemeStyle style)
{
- if (_styles.TryGetValue(style, out var wcts))
+ if (Styles.TryGetValue(style, out var wcts))
{
if (wcts.Foreground.HasValue)
Console.ForegroundColor = wcts.Foreground.Value;
diff --git a/src/Serilog.Sinks.Console/Sinks/SystemConsole/Themes/SystemConsoleThemes.cs b/src/Serilog.Sinks.Console/Sinks/SystemConsole/Themes/SystemConsoleThemes.cs
index 5e77b39..5e202f9 100644
--- a/src/Serilog.Sinks.Console/Sinks/SystemConsole/Themes/SystemConsoleThemes.cs
+++ b/src/Serilog.Sinks.Console/Sinks/SystemConsole/Themes/SystemConsoleThemes.cs
@@ -37,7 +37,7 @@ static class SystemConsoleThemes
[ConsoleThemeStyle.LevelInformation] = new SystemConsoleThemeStyle { Foreground = ConsoleColor.White },
[ConsoleThemeStyle.LevelWarning] = new SystemConsoleThemeStyle { Foreground = ConsoleColor.Yellow },
[ConsoleThemeStyle.LevelError] = new SystemConsoleThemeStyle { Foreground = ConsoleColor.White, Background = ConsoleColor.Red },
- [ConsoleThemeStyle.LevelFatal] = new SystemConsoleThemeStyle { Foreground = ConsoleColor.White, Background = ConsoleColor.Red }
+ [ConsoleThemeStyle.LevelFatal] = new SystemConsoleThemeStyle { Foreground = ConsoleColor.White, Background = ConsoleColor.Red },
});
public static SystemConsoleTheme Grayscale { get; } = new SystemConsoleTheme(
@@ -46,7 +46,7 @@ static class SystemConsoleThemes
[ConsoleThemeStyle.Text] = new SystemConsoleThemeStyle { Foreground = ConsoleColor.White },
[ConsoleThemeStyle.SecondaryText] = new SystemConsoleThemeStyle { Foreground = ConsoleColor.Gray },
[ConsoleThemeStyle.TertiaryText] = new SystemConsoleThemeStyle { Foreground = ConsoleColor.DarkGray },
- [ConsoleThemeStyle.Invalid] = new SystemConsoleThemeStyle { Foreground = ConsoleColor.White, Background = ConsoleColor.DarkGray},
+ [ConsoleThemeStyle.Invalid] = new SystemConsoleThemeStyle { Foreground = ConsoleColor.White, Background = ConsoleColor.DarkGray },
[ConsoleThemeStyle.Null] = new SystemConsoleThemeStyle { Foreground = ConsoleColor.White },
[ConsoleThemeStyle.Name] = new SystemConsoleThemeStyle { Foreground = ConsoleColor.Gray },
[ConsoleThemeStyle.String] = new SystemConsoleThemeStyle { Foreground = ConsoleColor.White },
@@ -56,9 +56,9 @@ static class SystemConsoleThemes
[ConsoleThemeStyle.LevelVerbose] = new SystemConsoleThemeStyle { Foreground = ConsoleColor.DarkGray },
[ConsoleThemeStyle.LevelDebug] = new SystemConsoleThemeStyle { Foreground = ConsoleColor.DarkGray },
[ConsoleThemeStyle.LevelInformation] = new SystemConsoleThemeStyle { Foreground = ConsoleColor.White },
- [ConsoleThemeStyle.LevelWarning] = new SystemConsoleThemeStyle { Foreground = ConsoleColor.White, Background = ConsoleColor.DarkGray},
+ [ConsoleThemeStyle.LevelWarning] = new SystemConsoleThemeStyle { Foreground = ConsoleColor.White, Background = ConsoleColor.DarkGray },
[ConsoleThemeStyle.LevelError] = new SystemConsoleThemeStyle { Foreground = ConsoleColor.Black, Background = ConsoleColor.White },
- [ConsoleThemeStyle.LevelFatal] = new SystemConsoleThemeStyle { Foreground = ConsoleColor.Black, Background = ConsoleColor.White }
+ [ConsoleThemeStyle.LevelFatal] = new SystemConsoleThemeStyle { Foreground = ConsoleColor.Black, Background = ConsoleColor.White },
});
public static SystemConsoleTheme Colored { get; } = new SystemConsoleTheme(
@@ -79,7 +79,7 @@ static class SystemConsoleThemes
[ConsoleThemeStyle.LevelInformation] = new SystemConsoleThemeStyle { Foreground = ConsoleColor.White, Background = ConsoleColor.Blue },
[ConsoleThemeStyle.LevelWarning] = new SystemConsoleThemeStyle { Foreground = ConsoleColor.DarkGray, Background = ConsoleColor.Yellow },
[ConsoleThemeStyle.LevelError] = new SystemConsoleThemeStyle { Foreground = ConsoleColor.White, Background = ConsoleColor.Red },
- [ConsoleThemeStyle.LevelFatal] = new SystemConsoleThemeStyle { Foreground = ConsoleColor.White, Background = ConsoleColor.Red }
+ [ConsoleThemeStyle.LevelFatal] = new SystemConsoleThemeStyle { Foreground = ConsoleColor.White, Background = ConsoleColor.Red },
});
}
}
diff --git a/test/Serilog.Sinks.Console.Tests/Configuration/ConsoleLoggerConfigurationExtensionsTests.cs b/test/Serilog.Sinks.Console.Tests/Configuration/ConsoleLoggerConfigurationExtensionsTests.cs
new file mode 100644
index 0000000..74596c5
--- /dev/null
+++ b/test/Serilog.Sinks.Console.Tests/Configuration/ConsoleLoggerConfigurationExtensionsTests.cs
@@ -0,0 +1,63 @@
+using System;
+using System.IO;
+using System.Linq;
+using Xunit;
+using Serilog.Sinks.SystemConsole.Themes;
+
+namespace Serilog.Sinks.Console.Tests.Configuration
+{
+ public class ConsoleLoggerConfigurationExtensionsTests
+ {
+ [Fact]
+ public void OutputFormattingIsIgnored()
+ {
+ using (var stream = new MemoryStream())
+ {
+ var sw = new StreamWriter(stream);
+
+ System.Console.SetOut(sw);
+ var config = new LoggerConfiguration()
+ .WriteTo.Console(theme: AnsiConsoleTheme.Literate,
+ applyThemeToRedirectedOutput: false);
+
+ var logger = config.CreateLogger();
+
+ logger.Error("test");
+ stream.Position = 0;
+
+ using (var streamReader = new StreamReader(stream))
+ {
+ var result = streamReader.ReadToEnd();
+ var controlCharacterCount = result.Count(c => Char.IsControl(c) && !Char.IsWhiteSpace(c));
+ Assert.Equal(0, controlCharacterCount);
+ }
+ }
+ }
+
+ [Fact]
+ public void OutputFormattingIsPresent()
+ {
+ using (var stream = new MemoryStream())
+ {
+ var sw = new StreamWriter(stream);
+
+ System.Console.SetOut(sw);
+ var config = new LoggerConfiguration()
+ .WriteTo.Console(theme: AnsiConsoleTheme.Literate,
+ applyThemeToRedirectedOutput: true);
+
+ var logger = config.CreateLogger();
+
+ logger.Error("test");
+ stream.Position = 0;
+
+ using (var streamReader = new StreamReader(stream))
+ {
+ var result = streamReader.ReadToEnd();
+ var controlCharacterCount = result.Count(c => Char.IsControl(c) && !Char.IsWhiteSpace(c));
+ Assert.NotEqual(0, controlCharacterCount);
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/test/Serilog.Sinks.Console.Tests/Formatting/ThemedDisplayValueFormatterTests.cs b/test/Serilog.Sinks.Console.Tests/Formatting/ThemedDisplayValueFormatterTests.cs
index c5c9833..2770069 100644
--- a/test/Serilog.Sinks.Console.Tests/Formatting/ThemedDisplayValueFormatterTests.cs
+++ b/test/Serilog.Sinks.Console.Tests/Formatting/ThemedDisplayValueFormatterTests.cs
@@ -11,11 +11,11 @@ public class ThemedDisplayValueFormatterTests
[Theory]
[InlineData("Hello", null, "\"Hello\"")]
[InlineData("Hello", "l", "Hello")]
- public void StringFormattingIsApplied(string s, string format, string expected)
+ public void StringFormattingIsApplied(string value, string format, string expected)
{
- var f = new ThemedDisplayValueFormatter(ConsoleTheme.None, null);
+ var formatter = new ThemedDisplayValueFormatter(ConsoleTheme.None, null);
var sw = new StringWriter();
- f.FormatLiteralValue(new ScalarValue(s), sw, format);
+ formatter.FormatLiteralValue(new ScalarValue(value), sw, format);
var actual = sw.ToString();
Assert.Equal(expected, actual);
}
diff --git a/test/Serilog.Sinks.Console.Tests/Formatting/ThemedJsonValueFormatterTests.cs b/test/Serilog.Sinks.Console.Tests/Formatting/ThemedJsonValueFormatterTests.cs
index 3e28425..45a3814 100644
--- a/test/Serilog.Sinks.Console.Tests/Formatting/ThemedJsonValueFormatterTests.cs
+++ b/test/Serilog.Sinks.Console.Tests/Formatting/ThemedJsonValueFormatterTests.cs
@@ -20,7 +20,7 @@ public TestThemedJsonValueFormatter()
public string Format(object literal)
{
var output = new StringWriter();
- Format(new SequenceValue(new [] {new ScalarValue(literal)}), output, null);
+ Format(new SequenceValue(new[] { new ScalarValue(literal) }), output, null);
var o = output.ToString();
return o.Substring(1, o.Length - 2);
}
@@ -114,8 +114,9 @@ public void StructuresFormatAsAnObject()
[Fact]
public void DictionaryWithScalarKeyFormatsAsAnObject()
{
- var dict = new DictionaryValue(new Dictionary {
- { new ScalarValue(12), new ScalarValue(345) }
+ var dict = new DictionaryValue(new Dictionary
+ {
+ { new ScalarValue(12), new ScalarValue(345) },
});
var f = Format(dict);
diff --git a/test/Serilog.Sinks.Console.Tests/Output/OutputTemplateRendererTests.cs b/test/Serilog.Sinks.Console.Tests/Output/OutputTemplateRendererTests.cs
new file mode 100644
index 0000000..1a71415
--- /dev/null
+++ b/test/Serilog.Sinks.Console.Tests/Output/OutputTemplateRendererTests.cs
@@ -0,0 +1,356 @@
+using System;
+using System.Globalization;
+using System.IO;
+using System.Linq;
+using Serilog.Events;
+using Serilog.Sinks.Console.Tests.Support;
+using Serilog.Sinks.SystemConsole.Output;
+using Serilog.Sinks.SystemConsole.Themes;
+using Xunit;
+
+namespace Serilog.Sinks.Console.Tests.Output
+{
+ public class OutputTemplateRendererTests
+ {
+ [Fact]
+ public void UsesFormatProvider()
+ {
+ var french = new CultureInfo("fr-FR");
+ var formatter = new OutputTemplateRenderer(ConsoleTheme.None, "{Message}", french);
+ var evt = DelegatingSink.GetLogEvent(l => l.Information("{0}", 12.345));
+ var sw = new StringWriter();
+ formatter.Format(evt, sw);
+ Assert.Equal("12,345", sw.ToString());
+ }
+
+ [Fact]
+ public void MessageTemplatesContainingFormatStringPropertiesRenderCorrectly()
+ {
+ var formatter = new OutputTemplateRenderer(ConsoleTheme.None, "{Message}", CultureInfo.InvariantCulture);
+ var evt = DelegatingSink.GetLogEvent(l => l.Information("{Message}", "Hello, world!"));
+ var sw = new StringWriter();
+ formatter.Format(evt, sw);
+ Assert.Equal("\"Hello, world!\"", sw.ToString());
+ }
+
+ [Fact]
+ public void UppercaseFormatSpecifierIsSupportedForStrings()
+ {
+ var formatter = new OutputTemplateRenderer(ConsoleTheme.None, "{Name:u}", CultureInfo.InvariantCulture);
+ var evt = DelegatingSink.GetLogEvent(l => l.Information("{Name}", "Nick"));
+ var sw = new StringWriter();
+ formatter.Format(evt, sw);
+ Assert.Equal("NICK", sw.ToString());
+ }
+
+ [Fact]
+ public void LowercaseFormatSpecifierIsSupportedForStrings()
+ {
+ var formatter = new OutputTemplateRenderer(ConsoleTheme.None, "{Name:w}", CultureInfo.InvariantCulture);
+ var evt = DelegatingSink.GetLogEvent(l => l.Information("{Name}", "Nick"));
+ var sw = new StringWriter();
+ formatter.Format(evt, sw);
+ Assert.Equal("nick", sw.ToString());
+ }
+
+ [Theory]
+ [InlineData(LogEventLevel.Verbose, 1, "V")]
+ [InlineData(LogEventLevel.Verbose, 2, "Vb")]
+ [InlineData(LogEventLevel.Verbose, 3, "Vrb")]
+ [InlineData(LogEventLevel.Verbose, 4, "Verb")]
+ [InlineData(LogEventLevel.Verbose, 5, "Verbo")]
+ [InlineData(LogEventLevel.Verbose, 6, "Verbos")]
+ [InlineData(LogEventLevel.Verbose, 7, "Verbose")]
+ [InlineData(LogEventLevel.Verbose, 8, "Verbose")]
+ [InlineData(LogEventLevel.Debug, 1, "D")]
+ [InlineData(LogEventLevel.Debug, 2, "De")]
+ [InlineData(LogEventLevel.Debug, 3, "Dbg")]
+ [InlineData(LogEventLevel.Debug, 4, "Dbug")]
+ [InlineData(LogEventLevel.Debug, 5, "Debug")]
+ [InlineData(LogEventLevel.Debug, 6, "Debug")]
+ [InlineData(LogEventLevel.Information, 1, "I")]
+ [InlineData(LogEventLevel.Information, 2, "In")]
+ [InlineData(LogEventLevel.Information, 3, "Inf")]
+ [InlineData(LogEventLevel.Information, 4, "Info")]
+ [InlineData(LogEventLevel.Information, 5, "Infor")]
+ [InlineData(LogEventLevel.Information, 6, "Inform")]
+ [InlineData(LogEventLevel.Information, 7, "Informa")]
+ [InlineData(LogEventLevel.Information, 8, "Informat")]
+ [InlineData(LogEventLevel.Information, 9, "Informati")]
+ [InlineData(LogEventLevel.Information, 10, "Informatio")]
+ [InlineData(LogEventLevel.Information, 11, "Information")]
+ [InlineData(LogEventLevel.Information, 12, "Information")]
+ [InlineData(LogEventLevel.Error, 1, "E")]
+ [InlineData(LogEventLevel.Error, 2, "Er")]
+ [InlineData(LogEventLevel.Error, 3, "Err")]
+ [InlineData(LogEventLevel.Error, 4, "Eror")]
+ [InlineData(LogEventLevel.Error, 5, "Error")]
+ [InlineData(LogEventLevel.Error, 6, "Error")]
+ [InlineData(LogEventLevel.Fatal, 1, "F")]
+ [InlineData(LogEventLevel.Fatal, 2, "Fa")]
+ [InlineData(LogEventLevel.Fatal, 3, "Ftl")]
+ [InlineData(LogEventLevel.Fatal, 4, "Fatl")]
+ [InlineData(LogEventLevel.Fatal, 5, "Fatal")]
+ [InlineData(LogEventLevel.Fatal, 6, "Fatal")]
+ [InlineData(LogEventLevel.Warning, 1, "W")]
+ [InlineData(LogEventLevel.Warning, 2, "Wn")]
+ [InlineData(LogEventLevel.Warning, 3, "Wrn")]
+ [InlineData(LogEventLevel.Warning, 4, "Warn")]
+ [InlineData(LogEventLevel.Warning, 5, "Warni")]
+ [InlineData(LogEventLevel.Warning, 6, "Warnin")]
+ [InlineData(LogEventLevel.Warning, 7, "Warning")]
+ [InlineData(LogEventLevel.Warning, 8, "Warning")]
+ public void FixedLengthLevelIsSupported(
+ LogEventLevel level,
+ int width,
+ string expected)
+ {
+ var formatter = new OutputTemplateRenderer(ConsoleTheme.None, $"{{Level:t{width}}}", CultureInfo.InvariantCulture);
+ var evt = DelegatingSink.GetLogEvent(l => l.Write(level, "Hello"));
+ var sw = new StringWriter();
+ formatter.Format(evt, sw);
+ Assert.Equal(expected, sw.ToString());
+ }
+
+ [Fact]
+ public void FixedLengthLevelSupportsUpperCasing()
+ {
+ var formatter = new OutputTemplateRenderer(ConsoleTheme.None, "{Level:u3}", CultureInfo.InvariantCulture);
+ var evt = DelegatingSink.GetLogEvent(l => l.Information("Hello"));
+ var sw = new StringWriter();
+ formatter.Format(evt, sw);
+ Assert.Equal("INF", sw.ToString());
+ }
+
+ [Fact]
+ public void FixedLengthLevelSupportsLowerCasing()
+ {
+ var formatter = new OutputTemplateRenderer(ConsoleTheme.None, "{Level:w3}", CultureInfo.InvariantCulture);
+ var evt = DelegatingSink.GetLogEvent(l => l.Information("Hello"));
+ var sw = new StringWriter();
+ formatter.Format(evt, sw);
+ Assert.Equal("inf", sw.ToString());
+ }
+
+ [Fact]
+ public void DefaultLevelLengthIsFullText()
+ {
+ var formatter = new OutputTemplateRenderer(ConsoleTheme.None, "{Level}", CultureInfo.InvariantCulture);
+ var evt = DelegatingSink.GetLogEvent(l => l.Information("Hello"));
+ var sw = new StringWriter();
+ formatter.Format(evt, sw);
+ Assert.Equal("Information", sw.ToString());
+ }
+
+ [Fact]
+ public void AlignmentAndWidthCanBeCombined()
+ {
+ var formatter = new OutputTemplateRenderer(ConsoleTheme.None, "{Level,5:w3}", CultureInfo.InvariantCulture);
+ var evt = DelegatingSink.GetLogEvent(l => l.Information("Hello"));
+ var sw = new StringWriter();
+ formatter.Format(evt, sw);
+ Assert.Equal(" inf", sw.ToString());
+ }
+
+ enum Size
+ {
+ Large
+ }
+
+ class SizeFormatter : IFormatProvider, ICustomFormatter
+ {
+ readonly IFormatProvider _innerFormatProvider;
+
+ public SizeFormatter(IFormatProvider innerFormatProvider)
+ {
+ _innerFormatProvider = innerFormatProvider;
+ }
+
+ public object? GetFormat(Type? formatType)
+ {
+ return formatType == typeof(ICustomFormatter) ? this : _innerFormatProvider.GetFormat(formatType) ?? this;
+ }
+
+ public string Format(string? format, object? arg, IFormatProvider? formatProvider)
+ {
+ if (arg is Size size)
+ return size == Size.Large ? "Huge" : size.ToString();
+
+ if (arg is IFormattable formattable)
+ return formattable.ToString(format, _innerFormatProvider);
+
+ return arg?.ToString() ?? "";
+ }
+ }
+
+ [Fact]
+ public void AppliesCustomFormatterToEnums()
+ {
+ var formatter = new OutputTemplateRenderer(ConsoleTheme.None, "{Message}", new SizeFormatter(CultureInfo.InvariantCulture));
+ var evt = DelegatingSink.GetLogEvent(l => l.Information("Size {Size}", Size.Large));
+ var sw = new StringWriter();
+ formatter.Format(evt, sw);
+ Assert.Equal("Size Huge", sw.ToString());
+ }
+
+ [Fact]
+ public void NonMessagePropertiesAreRendered()
+ {
+ var formatter = new OutputTemplateRenderer(ConsoleTheme.None, "{Properties}", CultureInfo.InvariantCulture);
+ var evt = DelegatingSink.GetLogEvent(l => l.ForContext("Foo", 42).Information("Hello from {Bar}!", "bar"));
+ var sw = new StringWriter();
+ formatter.Format(evt, sw);
+ Assert.Equal("{Foo=42}", sw.ToString());
+ }
+
+ [Fact]
+ public void NonMessagePositionalPropertiesAreRendered()
+ {
+ var formatter = new OutputTemplateRenderer(ConsoleTheme.None, "{Properties}", CultureInfo.InvariantCulture);
+ var evt = DelegatingSink.GetLogEvent(l => l.ForContext("Foo", 42).Information("Hello from {0}!", "bar"));
+ var sw = new StringWriter();
+ formatter.Format(evt, sw);
+ Assert.Equal("{Foo=42}", sw.ToString());
+ }
+
+ [Fact]
+ public void DoNotDuplicatePropertiesAlreadyRenderedInOutputTemplate()
+ {
+ var formatter = new OutputTemplateRenderer(ConsoleTheme.None, "{Foo} {Properties}", CultureInfo.InvariantCulture);
+ var evt = DelegatingSink.GetLogEvent(l => l.ForContext("Foo", 42).ForContext("Bar", 42).Information("Hello from bar!"));
+ var sw = new StringWriter();
+ formatter.Format(evt, sw);
+ Assert.Equal("42 {Bar=42}", sw.ToString());
+ }
+
+ [Theory]
+ [InlineData("", "Hello, \"World\"!")]
+ [InlineData(":j", "Hello, \"World\"!")]
+ [InlineData(":l", "Hello, World!")]
+ [InlineData(":lj", "Hello, World!")]
+ [InlineData(":jl", "Hello, World!")]
+ public void AppliesLiteralFormattingToMessageStringsWhenSpecified(string format, string expected)
+ {
+ var formatter = new OutputTemplateRenderer(ConsoleTheme.None, "{Message" + format + "}", null);
+ var evt = DelegatingSink.GetLogEvent(l => l.Information("Hello, {Name}!", "World"));
+ var sw = new StringWriter();
+ formatter.Format(evt, sw);
+ Assert.Equal(expected, sw.ToString());
+ }
+
+ [Theory]
+ [InlineData("", "{Name=\"World\"}")]
+ [InlineData(":j", "{\"Name\": \"World\"}")]
+ [InlineData(":lj", "{\"Name\": \"World\"}")]
+ [InlineData(":jl", "{\"Name\": \"World\"}")]
+ public void AppliesJsonFormattingToMessageStructuresWhenSpecified(string format, string expected)
+ {
+ var formatter = new OutputTemplateRenderer(ConsoleTheme.None, "{Message" + format + "}", null);
+ var evt = DelegatingSink.GetLogEvent(l => l.Information("{@Obj}", new { Name = "World" }));
+ var sw = new StringWriter();
+ formatter.Format(evt, sw);
+ Assert.Equal(expected, sw.ToString());
+ }
+
+ [Theory]
+ [InlineData("", "{Name=\"World\"}")]
+ [InlineData(":j", "{\"Name\": \"World\"}")]
+ [InlineData(":lj", "{\"Name\": \"World\"}")]
+ [InlineData(":jl", "{\"Name\": \"World\"}")]
+ public void AppliesJsonFormattingToPropertiesTokenWhenSpecified(string format, string expected)
+ {
+ var formatter = new OutputTemplateRenderer(ConsoleTheme.None, "{Properties" + format + "}", null);
+ var evt = DelegatingSink.GetLogEvent(l => l.ForContext("Name", "World").Information("Hello"));
+ var sw = new StringWriter();
+ formatter.Format(evt, sw);
+ Assert.Equal(expected, sw.ToString());
+ }
+
+ [Fact]
+ public void AnEmptyPropertiesTokenIsAnEmptyStructureValue()
+ {
+ var formatter = new OutputTemplateRenderer(ConsoleTheme.None, "{Properties}", null);
+ var evt = DelegatingSink.GetLogEvent(l => l.Information("Hello"));
+ var sw = new StringWriter();
+ formatter.Format(evt, sw);
+
+ // /!\ different behavior from Serilog Core : https://github.com/serilog/serilog/blob/5c3a7821aa0f654e551dc21e8e19089f6767666b/test/Serilog.Tests/Formatting/Display/MessageTemplateTextFormatterTests.cs#L268-L278
+ //
+ // var expected = new StructureValue(Enumerable.Empty()).ToString();
+ // // expected == "{ }"
+ // Assert.Equal(expected, sw.ToString());
+ //
+ Assert.Equal("{}", sw.ToString());
+ }
+
+ [Theory]
+ [InlineData("", true)]
+ [InlineData(":lj", true)]
+ [InlineData(":jl", true)]
+ [InlineData(":j", false)]
+ [InlineData(":l", true)]
+ public void FormatProviderWithScalarProperties(string format, bool shouldUseCustomFormatter)
+ {
+ var frenchFormatProvider = new CultureInfo("fr-FR");
+ var defaultFormatProvider = CultureInfo.InvariantCulture;
+
+ var date = new DateTime(2018, 01, 01);
+ var number = 12.345;
+
+ var expectedFormattedDate = shouldUseCustomFormatter
+ ? date.ToString(frenchFormatProvider)
+ : date.ToString("O", defaultFormatProvider);
+ var expectedFormattedNumber = shouldUseCustomFormatter
+ ? number.ToString(frenchFormatProvider)
+ : number.ToString(defaultFormatProvider);
+
+ var formatter = new OutputTemplateRenderer(ConsoleTheme.None, "{Message" + format + "}", frenchFormatProvider);
+ var evt = DelegatingSink.GetLogEvent(l =>
+ {
+ l.Information("{MyDate}{MyNumber}", date, number);
+ });
+ var sw = new StringWriter();
+ formatter.Format(evt, sw);
+
+ Assert.Contains(expectedFormattedDate, sw.ToString());
+ Assert.Contains(expectedFormattedNumber, sw.ToString());
+ }
+
+ [Theory]
+ [InlineData("", true)]
+ [InlineData(":lj", false)]
+ [InlineData(":jl", false)]
+ [InlineData(":j", false)]
+ [InlineData(":l", true)]
+ public void FormatProviderWithDestructuredProperties(string format, bool shouldUseCustomFormatter)
+ {
+ var frenchFormatProvider = new CultureInfo("fr-FR");
+ var defaultFormatProvider = CultureInfo.InvariantCulture;
+
+ var date = new DateTime(2018, 01, 01);
+ var number = 12.345;
+
+ var expectedFormattedDate = shouldUseCustomFormatter
+ ? date.ToString(frenchFormatProvider)
+ : date.ToString("O", defaultFormatProvider);
+ var expectedFormattedNumber = shouldUseCustomFormatter
+ ? number.ToString(frenchFormatProvider)
+ : number.ToString(defaultFormatProvider);
+
+ var formatter = new OutputTemplateRenderer(ConsoleTheme.None, "{Message" + format + "}", frenchFormatProvider);
+ var evt = DelegatingSink.GetLogEvent(l =>
+ {
+ l.Information("{@Item}", new
+ {
+ MyDate = date,
+ MyNumber = number,
+ });
+ });
+ var sw = new StringWriter();
+ formatter.Format(evt, sw);
+
+ Assert.Contains(expectedFormattedDate, sw.ToString());
+ Assert.Contains(expectedFormattedNumber, sw.ToString());
+ }
+ }
+}
diff --git a/test/Serilog.Sinks.Console.Tests/Properties/AssemblyInfo.cs b/test/Serilog.Sinks.Console.Tests/Properties/AssemblyInfo.cs
deleted file mode 100644
index 4911a24..0000000
--- a/test/Serilog.Sinks.Console.Tests/Properties/AssemblyInfo.cs
+++ /dev/null
@@ -1,19 +0,0 @@
-using System.Reflection;
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-
-// General Information about an assembly is controlled through the following
-// set of attributes. Change these attribute values to modify the information
-// associated with an assembly.
-[assembly: AssemblyConfiguration("")]
-[assembly: AssemblyCompany("")]
-[assembly: AssemblyProduct("Serilog.Sinks.Trace.Tests")]
-[assembly: AssemblyTrademark("")]
-
-// Setting ComVisible to false makes the types in this assembly not visible
-// to COM components. If you need to access a type in this assembly from
-// COM, set the ComVisible attribute to true on that type.
-[assembly: ComVisible(false)]
-
-// The following GUID is for the ID of the typelib if this project is exposed to COM
-[assembly: Guid("1d56534c-4009-42c2-a573-789cae6b8aa9")]
diff --git a/test/Serilog.Sinks.Console.Tests/Rendering/ThemedMessageTemplateRendererTests.cs b/test/Serilog.Sinks.Console.Tests/Rendering/ThemedMessageTemplateRendererTests.cs
index 18debf0..031f118 100644
--- a/test/Serilog.Sinks.Console.Tests/Rendering/ThemedMessageTemplateRendererTests.cs
+++ b/test/Serilog.Sinks.Console.Tests/Rendering/ThemedMessageTemplateRendererTests.cs
@@ -1,12 +1,12 @@
-using System;
+using Serilog.Sinks.SystemConsole.Formatting;
+using Serilog.Sinks.SystemConsole.Rendering;
+using Serilog.Sinks.SystemConsole.Themes;
+using System;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using Xunit;
-using Serilog.Sinks.SystemConsole.Themes;
-using Serilog.Sinks.SystemConsole.Formatting;
-using Serilog.Sinks.SystemConsole.Rendering;
namespace Serilog.Sinks.Console.Tests.Rendering
{
@@ -18,25 +18,20 @@ class Chair
public string Back => "straight";
public int[] Legs => new[] { 1, 2, 3, 4 };
+
// ReSharper restore UnusedMember.Local
- public override string ToString()
- {
- return "a chair";
- }
+ public override string ToString() => "a chair";
}
class Receipt
{
// ReSharper disable UnusedMember.Local
public decimal Sum => 12.345m;
-
+
public DateTime When => new DateTime(2013, 5, 20, 16, 39, 0);
- // ReSharper restore UnusedMember.Local
- public override string ToString()
- {
- return "a receipt";
- }
+ // ReSharper restore UnusedMember.Local
+ public override string ToString() => "a receipt";
}
[Fact]
@@ -126,10 +121,12 @@ static string Render(string messageTemplate, params object[] properties)
return Render(null, messageTemplate, properties);
}
- static string Render(IFormatProvider formatProvider, string messageTemplate, params object[] properties)
+ static string Render(IFormatProvider? formatProvider, string messageTemplate, params object[] properties)
{
var binder = new LoggerConfiguration().CreateLogger();
- binder.BindMessageTemplate(messageTemplate, properties, out var mt, out var props);
+ if (binder.BindMessageTemplate(messageTemplate, properties, out var mt, out var props) == false)
+ throw new InvalidOperationException();
+
var output = new StringBuilder();
var writer = new StringWriter(output);
var renderer = new ThemedMessageTemplateRenderer(ConsoleTheme.None,
diff --git a/test/Serilog.Sinks.Console.Tests/Serilog.Sinks.Console.Tests.csproj b/test/Serilog.Sinks.Console.Tests/Serilog.Sinks.Console.Tests.csproj
index dc49e7f..5e141e3 100644
--- a/test/Serilog.Sinks.Console.Tests/Serilog.Sinks.Console.Tests.csproj
+++ b/test/Serilog.Sinks.Console.Tests/Serilog.Sinks.Console.Tests.csproj
@@ -1,19 +1,13 @@
-
+
- net461;netcoreapp1.1
- Serilog.Sinks.SystemConsole.Tests
- Serilog.Sinks.Console.Tests
+ netcoreapp2.1;netcoreapp2.2;netcoreapp3.0;netcoreapp3.1;net452;net462;net472;net48;net5.0
true
- 1.6.0
- $(PackageTargetFallback);dnxcore50;portable-net45+win8
- 1.0.4
- false
- false
- false
../../assets/Serilog.snk
true
true
+ 8.0
+ enable
@@ -21,14 +15,10 @@
-
-
-
-
-
-
-
-
+
+
+
+
diff --git a/test/Serilog.Sinks.Console.Tests/Support/DelegatingSink.cs b/test/Serilog.Sinks.Console.Tests/Support/DelegatingSink.cs
new file mode 100644
index 0000000..1863a41
--- /dev/null
+++ b/test/Serilog.Sinks.Console.Tests/Support/DelegatingSink.cs
@@ -0,0 +1,33 @@
+using System;
+using Serilog.Core;
+using Serilog.Events;
+
+namespace Serilog.Sinks.Console.Tests.Support
+{
+ public class DelegatingSink : ILogEventSink
+ {
+ readonly Action _write;
+
+ public DelegatingSink(Action write)
+ {
+ _write = write ?? throw new ArgumentNullException(nameof(write));
+ }
+
+ public void Emit(LogEvent logEvent)
+ {
+ _write(logEvent);
+ }
+
+ public static LogEvent GetLogEvent(Action writeAction)
+ {
+ LogEvent? result = null;
+ var logger = new LoggerConfiguration()
+ .MinimumLevel.Verbose()
+ .WriteTo.Sink(new DelegatingSink(le => result = le))
+ .CreateLogger();
+
+ writeAction(logger);
+ return result!;
+ }
+ }
+}