Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 9 additions & 3 deletions CR.Exceptions.AspNet/CrExceptionHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -60,12 +60,17 @@ public async ValueTask<bool> TryHandleAsync(HttpContext httpContext, Exception e
_logger.LogMissingHttpStatusMapping(exception, exceptionTypeName);
}

var logLevel = _logLevelMap.TryFind(crException, out var level) ? level : LogLevel.Debug;
_logger.LogApplicationException(logLevel, exception, exceptionTypeName);
if (!_logLevelMap.TryFind(crException, out var logLevel))
{
logLevel = LogLevel.Debug;
_logger.LogMissingLogLevelMapping(exceptionTypeName, logLevel);
}

_logger.LogCrExceptionOccurred(logLevel, exception, exceptionTypeName);
}
else
{
_logger.LogUnhandledException(exception, exceptionTypeName);
_logger.LogUnknownException(exception, exceptionTypeName);
}

httpContext.Response.StatusCode = statusCode;
Expand All @@ -81,6 +86,7 @@ public async ValueTask<bool> TryHandleAsync(HttpContext httpContext, Exception e
Instance = httpContext.Request.Path
},
};

AddProblemDetailsExtension(problemDetailsContext.ProblemDetails, ProblemDetailsExtensionNames.Errors, errors);

return await TryWriteResponseAsync(exception, problemDetailsContext);
Expand Down
25 changes: 16 additions & 9 deletions CR.Exceptions.AspNet/CrExceptionHandlerLogExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,19 @@

namespace CR.Exceptions.AspNet;

public static partial class CrExceptionHandlerLogExtensions
internal static partial class CrExceptionHandlerLogExtensions
{
private static class LogIds
{
private const int BaseId = 33_000;

public const int ResponseAlreadyStarted = BaseId + 1;
public const int MissingHttpStatusMapping = BaseId + 2;
public const int UnhandledException = BaseId + 3;
public const int UnknownException = BaseId + 3;
public const int ProblemDetailsExtensionOverwritten = BaseId + 4;
public const int FailedToWriteProblemDetails = BaseId + 5;
public const int ApplicationException = BaseId + 6;
public const int CrExceptionOccurred = BaseId + 6;
public const int MissingLogLevelMapping = BaseId + 7;
}

[LoggerMessage(
Expand All @@ -29,10 +30,10 @@ private static class LogIds
public static partial void LogMissingHttpStatusMapping(this ILogger logger, Exception exception, string? exceptionType);

[LoggerMessage(
EventId = LogIds.UnhandledException,
EventId = LogIds.UnknownException,
Level = LogLevel.Error,
Message = "An unexpected exception of type '{ExceptionType}' occurred.")]
public static partial void LogUnhandledException(this ILogger logger, Exception exception, string? exceptionType);
Message = "Unknown exception of type '{ExceptionType}' occurred. Default internal errors will be used.")]
public static partial void LogUnknownException(this ILogger logger, Exception exception, string? exceptionType);

[LoggerMessage(
EventId = LogIds.ProblemDetailsExtensionOverwritten,
Expand All @@ -47,7 +48,13 @@ private static class LogIds
public static partial void LogFailedToWriteProblemDetails(this ILogger logger, Exception exception);

[LoggerMessage(
EventId = LogIds.ApplicationException,
Message = "Application exception of type '{ExceptionType}' occurred.")]
public static partial void LogApplicationException(this ILogger logger, LogLevel level, Exception exception, string? exceptionType);
EventId = LogIds.CrExceptionOccurred,
Message = "CR exception of type '{ExceptionType}' occurred.")]
public static partial void LogCrExceptionOccurred(this ILogger logger, LogLevel level, Exception exception, string? exceptionType);

[LoggerMessage(
EventId = LogIds.MissingLogLevelMapping,
Level = LogLevel.Debug,
Message = "No log level mapping found for exception type '{ExceptionType}'. Using fallback log level '{FallbackLogLevel}'.")]
public static partial void LogMissingLogLevelMapping(this ILogger logger, string? exceptionType, LogLevel fallbackLogLevel);
}
4 changes: 2 additions & 2 deletions CR.Exceptions.slnx
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
<Folder Name="/Solution Items/">
<File Path="Directory.Build.props" />
</Folder>
<Project Path="CR.Exceptions.AspNet.UnitTests/CR.Exceptions.AspNet.Tests.csproj" Id="98992ed2-cb1e-4e88-9e6a-faada37aeaa6" />
<Project Path="CR.Exceptions.AspNet.Tests/CR.Exceptions.AspNet.Tests.csproj" Id="98992ed2-cb1e-4e88-9e6a-faada37aeaa6" />
<Project Path="CR.Exceptions.AspNet/CR.Exceptions.AspNet.csproj" Id="2749300d-4ad8-4e25-b49f-75847b8c0cbd" />
<Project Path="CR.Exceptions.UnitTests/CR.Exceptions.Tests.csproj" Id="7b9ef70f-7663-4220-80fe-b00434912875" />
<Project Path="CR.Exceptions.Tests/CR.Exceptions.Tests.csproj" Id="7b9ef70f-7663-4220-80fe-b00434912875" />
<Project Path="CR.Exceptions/CR.Exceptions.csproj" />
</Solution>
2 changes: 1 addition & 1 deletion CR.Exceptions/CR.Exceptions.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
<Description>Core .NET exception framework providing base error models, an exception factory, and error mapping.</Description>

<PackageId>$(NuGetPackagePrefix).Exceptions</PackageId>
<PackageTags>exceptions;exception-handling;error-handling;error-factory;error-mapping;domain-exceptions</PackageTags>
<PackageTags>exceptions;exception-handling;exception-factory;error-handling;error-factory;error-mapping;</PackageTags>

<PackageReadmeFile>README.md</PackageReadmeFile>
</PropertyGroup>
Expand Down
9 changes: 5 additions & 4 deletions CR.Exceptions/Extensions/ImmutableArrayExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,23 +1,24 @@
using System.Collections.Immutable;
using System.Runtime.CompilerServices;

namespace CR.Exceptions.Extensions;

public static class ImmutableArrayExtensions
{
extension<TSource>(ImmutableArray<TSource> source) where TSource : class?
extension<TSource>(ImmutableArray<TSource> source)
{
public void ThrowIfEmptyOrContainsNull()
public void ThrowIfEmptyOrContainsNull([CallerArgumentExpression(nameof(source))] string? paramName = null)
{
if (source.IsDefaultOrEmpty)
{
throw new ArgumentException("The array cannot be empty.", nameof(source));
throw new ArgumentException("The array cannot be empty.", paramName);
}

for (var i = 0; i < source.Length; i++)
{
if (source[i] is null)
{
throw new ArgumentNullException(nameof(source), $"The array element[{i}] is null.");
throw new ArgumentNullException(paramName, $"The array element[{i}] is null.");
}
}
}
Expand Down
2 changes: 0 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@

A lightweight framework for defining application errors, creating typed exceptions, and exposing consistent error responses across application boundaries.

The repository contains the following modules:

## Modules

### CR.Exceptions
Expand Down
Loading