Skip to content

Commit

Permalink
chore: Use logging source generators
Browse files Browse the repository at this point in the history
Signed-off-by: Austin Drenski <[email protected]>
  • Loading branch information
austindrenski committed Jan 17, 2024
1 parent a6062fe commit 90db90c
Show file tree
Hide file tree
Showing 5 changed files with 38 additions and 20 deletions.
5 changes: 3 additions & 2 deletions build/Common.props
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<Project>
<PropertyGroup>
<LangVersion>7.3</LangVersion>
<LangVersion>latest</LangVersion>
<EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>
<EnableNETAnalyzers>true</EnableNETAnalyzers>
</PropertyGroup>
Expand All @@ -19,12 +19,13 @@
Please sort alphabetically.
Refer to https://docs.microsoft.com/nuget/concepts/package-versioning for semver syntax.
-->
<MicrosoftExtensionsLoggerVer>[2.0,)</MicrosoftExtensionsLoggerVer>
<MicrosoftExtensionsLoggerVer>[8.0.0,)</MicrosoftExtensionsLoggerVer>
<MicrosoftSourceLinkGitHubPkgVer>[1.0.0,2.0)</MicrosoftSourceLinkGitHubPkgVer>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="System.Collections.Immutable" Version="[1.7.1,)" />
<PackageReference Include="System.Threading.Channels" Version="[6.0.0,)" />
<PackageReference Include="System.ValueTuple" Version="[4.5.0,)" Condition="'$(TargetFramework)' == 'net462'" />
</ItemGroup>
</Project>
2 changes: 1 addition & 1 deletion src/OpenFeature/Api.cs
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@ public void RemoveHandler(ProviderEventTypes type, EventHandlerDelegate handler)
/// <param name="logger">The logger to be used</param>
public void SetLogger(ILogger logger)
{
this.EventExecutor.Logger = logger;
this.EventExecutor.SetLogger(logger);
}
}
}
15 changes: 10 additions & 5 deletions src/OpenFeature/EventExecutor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ namespace OpenFeature

internal delegate Task ShutdownDelegate();

internal class EventExecutor
internal sealed partial class EventExecutor
{
private readonly object _lockObj = new object();
public readonly Channel<object> EventChannel = Channel.CreateBounded<object>(1);
Expand All @@ -27,16 +27,18 @@ internal class EventExecutor
private readonly Dictionary<ProviderEventTypes, List<EventHandlerDelegate>> _apiHandlers = new Dictionary<ProviderEventTypes, List<EventHandlerDelegate>>();
private readonly Dictionary<string, Dictionary<ProviderEventTypes, List<EventHandlerDelegate>>> _clientHandlers = new Dictionary<string, Dictionary<ProviderEventTypes, List<EventHandlerDelegate>>>();

internal ILogger Logger { get; set; }
private ILogger _logger;

public EventExecutor()
{
this.Logger = new Logger<EventExecutor>(new NullLoggerFactory());
this._logger = NullLogger<EventExecutor>.Instance;
this._shutdownDelegate = this.SignalShutdownAsync;
var eventProcessing = new Thread(this.ProcessEventAsync);
eventProcessing.Start();
}

internal void SetLogger(ILogger logger) => this._logger = logger;

internal void AddApiLevelHandler(ProviderEventTypes eventType, EventHandlerDelegate handler)
{
lock (this._lockObj)
Expand Down Expand Up @@ -218,7 +220,7 @@ private void EmitOnRegistration(FeatureProviderReference provider, ProviderEvent
}
catch (Exception exc)
{
this.Logger?.LogError("Error running handler: " + exc);
this.ErrorRunningHandler(exc);
}
}
}
Expand Down Expand Up @@ -323,7 +325,7 @@ private void InvokeEventHandler(EventHandlerDelegate eventHandler, Event e)
}
catch (Exception exc)
{
this.Logger?.LogError("Error running handler: " + exc);
this.ErrorRunningHandler(exc);
}
}

Expand All @@ -346,6 +348,9 @@ private async Task SignalShutdownAsync()
// Wait for the processing loop to acknowledge the shutdown
await this._shutdownSemaphore.WaitAsync().ConfigureAwait(false);
}

[LoggerMessage(100, LogLevel.Error, "Error running handler")]
partial void ErrorRunningHandler(Exception exception);
}

