Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

make '$' sign optional for minimum level / filter switch declarations #242

Merged
merged 1 commit into from
Nov 24, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@

3.2.0 (pre-release)

* #162 - LoggingFilterSwitch support
* #202 - added support to AuditTo.Logger
* #203 - added support for custom types in arrays and custom collections
* #218 - fixed an issue with `dotnet restore` with `rid` specified if referenced from `netstandard` project
* #219 - reduced search graph for configuration dlls to avoid native assets
* #221 - added support for conditional/leveled enrichers from Serilog 2.9+
* #222 - updated Microsoft.Extensions.DependencyModel
* #231 - make '$' sign optional for minimum level / filter switch declarations
* #237 - DependencyContextAssemblyFinder fix: check `serilog` at the start of the name for any dependent package
* #239 - handle NotSupportedException for .net 5.0 single file applications

Expand Down
2 changes: 2 additions & 0 deletions Directory.Build.props
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
<Project>
<PropertyGroup>
<LangVersion>latest</LangVersion>
<TreatWarningsAsErrors>True</TreatWarningsAsErrors>
<TreatSpecificWarningsAsErrors />
</PropertyGroup>

<ItemGroup Condition="'$(TargetFrameworkIdentifier)' == '.NETFramework'">
Expand Down
25 changes: 22 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -140,12 +140,12 @@ Any changes for `Default`, `Microsoft`, `System` sources will be applied at runt

(Note: only existing sources are respected for a dynamic update. Inserting new records in `Override` section is **not** supported.)

You can also declare `LoggingLevelSwitch`-es in custom section and reference them for Sink parameters:
You can also declare `LoggingLevelSwitch`-es in custom section and reference them for sink parameters:

```json
{
"Serilog": {
"LevelSwitches": { "$controlSwitch": "Verbose" },
"LevelSwitches": { "controlSwitch": "Verbose" },
"WriteTo": [
{
"Name": "Seq",
Expand Down Expand Up @@ -205,7 +205,7 @@ This section defines a static list of key-value pairs that will enrich log event

### Filter section

This section defines filters that will be applied to log events. It is especially usefull in combination with _[Serilog.Filters.Expression](https://github.com/serilog/serilog-filters-expressions)_ package so you can write expression in text form:
This section defines filters that will be applied to log events. It is especially usefull in combination with _[Serilog.Filters.Expression](https://github.com/serilog/serilog-expressions)_ (or legacy _[Serilog.Filters.Expression](https://github.com/serilog/serilog-filters-expressions)_) package so you can write expression in text form:

```json
"Filter": [{
Expand All @@ -216,6 +216,25 @@ This section defines filters that will be applied to log events. It is especiall
}]
```

Using this package you can also declare `LoggingFilterSwitch`-es in custom section and reference them for filter parameters:

```json
{
"Serilog": {
"FilterSwitches": { "filterSwitch": "Application = 'Sample'" },
"Filter": [
{
"Name": "ControlledBy",
"Args": {
"switch": "$filterSwitch"
}
}
]
}
```

Level updates to switches are also respected for a dynamic update.

### Nested configuration sections

Some Serilog packages require a reference to a logger configuration object. The sample program in this project illustrates this with the following entry configuring the _[Serilog.Sinks.Async](https://github.com/serilog/serilog-sinks-async)_ package to wrap the _[Serilog.Sinks.File](https://github.com/serilog/serilog-sinks-file)_ package. The `configure` parameter references the File sink configuration:
Expand Down
3 changes: 2 additions & 1 deletion sample/Sample/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
using Serilog;
using Serilog.Core;
using Serilog.Events;
using System.Collections.Generic;
using Serilog.Debugging;

namespace Sample
Expand All @@ -19,6 +18,8 @@ public class Program
{
public static void Main(string[] args)
{
SelfLog.Enable(Console.Error);

Thread.CurrentThread.Name = "Main thread";

var configuration = new ConfigurationBuilder()
Expand Down
2 changes: 1 addition & 1 deletion sample/Sample/appsettings.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"Serilog": {
"Using": [ "Serilog.Sinks.Console" ],
"LevelSwitches": { "$controlSwitch": "Verbose" },
"LevelSwitches": { "controlSwitch": "Verbose" },
"FilterSwitches": { "$filterSwitch": "Application = 'Sample'" },
"MinimumLevel": {
"Default": "Debug",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
<ItemGroup>
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All"/>
<PackageReference Include="Microsoft.Extensions.DependencyModel" Version="3.0.0" />
<PackageReference Include="Serilog" Version="2.9.0" />
<PackageReference Include="Serilog" Version="2.10.0" />
<None Include="..\..\assets\icon.png" Pack="true" PackagePath=""/>
</ItemGroup>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text.RegularExpressions;

using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Primitives;
using System.Text.RegularExpressions;

using Serilog.Configuration;
using Serilog.Core;
Expand All @@ -17,7 +18,7 @@ namespace Serilog.Settings.Configuration
{
class ConfigurationReader : IConfigurationReader
{
const string LevelSwitchNameRegex = @"^\$[A-Za-z]+[A-Za-z0-9]*$";
const string LevelSwitchNameRegex = @"^\${0,1}[A-Za-z]+[A-Za-z0-9]*$";

readonly IConfigurationSection _section;
readonly IReadOnlyCollection<Assembly> _configurationAssemblies;
Expand Down Expand Up @@ -68,7 +69,7 @@ void ProcessFilterSwitchDeclarations()
// switchName must be something like $switch to avoid ambiguities
if (!IsValidSwitchName(switchName))
{
throw new FormatException($"\"{switchName}\" is not a valid name for a Filter Switch declaration. Filter switch must be declared with a '$' sign, like \"FilterSwitches\" : {{\"$switchName\" : \"{{FilterExpression}}\"}}");
throw new FormatException($"\"{switchName}\" is not a valid name for a Filter Switch declaration. The first character of the name must be a letter or '$' sign, like \"FilterSwitches\" : {{\"$switchName\" : \"{{FilterExpression}}\"}}");
}

SetFilterSwitch(throwOnError: true);
Expand Down Expand Up @@ -118,7 +119,7 @@ void ProcessLevelSwitchDeclarations()
// switchName must be something like $switch to avoid ambiguities
if (!IsValidSwitchName(switchName))
{
throw new FormatException($"\"{switchName}\" is not a valid name for a Level Switch declaration. Level switch must be declared with a '$' sign, like \"LevelSwitches\" : {{\"$switchName\" : \"InitialLevel\"}}");
throw new FormatException($"\"{switchName}\" is not a valid name for a Level Switch declaration. The first character of the name must be a letter or '$' sign, like \"LevelSwitches\" : {{\"$switchName\" : \"InitialLevel\"}}");
}

LoggingLevelSwitch newSwitch;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,14 +67,19 @@ public void AddLevelSwitch(string levelSwitchName, LoggingLevelSwitch levelSwitc
{
if (levelSwitchName == null) throw new ArgumentNullException(nameof(levelSwitchName));
if (levelSwitch == null) throw new ArgumentNullException(nameof(levelSwitch));
_declaredLevelSwitches[levelSwitchName] = levelSwitch;
_declaredLevelSwitches[ToSwitchReference(levelSwitchName)] = levelSwitch;
}

public void AddFilterSwitch(string filterSwitchName, LoggingFilterSwitchProxy filterSwitch)
{
if (filterSwitchName == null) throw new ArgumentNullException(nameof(filterSwitchName));
if (filterSwitch == null) throw new ArgumentNullException(nameof(filterSwitch));
_declaredFilterSwitches[filterSwitchName] = filterSwitch;
_declaredFilterSwitches[ToSwitchReference(filterSwitchName)] = filterSwitch;
}

string ToSwitchReference(string switchName)
{
return switchName.StartsWith("$") ? switchName : $"${switchName}";
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -305,8 +305,10 @@ public void SinksAreConfiguredWithStaticMember()
[Theory]
[InlineData("$switchName", true)]
[InlineData("$SwitchName", true)]
[InlineData("SwitchName", true)]
[InlineData("$switch1", true)]
[InlineData("$sw1tch0", true)]
[InlineData("sw1tch0", true)]
[InlineData("$SWITCHNAME", true)]
[InlineData("$$switchname", false)]
[InlineData("$switchname$", false)]
Expand All @@ -326,32 +328,34 @@ public void LoggingLevelSwitchNameValidityScenarios(string switchName, bool expe
public void LoggingLevelSwitchWithInvalidNameThrowsFormatException()
{
var json = @"{
""Serilog"": {
""LevelSwitches"": {""switchNameNotStartingWithDollar"" : ""Warning"" }
""Serilog"": {
""LevelSwitches"": {""1InvalidSwitchName"" : ""Warning"" }
}
}";

var ex = Assert.Throws<FormatException>(() => ConfigFromJson(json));

Assert.Contains("\"switchNameNotStartingWithDollar\"", ex.Message);
Assert.Contains("\"1InvalidSwitchName\"", ex.Message);
Assert.Contains("'$' sign", ex.Message);
Assert.Contains("\"LevelSwitches\" : {\"$switchName\" :", ex.Message);
}

[Fact]
public void LoggingFilterSwitchIsConfigured()
[Theory]
[InlineData("$mySwitch")]
[InlineData("mySwitch")]
public void LoggingFilterSwitchIsConfigured(string switchName)
{
var json = @"{
'Serilog': {
'FilterSwitches': { '$mySwitch': 'Prop = 42' },
'Filter:BySwitch': {
var json = $@"{{
'Serilog': {{
'FilterSwitches': {{ '{switchName}': 'Prop = 42' }},
'Filter:BySwitch': {{
'Name': 'ControlledBy',
'Args': {
'Args': {{
'switch': '$mySwitch'
}
}
}
}";
}}
}}
}}
}}";
LogEvent evt = null;

var log = ConfigFromJson(json)
Expand All @@ -365,17 +369,19 @@ public void LoggingFilterSwitchIsConfigured()
Assert.NotNull(evt);
}

[Fact]
public void LoggingLevelSwitchIsConfigured()
[Theory]
[InlineData("$switch1")]
[InlineData("switch1")]
public void LoggingLevelSwitchIsConfigured(string switchName)
{
var json = @"{
""Serilog"": {
""LevelSwitches"": {""$switch1"" : ""Warning"" },
""MinimumLevel"" : {
""ControlledBy"" : ""$switch1""
}
}
}";
var json = $@"{{
'Serilog': {{
'LevelSwitches': {{ '{switchName}' : 'Warning' }},
'MinimumLevel' : {{
'ControlledBy' : '$switch1'
}}
}}
}}";
LogEvent evt = null;

var log = ConfigFromJson(json)
Expand Down