Skip to content

Commit

Permalink
feat(exception handler): removed dependencies
Browse files Browse the repository at this point in the history
  • Loading branch information
zhifenglee-aelf committed Oct 14, 2024
1 parent 698837d commit eae5a0a
Show file tree
Hide file tree
Showing 9 changed files with 120 additions and 152 deletions.
13 changes: 6 additions & 7 deletions AElf.ExceptionHandler/AElf.ExceptionHandler.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
<PackageId>AElf.ExceptionHandler</PackageId>
<Title>AElf ExceptionHandler</Title>
<Authors>AElf</Authors>
<Description>An ExceptionHandler module for use in ABP and Orleans framework.</Description>
<PackageTags>abp;module;grains;orleans</PackageTags>
<Description>An ExceptionHandler in AOP.</Description>
<PackageTags>aop</PackageTags>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
Expand All @@ -16,15 +16,14 @@
<RootNamespace>AElf.ExceptionHandler</RootNamespace>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Orleans.Core.Abstractions" Version="7.0.0" />
<PackageReference Include="Volo.Abp.Core" Version="8.0.5" />
</ItemGroup>

<PropertyGroup>
<PackageReadmeFile>README.md</PackageReadmeFile>
<PackageLicenseFile>LICENSE</PackageLicenseFile>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Logging" Version="8.0.0" />
</ItemGroup>

<ItemGroup>
<None Include="../README.md" Pack="true" PackagePath="" />
Expand Down
33 changes: 0 additions & 33 deletions AElf.ExceptionHandler/AOPExceptionModule.cs

This file was deleted.

64 changes: 0 additions & 64 deletions AElf.ExceptionHandler/AttributeCallFilter.cs

This file was deleted.

100 changes: 87 additions & 13 deletions AElf.ExceptionHandler/ExceptionHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,10 @@
using System.Linq.Expressions;
using System.Reflection;
using Microsoft.Extensions.Logging;
using Volo.Abp.DependencyInjection;

namespace AElf.ExceptionHandler;

