Skip to content

Commit

Permalink
Merge pull request #343 from serilog/dev
Browse files Browse the repository at this point in the history
7.0.0 Release
  • Loading branch information
nblumhardt authored May 10, 2023
2 parents 20333a2 + d7e0dbd commit e878335
Show file tree
Hide file tree
Showing 79 changed files with 5,015 additions and 3,620 deletions.
2 changes: 2 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,5 @@ end_of_line = lf

[*.{cmd, bat}]
end_of_line = crlf

csharp_style_namespace_declarations = file_scoped:suggestion
5 changes: 1 addition & 4 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# TODO: Comment the next line if you want to checkin your web deploy settings
# TODO: Comment the next line if you want to checkin your web deploy settings
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
Expand Down Expand Up @@ -200,7 +200,4 @@ FakesAssemblies/

project.lock.json

#Test files
*.txt

artifacts/
58 changes: 18 additions & 40 deletions Build.ps1
Original file line number Diff line number Diff line change
@@ -1,60 +1,38 @@
echo "build: Build started"
Write-Output "build: Build started"

Push-Location $PSScriptRoot

if(Test-Path .\artifacts) {
echo "build: Cleaning .\artifacts"
Remove-Item .\artifacts -Force -Recurse
Write-Output "build: Cleaning .\artifacts"
Remove-Item .\artifacts -Force -Recurse
}

& dotnet restore --no-cache

$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 "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"

foreach ($src in gci src/*) {
Push-Location $src

echo "build: Packaging project in $src"

& dotnet build -c Release --version-suffix=$buildSuffix

if($suffix) {
& dotnet pack -c Release --include-source --no-build -o ../../artifacts --version-suffix=$suffix -p:ContinuousIntegrationBuild=true
} else {
& dotnet pack -c Release --include-source --no-build -o ../../artifacts -p:ContinuousIntegrationBuild=true
}
if($LASTEXITCODE -ne 0) { exit 1 }
Write-Output "build: Package version suffix is $suffix"
Write-Output "build: Build version suffix is $buildSuffix"

Pop-Location
}

foreach ($test in gci test/*.Tests) {
Push-Location $test

echo "build: Testing project in $test"
& dotnet build --configuration Release --version-suffix=$buildSuffix /p:ContinuousIntegrationBuild=true

& dotnet test -c Release
if($LASTEXITCODE -ne 0) { exit 3 }
if($LASTEXITCODE -ne 0) { throw 'build failed' }

Pop-Location
if($suffix) {
& dotnet pack src\Serilog.Settings.Configuration --configuration Release --no-build --no-restore -o artifacts --version-suffix=$suffix
} else {
& dotnet pack src\Serilog.Settings.Configuration --configuration Release --no-build --no-restore -o artifacts
}

foreach ($test in gci test/*.PerformanceTests) {
Push-Location $test
if($LASTEXITCODE -ne 0) { throw 'pack failed' }

echo "build: Building performance test project in $test"
Write-Output "build: Testing"

& dotnet build -c Release
if($LASTEXITCODE -ne 0) { exit 2 }

Pop-Location
}
# Dotnet test doesn't run separate TargetFrameworks in parallel: https://github.com/dotnet/sdk/issues/19147
# Workaround: use `dotnet test` on dlls directly in order to pass the `--parallel` option to vstest.
# The _reported_ runtime is wrong but the _actual_ used runtime is correct, see https://github.com/microsoft/vstest/issues/2037#issuecomment-720549173
& dotnet test test\Serilog.Settings.Configuration.Tests\bin\Release\*\Serilog.Settings.Configuration.Tests.dll --parallel

Pop-Location
if($LASTEXITCODE -ne 0) { throw 'unit tests failed' }
10 changes: 5 additions & 5 deletions Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@
<PropertyGroup>
<LangVersion>latest</LangVersion>
<TreatWarningsAsErrors>True</TreatWarningsAsErrors>
<TreatSpecificWarningsAsErrors />
<SignAssembly>true</SignAssembly>
<AssemblyOriginatorKeyFile>$(MSBuildThisFileDirectory)assets/Serilog.snk</AssemblyOriginatorKeyFile>
<ImplicitUsings>enable</ImplicitUsings>
<CheckEolTargetFramework>false</CheckEolTargetFramework>
<Nullable>enable</Nullable>
</PropertyGroup>

<ItemGroup Condition="'$(TargetFrameworkIdentifier)' == '.NETFramework'">
<PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.2" PrivateAssets="all" />
</ItemGroup>
</Project>
77 changes: 60 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ For a more sophisticated example go to the [sample](sample/Sample) folder.

Root section name can be changed:

```json
```yaml
{
"CustomSection": {
...
Expand All @@ -65,16 +65,17 @@ Root section name can be changed:
```

```csharp
var options = new ConfigurationReaderOptions { SectionName = "CustomSection" };
var logger = new LoggerConfiguration()
.ReadFrom.Configuration(configuration, sectionName: "CustomSection")
.ReadFrom.Configuration(configuration, options)
.CreateLogger();
```

### Using section and auto-discovery of configuration assemblies

`Using` section contains list of **assemblies** in which configuration methods (`WriteTo.File()`, `Enrich.WithThreadId()`) reside.

```json
```yaml
"Serilog": {
"Using": [ "Serilog.Sinks.Console", "Serilog.Enrichers.Thread", /* ... */ ],
// ...
Expand All @@ -83,7 +84,7 @@ var logger = new LoggerConfiguration()