internal class ShutdownSignal
Expand Down
31 changes: 22 additions & 9 deletions src/OpenFeature/OpenFeatureClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ namespace OpenFeature
/// <summary>
///
/// </summary>
public sealed class FeatureClient : IFeatureClient
public sealed partial class FeatureClient : IFeatureClient
{
private readonly ClientMetadata _metadata;
private readonly ConcurrentStack<Hook> _hooks = new ConcurrentStack<Hook>();
Expand Down Expand Up @@ -76,7 +76,7 @@ public void SetContext(EvaluationContext context)
public FeatureClient(string name, string version, ILogger logger = null, EvaluationContext context = null)
{
this._metadata = new ClientMetadata(name, version);
this._logger = logger ?? new Logger<Api>(new NullLoggerFactory());
this._logger = logger ?? NullLogger<Api>.Instance;
this._evaluationContext = context ?? EvaluationContext.Empty;
}

Expand Down Expand Up @@ -233,15 +233,14 @@ private async Task<FlagEvaluationDetails<T>> EvaluateFlag<T>(
}
catch (FeatureProviderException ex)
{
this._logger.LogError(ex, "Error while evaluating flag {FlagKey}. Error {ErrorType}", flagKey,
ex.ErrorType.GetDescription());
this.FlagEvaluationErrorWithDescription(flagKey, ex.ErrorType.GetDescription(), ex);
evaluation = new FlagEvaluationDetails<T>(flagKey, defaultValue, ex.ErrorType, Reason.Error,
string.Empty, ex.Message);
await this.TriggerErrorHooks(allHooksReversed, hookContext, ex, options).ConfigureAwait(false);
}
catch (Exception ex)
{
this._logger.LogError(ex, "Error while evaluating flag {FlagKey}", flagKey);
this.FlagEvaluationError(flagKey, ex);
var errorCode = ex is InvalidCastException ? ErrorType.TypeMismatch : ErrorType.General;
evaluation = new FlagEvaluationDetails<T>(flagKey, defaultValue, errorCode, Reason.Error, string.Empty);
await this.TriggerErrorHooks(allHooksReversed, hookContext, ex, options).ConfigureAwait(false);
Expand Down Expand Up @@ -270,8 +269,7 @@ private async Task<HookContext<T>> TriggerBeforeHooks<T>(IReadOnlyList<Hook> hoo
}
else
{
this._logger.LogDebug("Hook {HookName} returned null, nothing to merge back into context",
hook.GetType().Name);
this.HookReturnedNull(hook.GetType().Name);
}
}

Expand All @@ -298,7 +296,7 @@ private async Task TriggerErrorHooks<T>(IReadOnlyList<Hook> hooks, HookContext<T
}
catch (Exception e)
{
this._logger.LogError(e, "Error while executing Error hook {0}", hook.GetType().Name);
this.ErrorHookError(hook.GetType().Name, e);
}
}
}
Expand All @@ -314,9 +312,24 @@ private async Task TriggerFinallyHooks<T>(IReadOnlyList<Hook> hooks, HookContext
}
catch (Exception e)
{
this._logger.LogError(e, "Error while executing Finally hook {0}", hook.GetType().Name);
this.FinallyHookError(hook.GetType().Name, e);
}
}
}

[LoggerMessage(100, LogLevel.Debug, "Hook {HookName} returned null, nothing to merge back into context")]
partial void HookReturnedNull(string hookName);

[LoggerMessage(101, LogLevel.Error, "Error while evaluating flag {FlagKey}")]
partial void FlagEvaluationError(string flagKey, Exception exception);

[LoggerMessage(102, LogLevel.Error, "Error while evaluating flag {FlagKey}: {ErrorType}")]
partial void FlagEvaluationErrorWithDescription(string flagKey, string errorType, Exception exception);

[LoggerMessage(103, LogLevel.Error, "Error while executing Error hook {HookName}")]
partial void ErrorHookError(string hookName, Exception exception);

