Skip to content

Commit

Permalink
Add level override support, #32
Browse files Browse the repository at this point in the history
  • Loading branch information
daningalla committed Mar 9, 2024
1 parent d0913f7 commit 73b0b44
Show file tree
Hide file tree
Showing 8 changed files with 135 additions and 6 deletions.
10 changes: 8 additions & 2 deletions docs/basic-configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,20 @@ var loggerFactory = LoggerFactory
### Setting the minimum log event level.

The provider will not display any log events introduced that are of less of a severity than the configured value. By default, the provider sets the minimum level to `LogLevel.Information`.
The provider will not display any log events introduced that are of less of a severity than the configured value. By default, the provider sets the minimum level to `LogLevel.Information`. Additionally, you can configure the minimum log level for specific logging categories.

```csharp
// Trace & debug events are not displayed
// Trace & debug events are not displayed for any events
config.SetMinimumLevel(LogLevel.Information);

// Override minimum levels for specific logging categories
config.SetMinimumLevel("System", LogLevel.Warning);
config.SetMinimumLevel("System.Net.HttpClient", LogLevel.Warning);
```


### Filtering log events using a service.

If a filtering service is provided, the current log event is evaluated before being displayed. You can provide your own implementation of `ILogEventFilter` to handle this function.
Expand Down
10 changes: 10 additions & 0 deletions examples/MinimumLevelOverrides/MinimumLevelOverrides.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>

</Project>
36 changes: 36 additions & 0 deletions examples/MinimumLevelOverrides/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// See https://aka.ms/new-console-template for more information

using Microsoft.Extensions.Logging;
using Vertical.SpectreLogger;

var loggerFactory = LoggerFactory.Create(builder =>
{
builder.AddSpectreConsole(options =>
{
options.SetMinimumLevel(LogLevel.Debug);
options.SetMinimumLevel("Vertical", LogLevel.Warning);
options.ConfigureProfile(LogLevel.Debug, profile => profile.OutputTemplate =
"[grey46][[{DateTime:T} Dbug]] {CategoryName}: {Message}{NewLine}{Exception}[/]");
options.ConfigureProfile(LogLevel.Information, profile => profile.OutputTemplate =
"[grey85][[{DateTime:T} [green3_1]Info[/]]] {CategoryName}: {Message}{NewLine}{Exception}[/]");
options.ConfigureProfile(LogLevel.Warning, profile => profile.OutputTemplate =
"[grey85][[{DateTime:T} [gold1]Warn[/]]] {CategoryName}: {Message}{NewLine}{Exception}[/]");
options.ConfigureProfile(LogLevel.Error, profile => profile.OutputTemplate =
"[grey85][[{DateTime:T} [red1]Fail[/]]] {CategoryName}: {Message}{NewLine}{Exception}[/]");
});
builder.SetMinimumLevel(LogLevel.Debug);
});

var logger = loggerFactory.CreateLogger("Vertical");

logger.LogDebug("Debug message");
logger.LogInformation("Info message");
logger.LogWarning("Warning message");
logger.LogError("Error message");

var otherLogger = loggerFactory.CreateLogger("Program");
otherLogger.LogDebug("Debug message");
otherLogger.LogInformation("Info message");
otherLogger.LogWarning("Warning message");
otherLogger.LogError("Error message");
14 changes: 14 additions & 0 deletions examples/solution.sln
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Scopes", "Scopes\Scopes.csp
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DestructuredValues", "DestructuredValues\DestructuredValues.csproj", "{1A636677-808E-47ED-A030-0099136E5771}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MinimumLevelOverrides", "MinimumLevelOverrides\MinimumLevelOverrides.csproj", "{B599F9F4-A657-4CCB-B06C-D8465B7B6134}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -116,6 +118,18 @@ Global
{1A636677-808E-47ED-A030-0099136E5771}.Release|x64.Build.0 = Release|Any CPU
{1A636677-808E-47ED-A030-0099136E5771}.Release|x86.ActiveCfg = Release|Any CPU
{1A636677-808E-47ED-A030-0099136E5771}.Release|x86.Build.0 = Release|Any CPU
{B599F9F4-A657-4CCB-B06C-D8465B7B6134}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B599F9F4-A657-4CCB-B06C-D8465B7B6134}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B599F9F4-A657-4CCB-B06C-D8465B7B6134}.Debug|x64.ActiveCfg = Debug|Any CPU
{B599F9F4-A657-4CCB-B06C-D8465B7B6134}.Debug|x64.Build.0 = Debug|Any CPU
{B599F9F4-A657-4CCB-B06C-D8465B7B6134}.Debug|x86.ActiveCfg = Debug|Any CPU
{B599F9F4-A657-4CCB-B06C-D8465B7B6134}.Debug|x86.Build.0 = Debug|Any CPU
{B599F9F4-A657-4CCB-B06C-D8465B7B6134}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B599F9F4-A657-4CCB-B06C-D8465B7B6134}.Release|Any CPU.Build.0 = Release|Any CPU
{B599F9F4-A657-4CCB-B06C-D8465B7B6134}.Release|x64.ActiveCfg = Release|Any CPU
{B599F9F4-A657-4CCB-B06C-D8465B7B6134}.Release|x64.Build.0 = Release|Any CPU
{B599F9F4-A657-4CCB-B06C-D8465B7B6134}.Release|x86.ActiveCfg = Release|Any CPU
{B599F9F4-A657-4CCB-B06C-D8465B7B6134}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{604CEE06-4509-4C17-B876-A1112805F916} = {834A235D-0DCB-4561-8FE0-B0B51529A954}
Expand Down
5 changes: 5 additions & 0 deletions src/Options/SpectreLoggerOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ public class SpectreLoggerOptions
/// Gets or sets an object that controls log event filtering.
/// </summary>
public ILogEventFilter? LogEventFilter { get; set; }