For .NET Core projects build tools produce `.deps.json` files and this package implements a convention using `Microsoft.Extensions.DependencyModel` to find any package among dependencies with `Serilog` anywhere in the name and pulls configuration methods from it, so the `Using` section in example above can be omitted:

```json
```yaml
{
"Serilog": {
"MinimumLevel": "Debug",
Expand All @@ -106,8 +107,9 @@ In case of [non-standard](#azure-functions-v2-v3) dependency management you can
```csharp
var functionDependencyContext = DependencyContext.Load(typeof(Startup).Assembly);

var options = new ConfigurationReaderOptions(functionDependencyContext) { SectionName = "AzureFunctionsJobHost:Serilog" };
var logger = new LoggerConfiguration()
.ReadFrom.Configuration(hostConfig, sectionName: "AzureFunctionsJobHost:Serilog", dependencyContext: functionDependencyContext)
.ReadFrom.Configuration(hostConfig, options)
.CreateLogger();
```

Expand All @@ -119,8 +121,9 @@ var configurationAssemblies = new[]
typeof(ConsoleLoggerConfigurationExtensions).Assembly,
typeof(FileLoggerConfigurationExtensions).Assembly,
};
var options = new ConfigurationReaderOptions(configurationAssemblies);
var logger = new LoggerConfiguration()
.ReadFrom.Configuration(configuration, configurationAssemblies)
.ReadFrom.Configuration(configuration, options)
.CreateLogger();
```

Expand Down Expand Up @@ -183,6 +186,22 @@ You can also declare `LoggingLevelSwitch`-es in custom section and reference the

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

Since version 7.0.0, both declared switches (i.e. `Serilog:LevelSwitches` section) and minimum level override switches (i.e. `Serilog:MinimumLevel:Override` section) are exposed through a callback on the reader options so that a reference can be kept:

```csharp
var allSwitches = new Dictionary<string, LoggingLevelSwitch>();
var options = new ConfigurationReaderOptions
{
OnLevelSwitchCreated = (switchName, levelSwitch) => allSwitches[switchName] = levelSwitch
};

var logger = new LoggerConfiguration()
.ReadFrom.Configuration(configuration, options)
.CreateLogger();

LoggingLevelSwitch controlSwitch = allSwitches["$controlSwitch"];
```

### WriteTo, Enrich, AuditTo, Destructure sections

These sections support simplified syntax, for example the following is valid if no arguments are needed by the sinks:
Expand All @@ -195,7 +214,7 @@ Or alternatively, the long-form (`"Name":` ...) syntax from the example above ca

By `Microsoft.Extensions.Configuration.Json` convention, array syntax implicitly defines index for each element in order to make unique paths for configuration keys. So the example above is equivalent to:

```json
```yaml
"WriteTo": {
"0": "Console",
"1": "DiagnosticTrace"
Expand All @@ -204,7 +223,7 @@ By `Microsoft.Extensions.Configuration.Json` convention, array syntax implicitly

And

```json
```yaml
"WriteTo:0": "Console",
"WriteTo:1": "DiagnosticTrace"
```
Expand All @@ -213,7 +232,7 @@ And

When overriding settings with [environment variables](https://docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration/?view=aspnetcore-3.1#environment-variables) it becomes less convenient and fragile, so you can specify custom names:

```json
```yaml
"WriteTo": {
"ConsoleSink": "Console",
"DiagnosticTraceSink": { "Name": "DiagnosticTrace" }
Expand All @@ -226,9 +245,9 @@ 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.Expressions](https://github.com/serilog/serilog-expressions)_ (or legacy _[Serilog.Filters.Expressions](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 useful in combination with _[Serilog.Expressions](https://github.com/serilog/serilog-expressions)_ (or legacy _[Serilog.Filters.Expressions](https://github.com/serilog/serilog-filters-expressions)_) package so you can write expression in text form:

```json
```yaml
"Filter": [{
"Name": "ByIncludingOnly",
"Args": {
Expand All @@ -239,7 +258,7 @@ 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
```yaml
{
"Serilog": {
"FilterSwitches": { "filterSwitch": "Application = 'Sample'" },
Expand All @@ -256,11 +275,27 @@ Using this package you can also declare `LoggingFilterSwitch`-es in custom secti

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

Since version 7.0.0, filter switches are exposed through a callback on the reader options so that a reference can be kept:

```csharp
var filterSwitches = new Dictionary<string, ILoggingFilterSwitch>();
var options = new ConfigurationReaderOptions
{
OnFilterSwitchCreated = (switchName, filterSwitch) => filterSwitches[switchName] = filterSwitch
};
var logger = new LoggerConfiguration()
.ReadFrom.Configuration(configuration, options)
.CreateLogger();
ILoggingFilterSwitch filterSwitch = filterSwitches["filterSwitch"];
```

### 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:

```json
```yaml
"WriteTo:Async": {
"Name": "Async",
"Args": {
Expand All @@ -282,11 +317,13 @@ Some Serilog packages require a reference to a logger configuration object. The

When the configuration specifies a discrete value for a parameter (such as a string literal), the package will attempt to convert that value to the target method's declared CLR type of the parameter. Additional explicit handling is provided for parsing strings to `Uri`, `TimeSpan`, `enum`, arrays and custom collections.

Since version 7.0.0, conversion will use the invariant culture (`CultureInfo.InvariantCulture`) as long as the `ReadFrom.Configuration(IConfiguration configuration, ConfigurationReaderOptions options)` method is used. Obsolete methods use the current culture to preserve backward compatibility.

### Static member support

Static member access can be used for passing to the configuration argument via [special](https://github.com/serilog/serilog-settings-configuration/blob/dev/test/Serilog.Settings.Configuration.Tests/StringArgumentValueTests.cs#L35) syntax:

```json
```yaml
{
"Args": {
"encoding": "System.Text.Encoding::UTF8",
Expand All @@ -299,14 +336,15 @@ Static member access can be used for passing to the configuration argument via [

If the parameter value is not a discrete value, it will try to find a best matching public constructor for the argument:

```json
```yaml
{
"Name": "Console",
"Args": {
"formatter": {
// `type` (or $type) is optional, must be specified for abstract declared parameter types
"type": "Serilog.Templates.ExpressionTemplate, Serilog.Expressions",
"template": "[{@t:HH:mm:ss} {@l:u3} {Coalesce(SourceContext, '<none>')}] {@m}\n{@x}"
}
}
}
```
Expand All @@ -317,7 +355,7 @@ For other cases the package will use the configuration binding system provided b

If parameter type is an interface or an abstract class you need to specify the full type name that implements abstract type. The implementation type should have parameterless constructor.

```json
```yaml
"Destructure": [
{ "Name": "With", "Args": { "policy": "Sample.CustomPolicy, Sample" } },
...
Expand Down Expand Up @@ -377,8 +415,9 @@ public class Startup : FunctionsStartup
var functionDependencyContext = DependencyContext.Load(typeof(Startup).Assembly);

var hostConfig = sp.GetRequiredService<IConfiguration>();
var options = new ConfigurationReaderOptions(functionDependencyContext) { SectionName = "AzureFunctionsJobHost:Serilog" };
var logger = new LoggerConfiguration()
.ReadFrom.Configuration(hostConfig, sectionName: "AzureFunctionsJobHost:Serilog", dependencyContext: functionDependencyContext)
.ReadFrom.Configuration(hostConfig, options)
.CreateLogger();

return new SerilogLoggerProvider(logger, dispose: true);
Expand All @@ -405,3 +444,7 @@ In order to make auto-discovery of configuration assemblies work, modify Functio

</Project>
```

### Versioning

This package tracks the versioning and target framework support of its [_Microsoft.Extensions.Configuration_](https://nuget.org/packages/Microsoft.Extensions.Configuration) dependency.
20 changes: 19 additions & 1 deletion appveyor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,27 @@ skip_tags: true
image:
- Visual Studio 2022
- Ubuntu
- macOS

build_script:
- pwsh: ./Build.ps1
- pwsh: |
if ($isWindows) {
Invoke-WebRequest "https://dot.net/v1/dotnet-install.ps1" -OutFile "./dotnet-install.ps1"
./dotnet-install.ps1 -JSonFile global.json -Architecture x64 -InstallDir 'C:\Program Files\dotnet'
./Build.ps1
}
if ($isLinux) {
Invoke-WebRequest "https://dot.net/v1/dotnet-install.sh" -OutFile "./dotnet-install.sh"
sudo chmod u+x dotnet-install.sh
sudo ./dotnet-install.sh --jsonfile global.json --architecture x64 --install-dir '/usr/share/dotnet'
./Build.ps1
}
if ($isMacOS) {
Invoke-WebRequest "https://dot.net/v1/dotnet-install.sh" -OutFile "./dotnet-install.sh"
sudo chmod u+x dotnet-install.sh
sudo ./dotnet-install.sh --jsonfile global.json --architecture x64 --install-dir '/usr/local/share/dotnet'
./Build.ps1
}
test: off

Expand Down
7 changes: 7 additions & 0 deletions global.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"sdk": {
"version": "7.0.201",
"allowPrerelease": false,
"rollForward": "latestFeature"
}
}
21 changes: 21 additions & 0 deletions sample/Sample/CustomFilter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
using Serilog.Core;
using Serilog.Events;

namespace Sample;

// The filter syntax in the sample configuration file is
// processed by the Serilog.Filters.Expressions package.
public class CustomFilter : ILogEventFilter
{
readonly LogEventLevel _levelFilter;

public CustomFilter(LogEventLevel levelFilter = LogEventLevel.Information)
{
_levelFilter = levelFilter;
}

public bool IsEnabled(LogEvent logEvent)
{
return logEvent.Level >= _levelFilter;
}
}
Loading

0 comments on commit e878335

Please sign in to comment.