mirror of
https://github.com/AlexMacocian/SystemExtensions.git
synced 2026-07-21 00:29:29 +00:00
Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 41b1b48f98 | |||
| 721b444dda |
@@ -0,0 +1,13 @@
|
|||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using System.Logging;
|
||||||
|
|
||||||
|
namespace System.Extensions
|
||||||
|
{
|
||||||
|
public static class LoggingExtensions
|
||||||
|
{
|
||||||
|
public static ScopedLogger<T> CreateScopedLogger<T>(this ILogger<T> logger, string methodName, string flowIdentifier)
|
||||||
|
{
|
||||||
|
return ScopedLogger<T>.Create(logger, methodName, flowIdentifier);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using System.Extensions;
|
||||||
|
|
||||||
|
namespace System.Logging
|
||||||
|
{
|
||||||
|
public struct ScopedLogger<T>
|
||||||
|
{
|
||||||
|
private readonly ILogger<T> logger;
|
||||||
|
private readonly string scope;
|
||||||
|
private readonly string flowId;
|
||||||
|
|
||||||
|
private ScopedLogger(ILogger<T> logger, string scope, string flowId)
|
||||||
|
{
|
||||||
|
this.logger = logger;
|
||||||
|
this.scope = scope;
|
||||||
|
this.flowId = flowId.IsNullOrWhiteSpace() ? string.Empty : $"[{flowId}] ";
|
||||||
|
}
|
||||||
|
|
||||||
|
public ScopedLogger<T> LogInformation(string message, params object[] parameters)
|
||||||
|
{
|
||||||
|
this.logger.LogInformation(this.CreateMessage(message), parameters);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ScopedLogger<T> LogDebug(string message, params object[] parameters)
|
||||||
|
{
|
||||||
|
this.logger.LogDebug(this.CreateMessage(message), parameters);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ScopedLogger<T> LogWarning(string message, params object[] parameters)
|
||||||
|
{
|
||||||
|
this.logger.LogWarning(this.CreateMessage(message), parameters);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ScopedLogger<T> LogError(string message, params object[] parameters)
|
||||||
|
{
|
||||||
|
this.logger.LogError(this.CreateMessage(message), parameters);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ScopedLogger<T> LogCritical(string message, params object[] parameters)
|
||||||
|
{
|
||||||
|
this.logger.LogCritical(this.CreateMessage(message), parameters);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ScopedLogger<T> LogWarning(Exception e, string message, params object[] parameters)
|
||||||
|
{
|
||||||
|
this.logger.LogWarning(e, this.CreateMessage(message), parameters);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ScopedLogger<T> LogError(Exception e, string message, params object[] parameters)
|
||||||
|
{
|
||||||
|
this.logger.LogError(e, this.CreateMessage(message), parameters);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ScopedLogger<T> LogCritical(Exception e, string message, params object[] parameters)
|
||||||
|
{
|
||||||
|
this.logger.LogCritical(e, this.CreateMessage(message), parameters);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string CreateMessage(string message)
|
||||||
|
{
|
||||||
|
return $"{this.flowId}{this.scope}: {message}";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ScopedLogger<T> Create(ILogger<T> logger, string scope, string flowId)
|
||||||
|
{
|
||||||
|
return new ScopedLogger<T>(logger, scope.ThrowIfNull(nameof(scope)), flowId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -7,7 +7,7 @@
|
|||||||
<PackageLicenseFile>LICENSE</PackageLicenseFile>
|
<PackageLicenseFile>LICENSE</PackageLicenseFile>
|
||||||
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
|
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
|
||||||
<RootNamespace>System</RootNamespace>
|
<RootNamespace>System</RootNamespace>
|
||||||
<Version>1.3.2</Version>
|
<Version>1.4.1</Version>
|
||||||
<Authors>Alexandru Macocian</Authors>
|
<Authors>Alexandru Macocian</Authors>
|
||||||
<RepositoryUrl>https://github.com/AlexMacocian/SystemExtensions</RepositoryUrl>
|
<RepositoryUrl>https://github.com/AlexMacocian/SystemExtensions</RepositoryUrl>
|
||||||
<Description>Extensions for the System namespace</Description>
|
<Description>Extensions for the System namespace</Description>
|
||||||
@@ -21,6 +21,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="6.0.0" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,27 @@
|
|||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace SystemExtensions.NetStandard.Tests.Logging.Models
|
||||||
|
{
|
||||||
|
public sealed class CachingLogger<T> : ILogger<T>
|
||||||
|
{
|
||||||
|
public List<string> LogCache { get; } = new();
|
||||||
|
|
||||||
|
public IDisposable BeginScope<TState>(TState state)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsEnabled(LogLevel logLevel)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)
|
||||||
|
{
|
||||||
|
var message = formatter(state, exception);
|
||||||
|
this.LogCache.Add(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,260 @@
|
|||||||
|
using System.Extensions;
|
||||||
|
using System.Linq;
|
||||||
|
using FluentAssertions;
|
||||||
|
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||||
|
using SystemExtensions.NetStandard.Tests.Logging.Models;
|
||||||
|
|
||||||
|
namespace System.Logging.Tests
|
||||||
|
{
|
||||||
|
[TestClass]
|
||||||
|
public class ScopedLoggerTests
|
||||||
|
{
|
||||||
|
private const string Flow = "Flow";
|
||||||
|
private const string Message = "Some message";
|
||||||
|
private readonly CachingLogger<ScopedLoggerTests> cachingLogger = new();
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void CreateLogger_CreatesNewLogger()
|
||||||
|
{
|
||||||
|
var scopedLogger = this.cachingLogger.CreateScopedLogger(nameof(this.CreateLogger_CreatesNewLogger), Flow);
|
||||||
|
scopedLogger.Should().BeOfType<ScopedLogger<ScopedLoggerTests>>();
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void CreateLogger_NullScope_ThrowsArgumentNullException()
|
||||||
|
{
|
||||||
|
var action = new Action(() =>
|
||||||
|
{
|
||||||
|
var scopedLogger = this.cachingLogger.CreateScopedLogger(null, Flow);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
action.Should().Throw<ArgumentNullException>();
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void CreateLogger_NullFlow_ReturnsScopedLogger()
|
||||||
|
{
|
||||||
|
var scopedLogger = this.cachingLogger.CreateScopedLogger(nameof(this.CreateLogger_NullFlow_ReturnsScopedLogger), null);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void LogInformation_LogsExpected()
|
||||||
|
{
|
||||||
|
var scopedLogger = this.cachingLogger.CreateScopedLogger(nameof(this.LogInformation_LogsExpected), Flow);
|
||||||
|
var expectedMessage = $"[{Flow}] {nameof(this.LogInformation_LogsExpected)}: {Message}";
|
||||||
|
|
||||||
|
scopedLogger.LogInformation(Message);
|
||||||
|
|
||||||
|
this.cachingLogger.LogCache.Should().HaveCount(1);
|
||||||
|
this.cachingLogger.LogCache.First().Should().Be(expectedMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void LogInformation_EmptyFlow_LogsExpected()
|
||||||
|
{
|
||||||
|
var scopedLogger = this.cachingLogger.CreateScopedLogger(nameof(this.LogInformation_LogsExpected), string.Empty);
|
||||||
|
var expectedMessage = $"{nameof(this.LogInformation_LogsExpected)}: {Message}";
|
||||||
|
|
||||||
|
scopedLogger.LogInformation(Message);
|
||||||
|
|
||||||
|
this.cachingLogger.LogCache.Should().HaveCount(1);
|
||||||
|
this.cachingLogger.LogCache.First().Should().Be(expectedMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void LogInformation_WhitespaceFlow_LogsExpected()
|
||||||
|
{
|
||||||
|
var scopedLogger = this.cachingLogger.CreateScopedLogger(nameof(this.LogInformation_LogsExpected), " ");
|
||||||
|
var expectedMessage = $"{nameof(this.LogInformation_LogsExpected)}: {Message}";
|
||||||
|
|
||||||
|
scopedLogger.LogInformation(Message);
|
||||||
|
|
||||||
|
this.cachingLogger.LogCache.Should().HaveCount(1);
|
||||||
|
this.cachingLogger.LogCache.First().Should().Be(expectedMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void LogDebug_LogsExpected()
|
||||||
|
{
|
||||||
|
var scopedLogger = this.cachingLogger.CreateScopedLogger(nameof(this.LogDebug_LogsExpected), Flow);
|
||||||
|
var expectedMessage = $"[{Flow}] {nameof(this.LogDebug_LogsExpected)}: {Message}";
|
||||||
|
|
||||||
|
scopedLogger.LogDebug(Message);
|
||||||
|
|
||||||
|
this.cachingLogger.LogCache.Should().HaveCount(1);
|
||||||
|
this.cachingLogger.LogCache.First().Should().Be(expectedMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void LogDebug_EmptyFlow_LogsExpected()
|
||||||
|
{
|
||||||
|
var scopedLogger = this.cachingLogger.CreateScopedLogger(nameof(this.LogDebug_EmptyFlow_LogsExpected), string.Empty);
|
||||||
|
var expectedMessage = $"{nameof(this.LogDebug_EmptyFlow_LogsExpected)}: {Message}";
|
||||||
|
|
||||||
|
scopedLogger.LogDebug(Message);
|
||||||
|
|
||||||
|
this.cachingLogger.LogCache.Should().HaveCount(1);
|
||||||
|
this.cachingLogger.LogCache.First().Should().Be(expectedMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void LogDebug_WhitespaceFlow_LogsExpected()
|
||||||
|
{
|
||||||
|
var scopedLogger = this.cachingLogger.CreateScopedLogger(nameof(this.LogDebug_WhitespaceFlow_LogsExpected), " ");
|
||||||
|
var expectedMessage = $"{nameof(this.LogDebug_WhitespaceFlow_LogsExpected)}: {Message}";
|
||||||
|
|
||||||
|
scopedLogger.LogDebug(Message);
|
||||||
|
|
||||||
|
this.cachingLogger.LogCache.Should().HaveCount(1);
|
||||||
|
this.cachingLogger.LogCache.First().Should().Be(expectedMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void LogWarning_LogsExpected()
|
||||||
|
{
|
||||||
|
var scopedLogger = this.cachingLogger.CreateScopedLogger(nameof(this.LogWarning_LogsExpected), Flow);
|
||||||
|
var expectedMessage = $"[{Flow}] {nameof(this.LogWarning_LogsExpected)}: {Message}";
|
||||||
|
|
||||||
|
scopedLogger.LogWarning(Message);
|
||||||
|
|
||||||
|
this.cachingLogger.LogCache.Should().HaveCount(1);
|
||||||
|
this.cachingLogger.LogCache.First().Should().Be(expectedMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void LogWarning_EmptyFlow_LogsExpected()
|
||||||
|
{
|
||||||
|
var scopedLogger = this.cachingLogger.CreateScopedLogger(nameof(this.LogWarning_EmptyFlow_LogsExpected), string.Empty);
|
||||||
|
var expectedMessage = $"{nameof(this.LogWarning_EmptyFlow_LogsExpected)}: {Message}";
|
||||||
|
|
||||||
|
scopedLogger.LogWarning(Message);
|
||||||
|
|
||||||
|
this.cachingLogger.LogCache.Should().HaveCount(1);
|
||||||
|
this.cachingLogger.LogCache.First().Should().Be(expectedMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void LogWarning_WhitespaceFlow_LogsExpected()
|
||||||
|
{
|
||||||
|
var scopedLogger = this.cachingLogger.CreateScopedLogger(nameof(this.LogWarning_WhitespaceFlow_LogsExpected), " ");
|
||||||
|
var expectedMessage = $"{nameof(this.LogWarning_WhitespaceFlow_LogsExpected)}: {Message}";
|
||||||
|
|
||||||
|
scopedLogger.LogWarning(Message);
|
||||||
|
|
||||||
|
this.cachingLogger.LogCache.Should().HaveCount(1);
|
||||||
|
this.cachingLogger.LogCache.First().Should().Be(expectedMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void LogError_LogsExpected()
|
||||||
|
{
|
||||||
|
var scopedLogger = this.cachingLogger.CreateScopedLogger(nameof(this.LogError_LogsExpected), Flow);
|
||||||
|
var expectedMessage = $"[{Flow}] {nameof(this.LogError_LogsExpected)}: {Message}";
|
||||||
|
|
||||||
|
scopedLogger.LogError(Message);
|
||||||
|
|
||||||
|
this.cachingLogger.LogCache.Should().HaveCount(1);
|
||||||
|
this.cachingLogger.LogCache.First().Should().Be(expectedMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void LogError_EmptyFlow_LogsExpected()
|
||||||
|
{
|
||||||
|
var scopedLogger = this.cachingLogger.CreateScopedLogger(nameof(this.LogError_EmptyFlow_LogsExpected), string.Empty);
|
||||||
|
var expectedMessage = $"{nameof(this.LogError_EmptyFlow_LogsExpected)}: {Message}";
|
||||||
|
|
||||||
|
scopedLogger.LogError(Message);
|
||||||
|
|
||||||
|
this.cachingLogger.LogCache.Should().HaveCount(1);
|
||||||
|
this.cachingLogger.LogCache.First().Should().Be(expectedMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void LogError_WhitespaceFlow_LogsExpected()
|
||||||
|
{
|
||||||
|
var scopedLogger = this.cachingLogger.CreateScopedLogger(nameof(this.LogError_WhitespaceFlow_LogsExpected), " ");
|
||||||
|
var expectedMessage = $"{nameof(this.LogError_WhitespaceFlow_LogsExpected)}: {Message}";
|
||||||
|
|
||||||
|
scopedLogger.LogError(Message);
|
||||||
|
|
||||||
|
this.cachingLogger.LogCache.Should().HaveCount(1);
|
||||||
|
this.cachingLogger.LogCache.First().Should().Be(expectedMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void LogCritical_LogsExpected()
|
||||||
|
{
|
||||||
|
var scopedLogger = this.cachingLogger.CreateScopedLogger(nameof(this.LogCritical_LogsExpected), Flow);
|
||||||
|
var expectedMessage = $"[{Flow}] {nameof(this.LogCritical_LogsExpected)}: {Message}";
|
||||||
|
|
||||||
|
scopedLogger.LogCritical(Message);
|
||||||
|
|
||||||
|
this.cachingLogger.LogCache.Should().HaveCount(1);
|
||||||
|
this.cachingLogger.LogCache.First().Should().Be(expectedMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void LogCritical_EmptyFlow_LogsExpected()
|
||||||
|
{
|
||||||
|
var scopedLogger = this.cachingLogger.CreateScopedLogger(nameof(this.LogCritical_EmptyFlow_LogsExpected), string.Empty);
|
||||||
|
var expectedMessage = $"{nameof(this.LogCritical_EmptyFlow_LogsExpected)}: {Message}";
|
||||||
|
|
||||||
|
scopedLogger.LogCritical(Message);
|
||||||
|
|
||||||
|
this.cachingLogger.LogCache.Should().HaveCount(1);
|
||||||
|
this.cachingLogger.LogCache.First().Should().Be(expectedMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void LogCritical_WhitespaceFlow_LogsExpected()
|
||||||
|
{
|
||||||
|
var scopedLogger = this.cachingLogger.CreateScopedLogger(nameof(this.LogCritical_WhitespaceFlow_LogsExpected), " ");
|
||||||
|
var expectedMessage = $"{nameof(this.LogCritical_WhitespaceFlow_LogsExpected)}: {Message}";
|
||||||
|
|
||||||
|
scopedLogger.LogCritical(Message);
|
||||||
|
|
||||||
|
this.cachingLogger.LogCache.Should().HaveCount(1);
|
||||||
|
this.cachingLogger.LogCache.First().Should().Be(expectedMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void LogWarning_WithException_LogsExpected()
|
||||||
|
{
|
||||||
|
var exception = new Exception();
|
||||||
|
var scopedLogger = this.cachingLogger.CreateScopedLogger(nameof(this.LogWarning_WithException_LogsExpected), Flow);
|
||||||
|
var expectedMessage = $"[{Flow}] {nameof(this.LogWarning_WithException_LogsExpected)}: {Message}";
|
||||||
|
|
||||||
|
scopedLogger.LogWarning(exception, Message);
|
||||||
|
|
||||||
|
this.cachingLogger.LogCache.Should().HaveCount(1);
|
||||||
|
this.cachingLogger.LogCache.First().Should().Be(expectedMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void LogError_WithException_LogsExpected()
|
||||||
|
{
|
||||||
|
var exception = new Exception();
|
||||||
|
var scopedLogger = this.cachingLogger.CreateScopedLogger(nameof(this.LogError_WithException_LogsExpected), Flow);
|
||||||
|
var expectedMessage = $"[{Flow}] {nameof(this.LogError_WithException_LogsExpected)}: {Message}";
|
||||||
|
|
||||||
|
scopedLogger.LogError(exception, Message);
|
||||||
|
|
||||||
|
this.cachingLogger.LogCache.Should().HaveCount(1);
|
||||||
|
this.cachingLogger.LogCache.First().Should().Be(expectedMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void LogCritical_WithException_LogsExpected()
|
||||||
|
{
|
||||||
|
var exception = new Exception();
|
||||||
|
var scopedLogger = this.cachingLogger.CreateScopedLogger(nameof(this.LogCritical_WithException_LogsExpected), Flow);
|
||||||
|
var expectedMessage = $"[{Flow}] {nameof(this.LogCritical_WithException_LogsExpected)}: {Message}";
|
||||||
|
|
||||||
|
scopedLogger.LogCritical(exception, Message);
|
||||||
|
|
||||||
|
this.cachingLogger.LogCache.Should().HaveCount(1);
|
||||||
|
this.cachingLogger.LogCache.First().Should().Be(expectedMessage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user