nuget updates
This commit is contained in:
518
local-nugets/serilog.settings.configuration/8.0.0/README.md
Normal file
518
local-nugets/serilog.settings.configuration/8.0.0/README.md
Normal file
@@ -0,0 +1,518 @@
|
||||
# Serilog.Settings.Configuration [](https://ci.appveyor.com/project/serilog/serilog-settings-configuration/branch/master) [](https://www.nuget.org/packages/Serilog.Settings.Configuration/)
|
||||
|
||||
A Serilog settings provider that reads from [Microsoft.Extensions.Configuration](https://docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration/?view=aspnetcore-3.1) sources, including .NET Core's `appsettings.json` file.
|
||||
|
||||
By default, configuration is read from the `Serilog` section.
|
||||
|
||||
```json
|
||||
{
|
||||
"Serilog": {
|
||||
"Using": [ "Serilog.Sinks.Console", "Serilog.Sinks.File" ],
|
||||
"MinimumLevel": "Debug",
|
||||
"WriteTo": [
|
||||
{ "Name": "Console" },
|
||||
{ "Name": "File", "Args": { "path": "Logs/log.txt" } }
|
||||
],
|
||||
"Enrich": [ "FromLogContext", "WithMachineName", "WithThreadId" ],
|
||||
"Destructure": [
|
||||
{ "Name": "With", "Args": { "policy": "Sample.CustomPolicy, Sample" } },
|
||||
{ "Name": "ToMaximumDepth", "Args": { "maximumDestructuringDepth": 4 } },
|
||||
{ "Name": "ToMaximumStringLength", "Args": { "maximumStringLength": 100 } },
|
||||
{ "Name": "ToMaximumCollectionCount", "Args": { "maximumCollectionCount": 10 } }
|
||||
],
|
||||
"Properties": {
|
||||
"Application": "Sample"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
After installing this package, use `ReadFrom.Configuration()` and pass an `IConfiguration` object.
|
||||
|
||||
```csharp
|
||||
static void Main(string[] args)
|
||||
{
|
||||
var configuration = new ConfigurationBuilder()
|
||||
.SetBasePath(Directory.GetCurrentDirectory())
|
||||
.AddJsonFile("appsettings.json")
|
||||
.AddJsonFile($"appsettings.{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") ?? "Production"}.json", true)
|
||||
.Build();
|
||||
|
||||
var logger = new LoggerConfiguration()
|
||||
.ReadFrom.Configuration(configuration)
|
||||
.CreateLogger();
|
||||
|
||||
logger.Information("Hello, world!");
|
||||
}
|
||||
```
|
||||
|
||||
This example relies on the _[Microsoft.Extensions.Configuration.Json](https://www.nuget.org/packages/Microsoft.Extensions.Configuration.Json/)_, _[Serilog.Sinks.Console](https://github.com/serilog/serilog-sinks-console)_, _[Serilog.Sinks.File](https://github.com/serilog/serilog-sinks-file)_, _[Serilog.Enrichers.Environment](https://github.com/serilog/serilog-enrichers-environment)_ and _[Serilog.Enrichers.Thread](https://github.com/serilog/serilog-enrichers-thread)_ packages also being installed.
|
||||
|
||||
For a more sophisticated example go to the [sample](sample/Sample) folder.
|
||||
|
||||
## Syntax description
|
||||
|
||||
### Root section name
|
||||
|
||||
Root section name can be changed:
|
||||
|
||||
```yaml
|
||||
{
|
||||
"CustomSection": {
|
||||
...
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
```csharp
|
||||
var options = new ConfigurationReaderOptions { SectionName = "CustomSection" };
|
||||
var logger = new LoggerConfiguration()
|
||||
.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.
|
||||
|
||||
```yaml
|
||||
"Serilog": {
|
||||
"Using": [ "Serilog.Sinks.Console", "Serilog.Enrichers.Thread", /* ... */ ],
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
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:
|
||||
|
||||
```yaml
|
||||
{
|
||||
"Serilog": {
|
||||
"MinimumLevel": "Debug",
|
||||
"WriteTo": [ "Console" ],
|
||||
...
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
In order to utilize this convention for .NET Framework projects which are built with .NET Core CLI tools specify `PreserveCompilationContext` to `true` in the csproj properties:
|
||||
|
||||
```xml
|
||||
<PropertyGroup Condition=" '$(TargetFramework)' == 'net46' ">
|
||||
<PreserveCompilationContext>true</PreserveCompilationContext>
|
||||
</PropertyGroup>
|
||||
```
|
||||
|
||||
In case of [non-standard](#azure-functions-v2-v3) dependency management you can pass a custom `DependencyContext` object:
|
||||
|
||||
```csharp
|
||||
var functionDependencyContext = DependencyContext.Load(typeof(Startup).Assembly);
|
||||
|
||||
var options = new ConfigurationReaderOptions(functionDependencyContext) { SectionName = "AzureFunctionsJobHost:Serilog" };
|
||||
var logger = new LoggerConfiguration()
|
||||
.ReadFrom.Configuration(hostConfig, options)
|
||||
.CreateLogger();
|
||||
```
|
||||
|
||||
Alternatively, you can also pass an array of configuration assemblies:
|
||||
|
||||
```csharp
|
||||
var configurationAssemblies = new[]
|
||||
{
|
||||
typeof(ConsoleLoggerConfigurationExtensions).Assembly,
|
||||
typeof(FileLoggerConfigurationExtensions).Assembly,
|
||||
};
|
||||
var options = new ConfigurationReaderOptions(configurationAssemblies);
|
||||
var logger = new LoggerConfiguration()
|
||||
.ReadFrom.Configuration(configuration, options)
|
||||
.CreateLogger();
|
||||
```
|
||||
|
||||
For legacy .NET Framework projects it also scans default probing path(s).
|
||||
|
||||
For all other cases, as well as in the case of non-conventional configuration assembly names **DO** use [Using](#using-section-and-auto-discovery-of-configuration-assemblies) section.
|
||||
|
||||
#### .NET 5.0 onwards Single File Applications
|
||||
|
||||
Currently, auto-discovery of configuration assemblies is not supported in bundled mode. **DO** use [Using](#using-section-and-auto-discovery-of-configuration-assemblies) section or explicitly pass a collection of configuration assemblies for workaround.
|
||||
|
||||
### MinimumLevel, LevelSwitches, overrides and dynamic reload
|
||||
|
||||
The `MinimumLevel` configuration property can be set to a single value as in the sample above, or, levels can be overridden per logging source.
|
||||
|
||||
This is useful in ASP.NET Core applications, which will often specify minimum level as:
|
||||
|
||||
```json
|
||||
"MinimumLevel": {
|
||||
"Default": "Information",
|
||||
"Override": {
|
||||
"Microsoft": "Warning",
|
||||
"System": "Warning"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
`MinimumLevel` section also respects dynamic reload if the underlying provider supports it.
|
||||
|
||||
```csharp
|
||||
var configuration = new ConfigurationBuilder()
|
||||
.SetBasePath(Directory.GetCurrentDirectory())
|
||||
.AddJsonFile(path: "appsettings.json", reloadOnChange: true)
|
||||
.Build();
|
||||
```
|
||||
|
||||
Any changes for `Default`, `Microsoft`, `System` sources will be applied at runtime.
|
||||
|
||||
(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:
|
||||
|
||||
```json
|
||||
{
|
||||
"Serilog": {
|
||||
"LevelSwitches": { "controlSwitch": "Verbose" },
|
||||
"WriteTo": [
|
||||
{
|
||||
"Name": "Seq",
|
||||
"Args": {
|
||||
"serverUrl": "http://localhost:5341",
|
||||
"apiKey": "yeEZyL3SMcxEKUijBjN",
|
||||
"controlLevelSwitch": "$controlSwitch"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
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:
|
||||
|
||||
```json
|
||||
"WriteTo": [ "Console", "DiagnosticTrace" ]
|
||||
```
|
||||
|
||||
Or alternatively, the long-form (`"Name":` ...) syntax from the example above can be used when arguments need to be supplied.
|
||||
|
||||
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:
|
||||
|
||||
```yaml
|
||||
"WriteTo": {
|
||||
"0": "Console",
|
||||
"1": "DiagnosticTrace"
|
||||
}
|
||||
```
|
||||
|
||||
And
|
||||
|
||||
```yaml
|
||||
"WriteTo:0": "Console",
|
||||
"WriteTo:1": "DiagnosticTrace"
|
||||
```
|
||||
|
||||
(The result paths for the keys will be the same, i.e. `Serilog:WriteTo:0` and `Serilog:WriteTo:1`)
|
||||
|
||||
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:
|
||||
|
||||
```yaml
|
||||
"WriteTo": {
|
||||
"ConsoleSink": "Console",
|
||||
"DiagnosticTraceSink": { "Name": "DiagnosticTrace" }
|
||||
}
|
||||
```
|
||||
|
||||
### Properties section
|
||||
|
||||
This section defines a static list of key-value pairs that will enrich log events.
|
||||
|
||||
### Filter section
|
||||
|
||||
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:
|
||||
|
||||
```yaml
|
||||
"Filter": [{
|
||||
"Name": "ByIncludingOnly",
|
||||
"Args": {
|
||||
"expression": "Application = 'Sample'"
|
||||
}
|
||||
}]
|
||||
```
|
||||
|
||||
Using this package you can also declare `LoggingFilterSwitch`-es in custom section and reference them for filter parameters:
|
||||
|
||||
```yaml
|
||||
{
|
||||
"Serilog": {
|
||||
"FilterSwitches": { "filterSwitch": "Application = 'Sample'" },
|
||||
"Filter": [
|
||||
{
|
||||
"Name": "ControlledBy",
|
||||
"Args": {
|
||||
"switch": "$filterSwitch"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
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:
|
||||
|
||||
```yaml
|
||||
"WriteTo:Async": {
|
||||
"Name": "Async",
|
||||
"Args": {
|
||||
"configure": [
|
||||
{
|
||||
"Name": "File",
|
||||
"Args": {
|
||||
"path": "%TEMP%/Logs/serilog-configuration-sample.txt",
|
||||
"outputTemplate":
|
||||
"{Timestamp:o} [{Level:u3}] ({Application}/{MachineName}/{ThreadId}) {Message}{NewLine}{Exception}"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
```
|
||||
|
||||
### Destructuring
|
||||
|
||||
Destructuring means extracting pieces of information from an object and create properties with values; Serilog offers the `@` [structure-capturing operator](https://github.com/serilog/serilog/wiki/Structured-Data#preserving-object-structure). In case there is a need to customize the way log events are serialized (e.g., hide property values or replace them with something else), one can define several destructuring policies, like this:
|
||||
|
||||
```yaml
|
||||
"Destructure": [
|
||||
{
|
||||
"Name": "With",
|
||||
"Args": {
|
||||
"policy": "MyFirstNamespace.FirstDestructuringPolicy, MyFirstAssembly"
|
||||
}
|
||||
},
|
||||
{
|
||||
"Name": "With",
|
||||
"Args": {
|
||||
"policy": "policy": "MySecondNamespace.SecondDestructuringPolicy, MySecondAssembly"
|
||||
}
|
||||
},
|
||||
{
|
||||
"Name": "With",
|
||||
"Args": {
|
||||
"policy": "policy": "MyThirdNamespace.ThirdDestructuringPolicy, MyThirdAssembly"
|
||||
}
|
||||
},
|
||||
],
|
||||
```
|
||||
|
||||
This is how the first destructuring policy would look like:
|
||||
|
||||
```csharp
|
||||
namespace MyFirstNamespace;
|
||||
|
||||
public record MyDto(int Id, int Name);
|
||||
|
||||
public class FirstDestructuringPolicy : IDestructuringPolicy
|
||||
{
|
||||
public bool TryDestructure(object value, ILogEventPropertyValueFactory propertyValueFactory,
|
||||
[NotNullWhen(true)] out LogEventPropertyValue? result)
|
||||
{
|
||||
if (value is not MyDto dto)
|
||||
{
|
||||
result = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
result = new StructureValue(new List<LogEventProperty>
|
||||
{
|
||||
new LogEventProperty("Identifier", new ScalarValue(deleteTodoItemInfo.Id)),
|
||||
new LogEventProperty("NormalizedName", new ScalarValue(dto.Name.ToUpperInvariant()))
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Assuming Serilog needs to destructure an argument of type **MyDto** when handling a log event:
|
||||
|
||||
```csharp
|
||||
logger.Information("About to process input: {@MyDto} ...", myDto);
|
||||
```
|
||||
|
||||
it will apply **FirstDestructuringPolicy** which will convert **MyDto** instance to a **StructureValue** instance; a Serilog console sink would write the following entry:
|
||||
|
||||
```text
|
||||
About to process input: {"Identifier": 191, "NormalizedName": "SOME_UPPER_CASE_NAME"} ...
|
||||
```
|
||||
|
||||
## Arguments binding
|
||||
|
||||
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:
|
||||
|
||||
```yaml
|
||||
{
|
||||
"Args": {
|
||||
"encoding": "System.Text.Encoding::UTF8",
|
||||
"theme": "Serilog.Sinks.SystemConsole.Themes.AnsiConsoleTheme::Code, Serilog.Sinks.Console"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Complex parameter value binding
|
||||
|
||||
If the parameter value is not a discrete value, it will try to find a best matching public constructor for the argument:
|
||||
|
||||
```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}"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
For other cases the package will use the configuration binding system provided by _[Microsoft.Extensions.Options.ConfigurationExtensions](https://www.nuget.org/packages/Microsoft.Extensions.Options.ConfigurationExtensions/)_ to attempt to populate the parameter. Almost anything that can be bound by `IConfiguration.Get<T>` should work with this package. An example of this is the optional `List<Column>` parameter used to configure the .NET Standard version of the _[Serilog.Sinks.MSSqlServer](https://github.com/serilog/serilog-sinks-mssqlserver)_ package.
|
||||
|
||||
### Abstract parameter types
|
||||
|
||||
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.
|
||||
|
||||
```yaml
|
||||
"Destructure": [
|
||||
{ "Name": "With", "Args": { "policy": "Sample.CustomPolicy, Sample" } },
|
||||
...
|
||||
],
|
||||
```
|
||||
|
||||
### IConfiguration parameter
|
||||
|
||||
If a Serilog package requires additional external configuration information (for example, access to a `ConnectionStrings` section, which would be outside of the `Serilog` section), the sink should include an `IConfiguration` parameter in the configuration extension method. This package will automatically populate that parameter. It should not be declared in the argument list in the configuration source.
|
||||
|
||||
### IConfigurationSection parameters
|
||||
|
||||
Certain Serilog packages may require configuration information that can't be easily represented by discrete values or direct binding-friendly representations. An example might be lists of values to remove from a collection of default values. In this case the method can accept an entire `IConfigurationSection` as a call parameter and this package will recognize that and populate the parameter. In this way, Serilog packages can support arbitrarily complex configuration scenarios.
|
||||
|
||||
## Samples
|
||||
|
||||
### Azure Functions (v2, v3)
|
||||
|
||||
hosts.json
|
||||
|
||||
```json
|
||||
{
|
||||
"version": "2.0",
|
||||
"logging": {
|
||||
"applicationInsights": {
|
||||
"samplingExcludedTypes": "Request",
|
||||
"samplingSettings": {
|
||||
"isEnabled": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"Serilog": {
|
||||
"MinimumLevel": {
|
||||
"Default": "Information",
|
||||
"Override": {
|
||||
"Microsoft": "Warning",
|
||||
"System": "Warning"
|
||||
}
|
||||
},
|
||||
"Enrich": [ "FromLogContext" ],
|
||||
"WriteTo": [
|
||||
{ "Name": "Seq", "Args": { "serverUrl": "http://localhost:5341" } }
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
In `Startup.cs` section name should be prefixed with [AzureFunctionsJobHost](https://docs.microsoft.com/en-us/azure/azure-functions/functions-app-settings#azurefunctionsjobhost__)
|
||||
|
||||
```csharp
|
||||
public class Startup : FunctionsStartup
|
||||
{
|
||||
public override void Configure(IFunctionsHostBuilder builder)
|
||||
{
|
||||
builder.Services.AddSingleton<ILoggerProvider>(sp =>
|
||||
{
|
||||
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, options)
|
||||
.CreateLogger();
|
||||
|
||||
return new SerilogLoggerProvider(logger, dispose: true);
|
||||
});
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
In order to make auto-discovery of configuration assemblies work, modify Function's csproj file
|
||||
|
||||
```xml
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<!-- ... -->
|
||||
|
||||
<!-- add this targets -->
|
||||
<Target Name="FunctionsPostBuildDepsCopy" AfterTargets="PostBuildEvent">
|
||||
<Copy SourceFiles="$(OutDir)$(AssemblyName).deps.json" DestinationFiles="$(OutDir)bin\$(AssemblyName).deps.json" />
|
||||
</Target>
|
||||
|
||||
<Target Name="FunctionsPublishDepsCopy" AfterTargets="Publish">
|
||||
<Copy SourceFiles="$(OutDir)$(AssemblyName).deps.json" DestinationFiles="$(PublishDir)bin\$(AssemblyName).deps.json" />
|
||||
</Target>
|
||||
|
||||
</Project>
|
||||
```
|
||||
|
||||
### Versioning
|
||||
|
||||
This package tracks the versioning and target framework support of its [_Microsoft.Extensions.Configuration_](https://nuget.org/packages/Microsoft.Extensions.Configuration) dependency.
|
||||
Reference in New Issue
Block a user