/// <summary>
/// Gets a dictionary of log level overrides.
/// </summary>
public IDictionary<string, LogLevel> MinimumLevelOverrides { get; } = new Dictionary<string, LogLevel>();

/// <summary>
/// Gets the log level profiles.
Expand Down
18 changes: 18 additions & 0 deletions src/Options/SpectreLoggingBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,24 @@ public SpectreLoggingBuilder SetMinimumLevel(LogLevel logLevel)
return this;
}

/// <summary>
/// Sets the minimum log level for a specific logger category.
/// </summary>
/// <param name="category">The logger category.</param>
/// <param name="logLevel">The minimum log level used to evaluated whether events should be emitted.</param>
/// <returns>A reference to this instance.</returns>
/// <exception cref="ArgumentException"><paramref name="category"/> is null or whitespace.</exception>
public SpectreLoggingBuilder SetMinimumLevel(string category, LogLevel logLevel)
{
if (string.IsNullOrWhiteSpace(category))
{
throw new ArgumentException("Value cannot be null or whitespace.", nameof(category));
}

Services.Configure<SpectreLoggerOptions>(opt => opt.MinimumLevelOverrides[category] = logLevel);
return this;
}

/// <summary>
/// Sets an object that can filter log events from the rendering pipeline.
/// </summary>
Expand Down
18 changes: 14 additions & 4 deletions src/SpectreLogger.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
using System.Diagnostics.CodeAnalysis;
using Microsoft.Extensions.Logging;
using Vertical.SpectreLogger.Core;
using Vertical.SpectreLogger.Internal;
using Vertical.SpectreLogger.Options;
using Vertical.SpectreLogger.Scopes;

Expand All @@ -18,6 +17,7 @@ public class SpectreLogger : ILogger
private readonly ScopeManager _scopeManager;
private readonly string _categoryName;
private readonly SpectreLoggerOptions _options;
private readonly LogLevel _minimumLevel;

internal SpectreLogger(
IRendererPipeline rendererPipeline,
Expand All @@ -30,8 +30,9 @@ public class SpectreLogger : ILogger
_categoryName = categoryName;
_options = options;
_logEventFilter = _options.LogEventFilter;
_minimumLevel = ResolveMinimumLevel();
}

/// <inheritdoc />
public void Log<TState>(
LogLevel logLevel,
Expand Down Expand Up @@ -61,18 +62,27 @@ public class SpectreLogger : ILogger
_rendererPipeline.Render(eventInfo);
}


/// <inheritdoc />
[ExcludeFromCodeCoverage]
public bool IsEnabled(LogLevel logLevel)
{
return logLevel != LogLevel.None && logLevel >= _options.MinimumLogLevel;
return logLevel != LogLevel.None && logLevel >= _minimumLevel;
}

/// <inheritdoc />
public IDisposable BeginScope<TState>(TState state)
{
return _scopeManager.BeginScope(state);
}

private LogLevel ResolveMinimumLevel()
{
return _options.MinimumLevelOverrides.TryGetValue(_categoryName, out var logLevel) switch
{
true when logLevel > _options.MinimumLogLevel => logLevel,
_ => _options.MinimumLogLevel
};
}
}
}
30 changes: 30 additions & 0 deletions test/SpectreLoggerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,5 +30,35 @@ public void LoggerOutputsWhenLevelIsEnabled()
logger => logger.LogDebug("test message"))
.ShouldBe("test message");
}

[Fact]
public void LoggerEmitsWhenEventIsAboveMinimumOverride()
{
RendererTestHarness.Capture(
cfg =>
{
cfg.SetMinimumLevel(LogLevel.Information);
cfg.SetMinimumLevel("Minimum", LogLevel.Warning);
cfg.ConfigureProfiles(profile => profile.OutputTemplate = "{Message}");
},
log => log.LogWarning("warning"),
"Minimum")
.ShouldBe("warning");
}

[Fact]
public void LoggerDoesNotEmitWhenEventIsBelowMinimumOverride()
{
RendererTestHarness.Capture(
cfg =>
{
cfg.SetMinimumLevel(LogLevel.Information);
cfg.SetMinimumLevel("Minimum", LogLevel.Warning);
cfg.ConfigureProfiles(profile => profile.OutputTemplate = "{Message}");
},
log => log.LogInformation("information"),
"Minimum")
.ShouldBeEmpty();
}
}
}

0 comments on commit 73b0b44

Please sign in to comment.