[LoggerMessage(104, LogLevel.Error, "Error while executing Finally hook {HookName}")]
partial void FinallyHookError(string hookName, Exception exception);
}
}
5 changes: 2 additions & 3 deletions test/OpenFeature.Tests/OpenFeatureClientTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
using AutoFixture;
using FluentAssertions;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Internal;
using NSubstitute;
using NSubstitute.ExceptionExtensions;
using OpenFeature.Constant;
Expand Down Expand Up @@ -183,9 +182,9 @@ public async Task OpenFeatureClient_Should_Return_DefaultValue_When_Type_Mismatc
mockedLogger.Received(1).Log(

Check failure on line 182 in test/OpenFeature.Tests/OpenFeatureClientTests.cs

View workflow job for this annotation

GitHub Actions / unit-tests-windows

OpenFeature.Tests.OpenFeatureClientTests.OpenFeatureClient_Should_Return_DefaultValue_When_Type_Mismatch

NSubstitute.Exceptions.ReceivedCallsException : Expected to receive exactly 1 call matching: Log<String>(Error, any EventId, t => Equals(Format("Error while evaluating flag {0}", value(OpenFeature.Tests.OpenFeatureClientTests+<>c__DisplayClass4_0).flagName), t.ToString(), InvariantCultureIgnoreCase), any Exception, any Func<String, Exception, String>) Actually received no matching calls.

Check failure on line 182 in test/OpenFeature.Tests/OpenFeatureClientTests.cs

View workflow job for this annotation

GitHub Actions / unit-tests-windows

OpenFeature.Tests.OpenFeatureClientTests.OpenFeatureClient_Should_Return_DefaultValue_When_Type_Mismatch

NSubstitute.Exceptions.ReceivedCallsException : Expected to receive exactly 1 call matching: Log<String>(Error, any EventId, t => Equals(Format("Error while evaluating flag {0}", value(OpenFeature.Tests.OpenFeatureClientTests+<>c__DisplayClass4_0).flagName), t.ToString(), InvariantCultureIgnoreCase), any Exception, any Func<String, Exception, String>) Actually received no matching calls.

Check failure on line 182 in test/OpenFeature.Tests/OpenFeatureClientTests.cs

View workflow job for this annotation

GitHub Actions / unit-tests-windows

OpenFeature.Tests.OpenFeatureClientTests.OpenFeatureClient_Should_Return_DefaultValue_When_Type_Mismatch

NSubstitute.Exceptions.ReceivedCallsException : Expected to receive exactly 1 call matching: Log<String>(Error, any EventId, t => Equals(Format("Error while evaluating flag {0}", value(OpenFeature.Tests.OpenFeatureClientTests+<>c__DisplayClass4_0).flagName), t.ToString(), InvariantCultureIgnoreCase), any Exception, any Func<String, Exception, String>) Actually received no matching calls.

Check failure on line 182 in test/OpenFeature.Tests/OpenFeatureClientTests.cs

View workflow job for this annotation

GitHub Actions / unit-tests-linux

OpenFeature.Tests.OpenFeatureClientTests.OpenFeatureClient_Should_Return_DefaultValue_When_Type_Mismatch

NSubstitute.Exceptions.ReceivedCallsException : Expected to receive exactly 1 call matching: Log<String>(Error, any EventId, t => Equals(Format("Error while evaluating flag {0}", value(OpenFeature.Tests.OpenFeatureClientTests+<>c__DisplayClass4_0).flagName), t.ToString(), InvariantCultureIgnoreCase), any Exception, any Func<String, Exception, String>) Actually received no matching calls.

Check failure on line 182 in test/OpenFeature.Tests/OpenFeatureClientTests.cs

View workflow job for this annotation

GitHub Actions / unit-tests-linux

OpenFeature.Tests.OpenFeatureClientTests.OpenFeatureClient_Should_Return_DefaultValue_When_Type_Mismatch

NSubstitute.Exceptions.ReceivedCallsException : Expected to receive exactly 1 call matching: Log<String>(Error, any EventId, t => Equals(Format("Error while evaluating flag {0}", value(OpenFeature.Tests.OpenFeatureClientTests+<>c__DisplayClass4_0).flagName), t.ToString(), InvariantCultureIgnoreCase), any Exception, any Func<String, Exception, String>) Actually received no matching calls.

Check failure on line 182 in test/OpenFeature.Tests/OpenFeatureClientTests.cs

View workflow job for this annotation

GitHub Actions / unit-tests-linux

OpenFeature.Tests.OpenFeatureClientTests.OpenFeatureClient_Should_Return_DefaultValue_When_Type_Mismatch

NSubstitute.Exceptions.ReceivedCallsException : Expected to receive exactly 1 call matching: Log<String>(Error, any EventId, t => Equals(Format("Error while evaluating flag {0}", value(OpenFeature.Tests.OpenFeatureClientTests+<>c__DisplayClass4_0).flagName), t.ToString(), InvariantCultureIgnoreCase), any Exception, any Func<String, Exception, String>) Actually received no matching calls.
LogLevel.Error,
Arg.Any<EventId>(),
Arg.Is<FormattedLogValues>(t => string.Equals($"Error while evaluating flag {flagName}", t.ToString(), StringComparison.InvariantCultureIgnoreCase)),
Arg.Is<string>(t => string.Equals($"Error while evaluating flag {flagName}", t.ToString(), StringComparison.InvariantCultureIgnoreCase)),
Arg.Any<Exception>(),
Arg.Any<Func<object, Exception, string>>());
Arg.Any<Func<string, Exception, string>>());
}

[Fact]
Expand Down

0 comments on commit 90db90c

Please sign in to comment.