зеркало из https://github.com/SteeltoeOSS/Logging.git
Родитель
0f958ce840
Коммит
5e51521a93
14
Logging.sln
14
Logging.sln
|
@ -27,6 +27,10 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
|
|||
stylecop.json = stylecop.json
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Steeltoe.Extensions.Logging.SerilogDynamicLogger", "src\Steeltoe.Extensions.Logging.SerilogDynamicLogger\Steeltoe.Extensions.Logging.SerilogDynamicLogger.csproj", "{C4F8B0B3-86C8-45AA-88EB-A18570B2754E}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Steeltoe.Extensions.Logging.SerilogDynamicLogger.Test", "test\Steeltoe.Extensions.Logging.SerilogDynamicLogger.Test\Steeltoe.Extensions.Logging.SerilogDynamicLogger.Test.csproj", "{DF66D833-EAC4-4C84-A80F-74CFBD2BF78F}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
|
@ -41,6 +45,14 @@ Global
|
|||
{CBD7C37D-6CDC-4058-9B68-68EDC87837FD}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{CBD7C37D-6CDC-4058-9B68-68EDC87837FD}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{CBD7C37D-6CDC-4058-9B68-68EDC87837FD}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{C4F8B0B3-86C8-45AA-88EB-A18570B2754E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{C4F8B0B3-86C8-45AA-88EB-A18570B2754E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{C4F8B0B3-86C8-45AA-88EB-A18570B2754E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{C4F8B0B3-86C8-45AA-88EB-A18570B2754E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{DF66D833-EAC4-4C84-A80F-74CFBD2BF78F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{DF66D833-EAC4-4C84-A80F-74CFBD2BF78F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{DF66D833-EAC4-4C84-A80F-74CFBD2BF78F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{DF66D833-EAC4-4C84-A80F-74CFBD2BF78F}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
@ -48,6 +60,8 @@ Global
|
|||
GlobalSection(NestedProjects) = preSolution
|
||||
{BCF90E1F-ADD2-42A2-8601-AB7A5C9FAFC4} = {26E1A61B-FA79-41BF-9C3B-5A04299F356A}
|
||||
{CBD7C37D-6CDC-4058-9B68-68EDC87837FD} = {EEF15943-96DB-44B5-BA4A-1D11171AD74F}
|
||||
{C4F8B0B3-86C8-45AA-88EB-A18570B2754E} = {26E1A61B-FA79-41BF-9C3B-5A04299F356A}
|
||||
{DF66D833-EAC4-4C84-A80F-74CFBD2BF78F} = {EEF15943-96DB-44B5-BA4A-1D11171AD74F}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {F03D9805-6C7E-411E-A8D5-191ABE8D2F66}
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
// Copyright 2017 the original author or authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
namespace Steeltoe.Extensions.Logging.SerilogDynamicLogger
|
||||
{
|
||||
public interface ISerilogOptions
|
||||
{
|
||||
MinimumLevel MinimumLevel { get; set; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
// Copyright 2017 the original author or authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.DependencyInjection.Extensions;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Logging.Configuration;
|
||||
using Microsoft.Extensions.Logging.Console;
|
||||
using Microsoft.Extensions.Options;
|
||||
using System.Linq;
|
||||
|
||||
namespace Steeltoe.Extensions.Logging.SerilogDynamicLogger
|
||||
{
|
||||
public static class SerilogBuilderExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Add Steeltoe logger wrapped in a <see cref="IDynamicLoggerProvider"/> that supports
|
||||
/// dynamically controlling the minimum log level via management endpoints
|
||||
/// </summary>
|
||||
/// <param name="builder">The <see cref="ILoggingBuilder"/> for configuring the LoggerFactory </param>
|
||||
/// <returns>The configured <see cref="ILoggingBuilder"/></returns>
|
||||
public static ILoggingBuilder AddSerilogDynamicConsole(this ILoggingBuilder builder)
|
||||
{
|
||||
builder.AddFilter<DynamicLoggerProvider>(null, LogLevel.Trace);
|
||||
builder.Services.AddSingleton<ISerilogOptions, SerilogOptions>();
|
||||
builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton<ILoggerProvider, SerilogDynamicProvider>());
|
||||
|
||||
builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton<IOptionsChangeTokenSource<ConsoleLoggerOptions>, LoggerProviderOptionsChangeTokenSource<ConsoleLoggerOptions, ConsoleLoggerProvider>>());
|
||||
builder.Services.AddSingleton<IDynamicLoggerProvider>((p) => p.GetServices<ILoggerProvider>().OfType<IDynamicLoggerProvider>().SingleOrDefault());
|
||||
return builder;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,199 @@
|
|||
// Copyright 2017 the original author or authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Serilog.AspNetCore;
|
||||
using Serilog.Core;
|
||||
using Serilog.Events;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using static Serilog.ConfigurationLoggerConfigurationExtensions;
|
||||
|
||||
namespace Steeltoe.Extensions.Logging.SerilogDynamicLogger
|
||||
{
|
||||
/// <summary>
|
||||
/// A wrapper for the <see cref="Serilog.Logger"/> to dynamically set log levels
|
||||
/// </summary>
|
||||
public class SerilogDynamicProvider : IDynamicLoggerProvider
|
||||
{
|
||||
private Logger _globalLogger;
|
||||
private ISerilogOptions _serilogOptions;
|
||||
|
||||
private ConcurrentDictionary<string, ILogger> _loggers = new ConcurrentDictionary<string, ILogger>();
|
||||
private ConcurrentDictionary<string, LoggingLevelSwitch> _loggerSwitches = new ConcurrentDictionary<string, LoggingLevelSwitch>();
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SerilogDynamicProvider"/> class.
|
||||
/// Any Serilog settings can be passed in the IConfiguration as needed.
|
||||
/// </summary>
|
||||
/// <param name="configuration">Serilog readable <see cref="IConfiguration"/></param>
|
||||
/// <param name="options">Subset of Serilog options managed by wrapper<see cref="ISerilogOptions"/></param>
|
||||
public SerilogDynamicProvider(IConfiguration configuration, ISerilogOptions options = null)
|
||||
{
|
||||
if (configuration == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(configuration));
|
||||
}
|
||||
|
||||
_serilogOptions = options ?? new SerilogOptions(configuration);
|
||||
|
||||
// Add a level switch that controls the "Default" level at the root
|
||||
var levelSwitch = new LoggingLevelSwitch(_serilogOptions.MinimumLevel.Default);
|
||||
_loggerSwitches.GetOrAdd("Default", levelSwitch);
|
||||
|
||||
// Add a global logger that will be the root of all other added loggers
|
||||
_globalLogger = new Serilog.LoggerConfiguration()
|
||||
.MinimumLevel.ControlledBy(levelSwitch)
|
||||
.ReadFrom.Configuration(configuration)
|
||||
.CreateLogger();
|
||||
}
|
||||
|
||||
public ILogger CreateLogger(string categoryName)
|
||||
{
|
||||
LogEventLevel eventLevel = _serilogOptions.MinimumLevel.Default;
|
||||
|
||||
foreach (var overrideOption in _serilogOptions.MinimumLevel.Override)
|
||||
{
|
||||
if (categoryName.StartsWith(overrideOption.Key))
|
||||
{
|
||||
eventLevel = overrideOption.Value;
|
||||
}
|
||||
}
|
||||
|
||||
// Chain new loggers to the global loggers with its own switch
|
||||
// taking into accound any "Overrides"
|
||||
var levelSwitch = new LoggingLevelSwitch(eventLevel);
|
||||
_loggerSwitches.GetOrAdd(categoryName, levelSwitch);
|
||||
var serilogger = new Serilog.LoggerConfiguration()
|
||||
.MinimumLevel.ControlledBy(levelSwitch)
|
||||
.WriteTo.Logger(_globalLogger)
|
||||
.CreateLogger();
|
||||
var factory = new SerilogLoggerFactory(serilogger, true);
|
||||
|
||||
return _loggers.GetOrAdd(categoryName, factory.CreateLogger(categoryName));
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_globalLogger.Dispose();
|
||||
_loggerSwitches = null;
|
||||
_loggers = null;
|
||||
}
|
||||
|
||||
public ICollection<ILoggerConfiguration> GetLoggerConfigurations()
|
||||
{
|
||||
var results = new Dictionary<string, ILoggerConfiguration>();
|
||||
|
||||
// get the default first
|
||||
LogLevel configuredDefault = GetConfiguredLevel("Default") ?? LogLevel.None;
|
||||
LogLevel effectiveDefault = GetEffectiveLevel("Default");
|
||||
results.Add("Default", new LoggerConfiguration("Default", configuredDefault, effectiveDefault));
|
||||
|
||||
// then get all running loggers
|
||||
foreach (var logger in _loggers)
|
||||
{
|
||||
foreach (var name in GetKeyPrefixes(logger.Key))
|
||||
{
|
||||
if (name != "Default")
|
||||
{
|
||||
LogLevel? configured = GetConfiguredLevel(name);
|
||||
LogLevel effective = GetEffectiveLevel(logger.Key);
|
||||
var config = new LoggerConfiguration(name, configured, effective);
|
||||
if (results.ContainsKey(name))
|
||||
{
|
||||
if (!results[name].Equals(config))
|
||||
{
|
||||
throw new InvalidProgramException("Shouldn't happen");
|
||||
}
|
||||
}
|
||||
|
||||
results[name] = config;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return results.Values;
|
||||
}
|
||||
|
||||
public void SetLogLevel(string category, LogLevel? level)
|
||||
{
|
||||
var filteredPairs = _loggerSwitches.Where(kvp => kvp.Key.StartsWith(category));
|
||||
foreach (var kvp in filteredPairs)
|
||||
{
|
||||
var currentLevel = level ?? GetConfiguredLevel(kvp.Key);
|
||||
if (currentLevel != null)
|
||||
{
|
||||
kvp.Value.MinimumLevel = ToSerilogLevel(currentLevel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private LogLevel? GetConfiguredLevel(string name)
|
||||
{
|
||||
LogLevel? returnValue = null;
|
||||
if (name == "Default")
|
||||
{
|
||||
returnValue = (LogLevel)_serilogOptions.MinimumLevel.Default;
|
||||
}
|
||||
else
|
||||
{
|
||||
var overrides = _serilogOptions.MinimumLevel.Override;
|
||||
if (overrides != null
|
||||
&& overrides.ContainsKey(name)
|
||||
&& overrides.TryGetValue(name, out LogEventLevel configuredLevel))
|
||||
{
|
||||
returnValue = (LogLevel)configuredLevel;
|
||||
}
|
||||
}
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
private LogLevel GetEffectiveLevel(string name)
|
||||
{
|
||||
LoggingLevelSwitch levelSwitch;
|
||||
_loggerSwitches.TryGetValue(name, out levelSwitch);
|
||||
return (LogLevel)levelSwitch.MinimumLevel;
|
||||
}
|
||||
|
||||
private IEnumerable<string> GetKeyPrefixes(string name)
|
||||
{
|
||||
while (!string.IsNullOrEmpty(name))
|
||||
{
|
||||
yield return name;
|
||||
var lastIndexOfDot = name.LastIndexOf('.');
|
||||
if (lastIndexOfDot == -1)
|
||||
{
|
||||
yield return "Default";
|
||||
break;
|
||||
}
|
||||
|
||||
name = name.Substring(0, lastIndexOfDot);
|
||||
}
|
||||
}
|
||||
|
||||
private LogEventLevel ToSerilogLevel(LogLevel? level)
|
||||
{
|
||||
if (level == null || level == LogLevel.None)
|
||||
{
|
||||
return LogEventLevel.Fatal;
|
||||
}
|
||||
|
||||
return (LogEventLevel)level;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
// Copyright 2017 the original author or authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Serilog.Events;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Steeltoe.Extensions.Logging.SerilogDynamicLogger
|
||||
{
|
||||
/// <summary>
|
||||
/// Implements a subset of the Serilog Options needed for SerilogDynamicProvider
|
||||
/// </summary>
|
||||
public class SerilogOptions : ISerilogOptions
|
||||
{
|
||||
private const string CONFIG_PATH = "Serilog";
|
||||
|
||||
/// <summary>
|
||||
/// This controls the root logger (and the "Default") and
|
||||
/// limits the verbosity of all other overrides to this setting
|
||||
/// </summary>
|
||||
public MinimumLevel MinimumLevel { get; set; }
|
||||
|
||||
public SerilogOptions(IConfiguration configuration)
|
||||
{
|
||||
var section = configuration.GetSection(CONFIG_PATH);
|
||||
section.Bind(this);
|
||||
if (MinimumLevel == null)
|
||||
{
|
||||
MinimumLevel = new MinimumLevel()
|
||||
{
|
||||
Default = LogEventLevel.Verbose, // Set root to verbose to have sub loggers work at all levels
|
||||
Override = new Dictionary<string, LogEventLevel>()
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#pragma warning disable SA1402 // File may only contain a single class
|
||||
public class MinimumLevel
|
||||
#pragma warning restore SA1402 // File may only contain a single class
|
||||
{
|
||||
public LogEventLevel Default { get; set; }
|
||||
|
||||
public Dictionary<string, LogEventLevel> Override { get; set; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Import Project="..\..\config\versions.props" />
|
||||
<PropertyGroup>
|
||||
<Description>Steeltoe Console Logger</Description>
|
||||
<Authors>Pivotal;hsarella</Authors>
|
||||
<VersionPrefix>$(SteeltoeVersion)</VersionPrefix>
|
||||
<VersionSuffix>$(VersionSuffix)</VersionSuffix>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
<AssemblyName>Steeltoe.Extensions.Logging.SerilogDynamicLogger</AssemblyName>
|
||||
<PackageId>Steeltoe.Extensions.Logging.SerilogDynamicLogger</PackageId>
|
||||
<PackageTags>Spring Cloud;Logging;Management</PackageTags>
|
||||
<PackageIconUrl>https://steeltoe.io/images/transparent.png</PackageIconUrl>
|
||||
<PackageProjectUrl>https://steeltoe.io</PackageProjectUrl>
|
||||
<PackageLicenseUrl>https://www.apache.org/licenses/LICENSE-2.0</PackageLicenseUrl>
|
||||
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
|
||||
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
|
||||
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||
<NoWarn>SA1101;SA1124;SA1201;SA1309;SA1310;SA1401;SA1600;SA1652;1591</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.Logging" Version="2.2.0" />
|
||||
<PackageReference Include="Serilog.AspNetCore" Version="2.1.1" />
|
||||
<PackageReference Include="Serilog.Filters.Expressions" Version="2.0.0" />
|
||||
<PackageReference Include="Serilog.Settings.Configuration" Version="3.0.1" />
|
||||
<PackageReference Include="Serilog.Sinks.Console" Version="3.1.1" />
|
||||
<PackageReference Include="StyleCop.Analyzers" Version="1.0.2">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<AdditionalFiles Include="..\..\stylecop.json">
|
||||
<Link>stylecop.json</Link>
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</AdditionalFiles>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Steeltoe.Extensions.Logging.DynamicLogger\Steeltoe.Extensions.Logging.DynamicLogger.csproj" />
|
||||
</ItemGroup>
|
||||
</Project>
|
|
@ -0,0 +1,43 @@
|
|||
// Copyright 2017 the original author or authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace Steeltoe.Extensions.Logging.SerilogDynamicLogger.Test
|
||||
{
|
||||
internal class ConsoleOutputBorrower : IDisposable
|
||||
{
|
||||
private StringWriter _borrowedOutput;
|
||||
private TextWriter _originalOutput;
|
||||
|
||||
public ConsoleOutputBorrower()
|
||||
{
|
||||
_borrowedOutput = new StringWriter();
|
||||
_originalOutput = Console.Out;
|
||||
Console.SetOut(_borrowedOutput);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return _borrowedOutput.ToString();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Console.SetOut(_originalOutput);
|
||||
_borrowedOutput.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
// Copyright 2017 the original author or authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Logging.Console;
|
||||
using Serilog.Events;
|
||||
using System.Collections.Generic;
|
||||
using Xunit;
|
||||
|
||||
namespace Steeltoe.Extensions.Logging.SerilogDynamicLogger.Test
|
||||
{
|
||||
public class SerilogDynamicLoggerConfigurationExtensionsTest
|
||||
{
|
||||
[Fact]
|
||||
public void SerilogOptions_Set_Correctly()
|
||||
{
|
||||
// arrange
|
||||
var appSettings = new Dictionary<string, string>
|
||||
{
|
||||
{ "Serilog:MinimumLevel:Default", "Error" },
|
||||
{ "Serilog:MinimumLevel:Override:Microsoft", "Warning" },
|
||||
{ "Serilog:MinimumLevel:Override:Steeltoe.Extensions", "Verbose" },
|
||||
{ "Serilog:MinimumLevel:Override:Steeltoe", "Information" }
|
||||
};
|
||||
var builder = new ConfigurationBuilder().AddInMemoryCollection(appSettings);
|
||||
|
||||
// act
|
||||
var serilogOptions = new SerilogOptions(builder.Build());
|
||||
|
||||
// assert
|
||||
Assert.Equal(LogEventLevel.Error, serilogOptions.MinimumLevel.Default);
|
||||
Assert.Equal(LogEventLevel.Warning, serilogOptions.MinimumLevel.Override["Microsoft"]);
|
||||
Assert.Equal(LogEventLevel.Information, serilogOptions.MinimumLevel.Override["Steeltoe"]);
|
||||
Assert.Equal(LogEventLevel.Verbose, serilogOptions.MinimumLevel.Override["Steeltoe.Extensions"]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SerilogOptions_NoError_When_NotConfigured()
|
||||
{
|
||||
// arrange
|
||||
var appSettings = new Dictionary<string, string>();
|
||||
var builder = new ConfigurationBuilder().AddInMemoryCollection(appSettings);
|
||||
|
||||
// act
|
||||
var serilogOptions = new SerilogOptions(builder.Build());
|
||||
|
||||
// assert
|
||||
Assert.Equal(LogEventLevel.Verbose, serilogOptions.MinimumLevel.Default);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,375 @@
|
|||
// Copyright 2017 the original author or authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Logging.Console;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using Xunit;
|
||||
|
||||
namespace Steeltoe.Extensions.Logging.SerilogDynamicLogger.Test
|
||||
{
|
||||
public class SerilogDynamicLoggerProviderTest
|
||||
{
|
||||
[Fact]
|
||||
public void Create_CreatesCorrectLogger()
|
||||
{
|
||||
var provider = new SerilogDynamicProvider(GetConfiguration());
|
||||
LoggerFactory fac = new LoggerFactory();
|
||||
fac.AddProvider(provider);
|
||||
|
||||
ILogger logger = fac.CreateLogger(typeof(A.B.C.D.TestClass));
|
||||
Assert.NotNull(logger);
|
||||
Assert.True(logger.IsEnabled(LogLevel.Information));
|
||||
Assert.False(logger.IsEnabled(LogLevel.Debug));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SetLogLevel_UpdatesLogger()
|
||||
{
|
||||
var provider = new SerilogDynamicProvider(GetConfiguration());
|
||||
LoggerFactory fac = new LoggerFactory();
|
||||
fac.AddProvider(provider);
|
||||
|
||||
ILogger logger = fac.CreateLogger(typeof(A.B.C.D.TestClass));
|
||||
Assert.NotNull(logger);
|
||||
Assert.True(logger.IsEnabled(LogLevel.Critical));
|
||||
Assert.True(logger.IsEnabled(LogLevel.Error));
|
||||
Assert.True(logger.IsEnabled(LogLevel.Warning));
|
||||
Assert.True(logger.IsEnabled(LogLevel.Information));
|
||||
Assert.False(logger.IsEnabled(LogLevel.Debug));
|
||||
|
||||
provider.SetLogLevel("A", LogLevel.Debug);
|
||||
Assert.True(logger.IsEnabled(LogLevel.Information));
|
||||
Assert.True(logger.IsEnabled(LogLevel.Debug));
|
||||
|
||||
provider.SetLogLevel("A", LogLevel.Information);
|
||||
Assert.True(logger.IsEnabled(LogLevel.Information));
|
||||
Assert.False(logger.IsEnabled(LogLevel.Debug));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SetLogLevel_UpdatesNamespaceDescendants()
|
||||
{
|
||||
// arrange (A* should log at Information)
|
||||
var provider = new SerilogDynamicProvider(GetConfiguration());
|
||||
|
||||
// act I: with original setup
|
||||
var childLogger = provider.CreateLogger("A.B.C");
|
||||
var configurations = provider.GetLoggerConfigurations();
|
||||
var tierOneNamespace = configurations.First(n => n.Name == "A");
|
||||
|
||||
// assert I: base namespace is in the response, correctly
|
||||
Assert.Equal(LogLevel.Information, tierOneNamespace.EffectiveLevel);
|
||||
|
||||
configurations = provider.GetLoggerConfigurations();
|
||||
|
||||
// act II: set A.B* to log at Trace
|
||||
provider.SetLogLevel("A.B", LogLevel.Trace);
|
||||
configurations = provider.GetLoggerConfigurations();
|
||||
|
||||
tierOneNamespace = configurations.First(n => n.Name == "A");
|
||||
var tierTwoNamespace = configurations.First(n => n.Name == "A.B");
|
||||
|
||||
// assert II: since Serilog doesnt expose filters, we can only change at the granularity of configured filters
|
||||
Assert.Equal(LogLevel.Trace, tierOneNamespace.EffectiveLevel);
|
||||
Assert.Equal(LogLevel.Trace, tierTwoNamespace.EffectiveLevel);
|
||||
Assert.True(childLogger.IsEnabled(LogLevel.Trace));
|
||||
|
||||
// act III: set A to something else, make sure it inherits down
|
||||
provider.SetLogLevel("A", LogLevel.Error);
|
||||
configurations = provider.GetLoggerConfigurations();
|
||||
tierOneNamespace = configurations.First(n => n.Name == "A");
|
||||
tierTwoNamespace = configurations.First(n => n.Name == "A.B");
|
||||
var grandchildLogger = provider.CreateLogger("A.B.C.D");
|
||||
|
||||
// assert again
|
||||
Assert.Equal(LogLevel.Error, tierOneNamespace.EffectiveLevel);
|
||||
Assert.Equal(LogLevel.Error, tierTwoNamespace.EffectiveLevel);
|
||||
Assert.False(childLogger.IsEnabled(LogLevel.Warning));
|
||||
Assert.False(grandchildLogger.IsEnabled(LogLevel.Debug));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SetLogLevel_Can_Reset_to_Default()
|
||||
{
|
||||
// arrange (A* should log at Information)
|
||||
var provider = new SerilogDynamicProvider(GetConfiguration());
|
||||
|
||||
// act I: with original setup
|
||||
var firstLogger = provider.CreateLogger("A.B.C");
|
||||
var configurations = provider.GetLoggerConfigurations();
|
||||
var tierOneNamespace = configurations.First(n => n.Name == "A");
|
||||
|
||||
// assert I: base namespace is in the response, correctly
|
||||
Assert.Equal(LogLevel.Information, tierOneNamespace.EffectiveLevel);
|
||||
|
||||
// act II: set A.B* to log at Trace
|
||||
provider.SetLogLevel("A.B", LogLevel.Trace);
|
||||
configurations = provider.GetLoggerConfigurations();
|
||||
tierOneNamespace = configurations.First(n => n.Name == "A");
|
||||
var tierTwoNamespace = configurations.First(n => n.Name == "A.B");
|
||||
|
||||
// assert II: since Serilog doesnt expose filters, we can only change at the granularity of configured overrides
|
||||
Assert.Equal(LogLevel.Trace, tierOneNamespace.EffectiveLevel);
|
||||
Assert.Equal(LogLevel.Trace, tierTwoNamespace.EffectiveLevel);
|
||||
Assert.True(firstLogger.IsEnabled(LogLevel.Trace));
|
||||
|
||||
// act III: reset A.B
|
||||
provider.SetLogLevel("A.B", null);
|
||||
configurations = provider.GetLoggerConfigurations();
|
||||
tierOneNamespace = configurations.First(n => n.Name == "A");
|
||||
tierTwoNamespace = configurations.First(n => n.Name == "A.B");
|
||||
var secondLogger = provider.CreateLogger("A.B.C.D");
|
||||
|
||||
// assert again
|
||||
Assert.Equal(LogLevel.Information, tierOneNamespace.EffectiveLevel);
|
||||
Assert.Equal(LogLevel.Information, tierTwoNamespace.EffectiveLevel);
|
||||
Assert.True(firstLogger.IsEnabled(LogLevel.Information));
|
||||
Assert.True(secondLogger.IsEnabled(LogLevel.Information));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetLoggerConfigurations_ReturnsExpected()
|
||||
{
|
||||
var provider = new SerilogDynamicProvider(GetConfiguration());
|
||||
LoggerFactory fac = new LoggerFactory();
|
||||
fac.AddProvider(provider);
|
||||
|
||||
ILogger logger = fac.CreateLogger(typeof(A.B.C.D.TestClass));
|
||||
|
||||
var logConfig = provider.GetLoggerConfigurations();
|
||||
Assert.Equal(6, logConfig.Count);
|
||||
Assert.Contains(new LoggerConfiguration("Default", LogLevel.Trace, LogLevel.Trace), logConfig);
|
||||
Assert.Contains(new LoggerConfiguration("A.B.C.D.TestClass", null, LogLevel.Information), logConfig);
|
||||
Assert.Contains(new LoggerConfiguration("A.B.C.D", null, LogLevel.Information), logConfig);
|
||||
Assert.Contains(new LoggerConfiguration("A.B.C", LogLevel.Information, LogLevel.Information), logConfig);
|
||||
Assert.Contains(new LoggerConfiguration("A.B", null, LogLevel.Information), logConfig);
|
||||
Assert.Contains(new LoggerConfiguration("A", LogLevel.Information, LogLevel.Information), logConfig);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetLoggerConfigurations_ReturnsExpected_After_SetLogLevel()
|
||||
{
|
||||
// arrange
|
||||
var provider = new SerilogDynamicProvider(GetConfiguration());
|
||||
LoggerFactory fac = new LoggerFactory();
|
||||
fac.AddProvider(provider);
|
||||
|
||||
// act I
|
||||
ILogger logger = fac.CreateLogger(typeof(A.B.C.D.TestClass));
|
||||
var logConfig = provider.GetLoggerConfigurations();
|
||||
|
||||
// assert I
|
||||
Assert.Equal(6, logConfig.Count);
|
||||
Assert.Contains(new LoggerConfiguration("Default", LogLevel.Trace, LogLevel.Trace), logConfig);
|
||||
Assert.Contains(new LoggerConfiguration("A.B.C.D.TestClass", null, LogLevel.Information), logConfig);
|
||||
Assert.Contains(new LoggerConfiguration("A.B.C.D", null, LogLevel.Information), logConfig);
|
||||
Assert.Contains(new LoggerConfiguration("A.B.C", LogLevel.Information, LogLevel.Information), logConfig);
|
||||
Assert.Contains(new LoggerConfiguration("A.B", null, LogLevel.Information), logConfig);
|
||||
Assert.Contains(new LoggerConfiguration("A", LogLevel.Information, LogLevel.Information), logConfig);
|
||||
|
||||
// act II
|
||||
provider.SetLogLevel("A.B", LogLevel.Trace);
|
||||
logConfig = provider.GetLoggerConfigurations();
|
||||
|
||||
// assert II
|
||||
Assert.Equal(6, logConfig.Count);
|
||||
Assert.Contains(new LoggerConfiguration("Default", LogLevel.Trace, LogLevel.Trace), logConfig);
|
||||
Assert.Contains(new LoggerConfiguration("A.B.C.D.TestClass", null, LogLevel.Trace), logConfig);
|
||||
Assert.Contains(new LoggerConfiguration("A.B.C.D", null, LogLevel.Trace), logConfig);
|
||||
Assert.Contains(new LoggerConfiguration("A.B.C", LogLevel.Information, LogLevel.Trace), logConfig);
|
||||
Assert.Contains(new LoggerConfiguration("A.B", null, LogLevel.Trace), logConfig);
|
||||
Assert.Contains(new LoggerConfiguration("A", LogLevel.Information, LogLevel.Trace), logConfig);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SetLogLevel_Works_OnDefault()
|
||||
{
|
||||
// arrange
|
||||
var provider = new SerilogDynamicProvider(GetConfiguration());
|
||||
LoggerFactory fac = new LoggerFactory();
|
||||
fac.AddProvider(provider);
|
||||
var originalLogConfig = provider.GetLoggerConfigurations();
|
||||
|
||||
// act
|
||||
provider.SetLogLevel("Default", LogLevel.Information);
|
||||
var updatedLogConfig = provider.GetLoggerConfigurations();
|
||||
|
||||
// assert
|
||||
Assert.Contains(new LoggerConfiguration("Default", LogLevel.Trace, LogLevel.Trace), originalLogConfig);
|
||||
Assert.Contains(new LoggerConfiguration("Default", LogLevel.Trace, LogLevel.Information), updatedLogConfig);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ResetLogLevel_Works_OnDefault()
|
||||
{
|
||||
// arrange
|
||||
var provider = new SerilogDynamicProvider(GetConfiguration());
|
||||
LoggerFactory fac = new LoggerFactory();
|
||||
fac.AddProvider(provider);
|
||||
var originalLogConfig = provider.GetLoggerConfigurations();
|
||||
|
||||
// act
|
||||
provider.SetLogLevel("Default", LogLevel.Information);
|
||||
var updatedLogConfig = provider.GetLoggerConfigurations();
|
||||
provider.SetLogLevel("Default", null);
|
||||
var resetConfig = provider.GetLoggerConfigurations();
|
||||
|
||||
// assert
|
||||
Assert.Contains(new LoggerConfiguration("Default", LogLevel.Trace, LogLevel.Trace), originalLogConfig);
|
||||
Assert.Contains(new LoggerConfiguration("Default", LogLevel.Trace, LogLevel.Information), updatedLogConfig);
|
||||
Assert.Contains(new LoggerConfiguration("Default", LogLevel.Trace, LogLevel.Trace), resetConfig);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void LoggerLogs_At_Configured_Setting()
|
||||
{
|
||||
// arrange
|
||||
var provider = new SerilogDynamicProvider(GetConfiguration());
|
||||
LoggerFactory fac = new LoggerFactory();
|
||||
fac.AddProvider(provider);
|
||||
ILogger logger = fac.CreateLogger(typeof(A.B.C.D.TestClass));
|
||||
|
||||
// act I - log at all levels, expect Info and above to work
|
||||
using (var unConsole = new ConsoleOutputBorrower())
|
||||
{
|
||||
WriteLogEntries(logger);
|
||||
|
||||
// pause the thread to allow the logging to happen
|
||||
Thread.Sleep(100);
|
||||
|
||||
var logged = unConsole.ToString();
|
||||
|
||||
// assert I
|
||||
Assert.Contains("Critical message", logged);
|
||||
Assert.Contains("Error message", logged);
|
||||
Assert.Contains("Warning message", logged);
|
||||
Assert.Contains("Informational message", logged);
|
||||
Assert.DoesNotContain("Debug message", logged);
|
||||
Assert.DoesNotContain("Trace message", logged);
|
||||
}
|
||||
|
||||
// act II - adjust rules, expect Error and above to work
|
||||
provider.SetLogLevel("A.B.C.D", LogLevel.Error);
|
||||
using (var unConsole = new ConsoleOutputBorrower())
|
||||
{
|
||||
WriteLogEntries(logger);
|
||||
|
||||
// pause the thread to allow the logging to happen
|
||||
Thread.Sleep(100);
|
||||
|
||||
var logged2 = unConsole.ToString();
|
||||
|
||||
// assert II
|
||||
Assert.Contains("Critical message", logged2);
|
||||
Assert.Contains("Error message", logged2);
|
||||
Assert.DoesNotContain("Warning message", logged2);
|
||||
Assert.DoesNotContain("Informational message", logged2);
|
||||
Assert.DoesNotContain("Debug message", logged2);
|
||||
Assert.DoesNotContain("Trace message", logged2);
|
||||
}
|
||||
|
||||
// act III - adjust rules, expect Trace and above to work
|
||||
provider.SetLogLevel("A", LogLevel.Trace);
|
||||
using (var unConsole = new ConsoleOutputBorrower())
|
||||
{
|
||||
WriteLogEntries(logger);
|
||||
|
||||
// pause the thread to allow the logging to happen
|
||||
Thread.Sleep(100);
|
||||
|
||||
var logged3 = unConsole.ToString();
|
||||
|
||||
// assert III
|
||||
Assert.Contains("Critical message", logged3);
|
||||
Assert.Contains("Error message", logged3);
|
||||
Assert.Contains("Warning message", logged3);
|
||||
Assert.Contains("Informational message", logged3);
|
||||
Assert.Contains("Debug message", logged3);
|
||||
Assert.Contains("Trace message", logged3);
|
||||
}
|
||||
|
||||
// act IV - adjust rules, expect nothing to work
|
||||
provider.SetLogLevel("A", LogLevel.None);
|
||||
using (var unConsole = new ConsoleOutputBorrower())
|
||||
{
|
||||
WriteLogEntries(logger);
|
||||
|
||||
// pause the thread to allow the logging to happen
|
||||
Thread.Sleep(100);
|
||||
|
||||
var logged4 = unConsole.ToString();
|
||||
|
||||
// assert IV
|
||||
Assert.Contains("Critical message", logged4); // Serilog lowest level is Fatal == Critical
|
||||
Assert.DoesNotContain("Error message", logged4);
|
||||
Assert.DoesNotContain("Warning message", logged4);
|
||||
Assert.DoesNotContain("Informational message", logged4);
|
||||
Assert.DoesNotContain("Debug message", logged4);
|
||||
Assert.DoesNotContain("Trace message", logged4);
|
||||
}
|
||||
|
||||
// act V - reset the rules, expect Info and above to work
|
||||
provider.SetLogLevel("A", LogLevel.Information); // Only works with serilog for configured values
|
||||
using (var unConsole = new ConsoleOutputBorrower())
|
||||
{
|
||||
WriteLogEntries(logger);
|
||||
|
||||
// pause the thread to allow the logging to happen
|
||||
Thread.Sleep(100);
|
||||
|
||||
var logged5 = unConsole.ToString();
|
||||
|
||||
// assert V
|
||||
Assert.NotNull(provider.GetLoggerConfigurations().First(c => c.Name == "A"));
|
||||
Assert.Contains("Critical message", logged5);
|
||||
Assert.Contains("Error message", logged5);
|
||||
Assert.Contains("Warning message", logged5);
|
||||
Assert.Contains("Informational message", logged5);
|
||||
Assert.DoesNotContain("Debug message", logged5);
|
||||
Assert.DoesNotContain("Trace message", logged5);
|
||||
}
|
||||
}
|
||||
|
||||
private void WriteLogEntries(ILogger logger)
|
||||
{
|
||||
logger.LogCritical("Critical message");
|
||||
logger.LogError("Error message");
|
||||
logger.LogWarning("Warning message");
|
||||
logger.LogInformation("Informational message");
|
||||
logger.LogDebug("Debug message");
|
||||
logger.LogTrace("Trace message");
|
||||
}
|
||||
|
||||
private IConfiguration GetConfiguration()
|
||||
{
|
||||
var appSettings = new Dictionary<string, string>
|
||||
{
|
||||
{ "Serilog:MinimumLevel:Default", "Verbose" }, // Sets level of root logger so has to be higher than any sub logger
|
||||
{ "Serilog:MinimumLevel:Override:Microsoft", "Warning" },
|
||||
{ "Serilog:MinimumLevel:Override:Steeltoe.Extensions", "Verbose" },
|
||||
{ "Serilog:MinimumLevel:Override:Steeltoe", "Information" },
|
||||
{ "Serilog:MinimumLevel:Override:A", "Information" },
|
||||
{ "Serilog:MinimumLevel:Override:A.B.C", "Information" },
|
||||
{ "Serilog:WriteTo:Name", "Console" },
|
||||
};
|
||||
|
||||
var builder = new ConfigurationBuilder().AddInMemoryCollection(appSettings);
|
||||
return builder.Build();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,166 @@
|
|||
// Copyright 2017 the original author or authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Logging.Console;
|
||||
using Microsoft.Extensions.Options;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Xunit;
|
||||
|
||||
namespace Steeltoe.Extensions.Logging.SerilogDynamicLogger.Test
|
||||
{
|
||||
public class SerilogDynamicLoggingBuilderTest
|
||||
{
|
||||
private static Dictionary<string, string> appsettings = new Dictionary<string, string>()
|
||||
{
|
||||
{ "Serilog:MinimumLevel:Default", "Verbose" }, // Sets level of root logger so has to be higher than any sub logger
|
||||
{ "Serilog:MinimumLevel:Override:Microsoft", "Warning" },
|
||||
{ "Serilog:MinimumLevel:Override:Steeltoe.Extensions", "Verbose" },
|
||||
{ "Serilog:MinimumLevel:Override:Steeltoe", "Information" },
|
||||
{ "Serilog:MinimumLevel:Override:A", "Information" },
|
||||
{ "Serilog:MinimumLevel:Override:A.B.C.D", "Fatal" },
|
||||
{ "Serilog:WriteTo:Name", "Console" },
|
||||
};
|
||||
|
||||
[Fact]
|
||||
public void OnlyApplicableFilters_AreApplied()
|
||||
{
|
||||
// arrange
|
||||
var appsettings = new Dictionary<string, string>()
|
||||
{
|
||||
["Logging:IncludeScopes"] = "false",
|
||||
["Logging:LogLevel:Default"] = "Information",
|
||||
["Logging:foo:LogLevel:A.B.C.D.TestClass"] = "None"
|
||||
};
|
||||
var configuration = new ConfigurationBuilder().AddInMemoryCollection(appsettings).Build();
|
||||
var services = new ServiceCollection()
|
||||
.AddSingleton<IConfiguration>(configuration)
|
||||
.AddLogging(builder =>
|
||||
{
|
||||
builder.AddSerilogDynamicConsole();
|
||||
})
|
||||
.BuildServiceProvider();
|
||||
|
||||
// act
|
||||
var logger = services.GetService(typeof(ILogger<A.B.C.D.TestClass>)) as ILogger<A.B.C.D.TestClass>;
|
||||
|
||||
// assert
|
||||
Assert.NotNull(logger);
|
||||
Assert.True(logger.IsEnabled(LogLevel.Information), "Information level should be enabled");
|
||||
Assert.False(logger.IsEnabled(LogLevel.Debug), "Debug level should NOT be enabled");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DynamicLevelSetting_WorksWith_ConsoleFilters()
|
||||
{
|
||||
// arrange
|
||||
var configuration = new ConfigurationBuilder().AddInMemoryCollection(appsettings).Build();
|
||||
var services = new ServiceCollection()
|
||||
.AddSingleton<IConfiguration>(configuration)
|
||||
.AddLogging(builder =>
|
||||
{
|
||||
builder.AddSerilogDynamicConsole();
|
||||
})
|
||||
.BuildServiceProvider();
|
||||
|
||||
// act
|
||||
var logger = services.GetService(typeof(ILogger<A.B.C.D.TestClass>)) as ILogger<A.B.C.D.TestClass>;
|
||||
|
||||
// assert
|
||||
Assert.NotNull(logger);
|
||||
Assert.True(logger.IsEnabled(LogLevel.Critical), "Critical level should be enabled");
|
||||
Assert.False(logger.IsEnabled(LogLevel.Error), "Error level should NOT be enabled");
|
||||
Assert.False(logger.IsEnabled(LogLevel.Warning), "Warning level should NOT be enabled");
|
||||
Assert.False(logger.IsEnabled(LogLevel.Debug), "Debug level should NOT be enabled");
|
||||
Assert.False(logger.IsEnabled(LogLevel.Trace), "Trace level should NOT be enabled yet");
|
||||
|
||||
// change the log level and confirm it worked
|
||||
var provider = services.GetRequiredService(typeof(ILoggerProvider)) as SerilogDynamicProvider;
|
||||
provider.SetLogLevel("A.B.C.D", LogLevel.Trace);
|
||||
var levels = provider.GetLoggerConfigurations().Where(c => c.Name.StartsWith("A.B.C.D"))
|
||||
.Select(x => x.EffectiveLevel);
|
||||
|
||||
Assert.NotNull(levels);
|
||||
Assert.True(levels.All(x => x == LogLevel.Trace));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AddDynamicConsole_AddsAllLoggerProviders()
|
||||
{
|
||||
// arrange
|
||||
var configuration = new ConfigurationBuilder().AddInMemoryCollection(appsettings).Build();
|
||||
var services = new ServiceCollection()
|
||||
.AddSingleton<IConfiguration>(configuration)
|
||||
.AddLogging(builder =>
|
||||
{
|
||||
builder.AddSerilogDynamicConsole();
|
||||
}).BuildServiceProvider();
|
||||
|
||||
// act
|
||||
var dlogProvider = services.GetService<IDynamicLoggerProvider>();
|
||||
var logProviders = services.GetServices<ILoggerProvider>();
|
||||
|
||||
// assert
|
||||
Assert.NotNull(dlogProvider);
|
||||
Assert.NotEmpty(logProviders);
|
||||
Assert.Single(logProviders);
|
||||
Assert.IsType<SerilogDynamicProvider>(logProviders.SingleOrDefault());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AddDynamicConsole_AddsLoggerProvider_DisposeTwiceSucceeds()
|
||||
{
|
||||
// arrange
|
||||
var configuration = new ConfigurationBuilder().AddInMemoryCollection(appsettings).Build();
|
||||
var services = new ServiceCollection()
|
||||
.AddSingleton<IConfiguration>(configuration)
|
||||
.AddLogging(builder =>
|
||||
{
|
||||
builder.AddSerilogDynamicConsole();
|
||||
}).BuildServiceProvider();
|
||||
|
||||
// act
|
||||
var dlogProvider = services.GetService<IDynamicLoggerProvider>();
|
||||
var logProviders = services.GetServices<ILoggerProvider>();
|
||||
|
||||
// assert
|
||||
services.Dispose();
|
||||
dlogProvider.Dispose();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AddDynamicConsole_WithConfigurationParam_AddsServices()
|
||||
{
|
||||
// arrange
|
||||
var configuration = new ConfigurationBuilder().AddInMemoryCollection(appsettings).Build();
|
||||
var services = new ServiceCollection()
|
||||
.AddSingleton<IConfiguration>(configuration)
|
||||
.AddLogging(builder => builder.AddSerilogDynamicConsole())
|
||||
.BuildServiceProvider();
|
||||
|
||||
// act
|
||||
var dlogProvider = services.GetService<IDynamicLoggerProvider>();
|
||||
var logProviders = services.GetServices<ILoggerProvider>();
|
||||
|
||||
// assert
|
||||
Assert.NotNull(dlogProvider);
|
||||
Assert.NotEmpty(logProviders);
|
||||
Assert.Single(logProviders);
|
||||
Assert.IsType<SerilogDynamicProvider>(logProviders.SingleOrDefault());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Import Project="..\..\versions.props" />
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net461;netcoreapp2.1</TargetFrameworks>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Update="xunit.runner.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="$(AspNetCoreMvcTestVersion)" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.TestHost" Version="$(AspNetCoreTestVersion)" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="$(TestSdkVersion)" />
|
||||
<PackageReference Include="xunit" Version="$(XunitVersion)" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="$(XunitStudioVersion)" />
|
||||
<DotNetCliToolReference Include="dotnet-xunit" Version="$(XunitVersion)" />
|
||||
|
||||
<PackageReference Include="StyleCop.Analyzers" Version="$(StyleCopVersion)">
|
||||
<PrivateAssets>All</PrivateAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<NoWarn>SA1101;SA1124;SA1201;SA1309;SA1310;SA1401;SA1600;SA1652;1591</NoWarn>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<AdditionalFiles Include="..\..\stylecop.json">
|
||||
<Link>stylecop.json</Link>
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</AdditionalFiles>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\Steeltoe.Extensions.Logging.SerilogDynamicLogger\Steeltoe.Extensions.Logging.SerilogDynamicLogger.csproj" />
|
||||
</ItemGroup>
|
||||
</Project>
|
|
@ -0,0 +1,20 @@
|
|||
// Copyright 2017 the original author or authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
namespace A.B.C.D
|
||||
{
|
||||
public class TestClass
|
||||
{
|
||||
}
|
||||
}
|
Загрузка…
Ссылка в новой задаче