public class ExceptionHandler : ITransientDependency, IInterceptor
public class ExceptionHandler : IInterceptor
{
private class Result
{
Expand Down Expand Up @@ -174,14 +173,7 @@ private Result HandleInnerException(Exception exception, MethodExecutionArgs arg
// Log the exception
if(logger != null)
{
if (attribute.Message != null)
{
((ILogger)logger).Log(attribute.LogLevel, exception, "Message: {Message} Exception Message: {ExceptionMessage}", attribute.Message, exception.Message);
}
else
{
((ILogger)logger).Log(attribute.LogLevel, exception, "Exception Message: {ExceptionMessage}", exception.Message);
}
LogException(exception, args, attribute, logger);
}

if (attribute.LogOnly)
Expand All @@ -201,7 +193,7 @@ private Result HandleInnerException(Exception exception, MethodExecutionArgs arg

if (returnType.IsGenericType && returnType.GetGenericTypeDefinition() == typeof(Task<>))
{
genericType = returnType.GetGenericArguments()[0];
genericType = returnType.GetGenericArguments().FirstOrDefault();
}

if (genericType != null)
Expand All @@ -218,6 +210,13 @@ private Result HandleInnerException(Exception exception, MethodExecutionArgs arg
Rethrow = false
};
}

// if the method returns Task and not Task<>
return new Result
{
Handled = true,
Rethrow = false
};
}

var exceptionHandlerInfo = GetExceptionHandlerInfo(attribute.TargetType, attribute.MethodName);
Expand Down Expand Up @@ -246,6 +245,16 @@ private Result HandleInnerException(Exception exception, MethodExecutionArgs arg
Rethrow = true
};
}

if(flowBehavior.ExceptionHandlingStrategy == ExceptionHandlingStrategy.Continue)
{
args.Exception = exception;
return new Result
{
Handled = false,
Rethrow = false
};
}

if (flowBehavior.ReturnValue == null)
{
Expand All @@ -258,20 +267,85 @@ private Result HandleInnerException(Exception exception, MethodExecutionArgs arg

if(flowBehavior.ExceptionHandlingStrategy == ExceptionHandlingStrategy.Throw)
{
if (args.MethodInfo.ReturnType != typeof(Exception))
{
throw new ReturnTypeMismatchException("Return type mismatch when trying to throw a new exception. ReturnValue should be of type Exception.");
}
var newException = (Exception)flowBehavior.ReturnValue!;
args.Exception = newException;
throw newException;
}

args.Exception = null;
args.ReturnValue = flowBehavior.ReturnValue;

//throw custom exception if the return is different
var flowReturnType = flowBehavior.ReturnValue.GetType();
Type? genericReturnType = null;

if (args.MethodInfo.ReturnType.IsGenericType && args.MethodInfo.ReturnType.GetGenericTypeDefinition() == typeof(Task<>))
{
genericReturnType = args.MethodInfo.ReturnType.GetGenericArguments().FirstOrDefault();
}

if (genericReturnType != null)
{
if (genericReturnType != flowReturnType)
{
throw new ReturnTypeMismatchException(
$"Return type mismatch when handling exception's return value. ReturnValue should be of type {genericReturnType} but was {flowReturnType}.");
}

args.ReturnValue = flowBehavior.ReturnValue;
}

return new Result
{
Handled = true,
Rethrow = false
};
}


private static void LogException(Exception exception, MethodExecutionArgs args, ExceptionHandlerAttribute attribute,
object logger)
{
var logValues = new List<object> { exception.Message };
var logMessage = $"Exception Message: {{ExceptionMessage}}";
//get parameter names from args.MethodInfo and check if it exists within attribute.LogTargets. if it does, log it
if (attribute.LogTargets != null)
{
var parameters = args.MethodInfo.GetParameters();
var parameterNames = parameters.Select(p => p.Name).ToArray();
var logTargets = attribute.LogTargets.Intersect(parameterNames).ToArray();
if (logTargets.Length > 0)
{
foreach (var logTarget in logTargets)
{
// check if the parameter is a value type or a reference type
var parameter = parameters.First(p => p.Name == logTarget);
if (parameter.ParameterType.IsValueType || parameter.ParameterType == typeof(string))
{
logMessage += $" {logTarget}: {{{logTarget}}}";
}
else
{
logMessage += $" {logTarget}: {{@{logTarget}}}";
}
}
logValues.AddRange(logTargets.Select(target => args.Arguments[Array.IndexOf(parameterNames, target)]));
}
}
if (attribute.Message != null)
{
logMessage = $"Message: {{Message}} " + logMessage;
logValues.Insert(0, attribute.Message);
((ILogger)logger).Log(attribute.LogLevel, exception, logMessage, logValues.ToArray());
}
else
{
((ILogger)logger).Log(attribute.LogLevel, exception, logMessage, logValues.ToArray());
}
}

private ExceptionHandlerInfo GetExceptionHandlerInfo(Type targetType, string methodName)
{
var cacheKey = CacheKey(targetType, methodName);
Expand Down
1 change: 1 addition & 0 deletions AElf.ExceptionHandler/ExceptionHandlerAttribute.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ public class ExceptionHandlerAttribute : Attribute
public string? FinallyMethodName { get; set; } = null;
public string? Message { get; set; } = null;
public ReturnDefault ReturnDefault { get; set; } = ReturnDefault.None;
public string[]? LogTargets { get; set; } = null;

public ExceptionHandlerAttribute(params Type [] exceptions)

Check warning on line 19 in AElf.ExceptionHandler/ExceptionHandlerAttribute.cs

View workflow job for this annotation

GitHub Actions / publish

Non-nullable property 'TargetType' must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring the property as nullable.

Check warning on line 19 in AElf.ExceptionHandler/ExceptionHandlerAttribute.cs

View workflow job for this annotation

GitHub Actions / publish

Non-nullable property 'MethodName' must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring the property as nullable.
{
Expand Down
35 changes: 0 additions & 35 deletions AElf.ExceptionHandler/ExceptionHandlerInterceptor.cs

This file was deleted.

1 change: 1 addition & 0 deletions AElf.ExceptionHandler/ExceptionHandlingStrategy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@ public enum ExceptionHandlingStrategy
Rethrow,
Return,
Throw,
Continue
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
using System.Collections.Concurrent;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;

namespace AElf.ExceptionHandler.Extensions;

public static class ExceptionHandlerConfigurationExtension
{
public static IServiceCollection AddExceptionHandler(this IServiceCollection services)
{
services.TryAddTransient<IInterceptor, ExceptionHandler>();
services.TryAddSingleton<ConcurrentDictionary<string, ExceptionHandlerInfo>>();
services.TryAddSingleton<ConcurrentDictionary<string, Func<object, object[], Task>>>();
services.TryAddSingleton<ConcurrentDictionary<string, List<ExceptionHandlerAttribute>>>();
return services;
}
}
8 changes: 8 additions & 0 deletions AElf.ExceptionHandler/ReturnTypeMismatchException.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace AElf.ExceptionHandler;

public class ReturnTypeMismatchException : Exception
{
public ReturnTypeMismatchException(string message) : base(message)
{
}
}

0 comments on commit eae5a0a

Please sign in to comment.