Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Full stack trace for intercepted methods at call site in Unity

We're looking into using Unity to handle logging service methods with interception. However, one concern is that the full stack trace is not available at the call site; its only available within an interceptor call.

Here's an example setup:

public interface IExceptionService
{
    void ThrowEx();
}

public class ExceptionService : IExceptionService
{
    public void ThrowEx()
    {
        throw new NotImplementedException();
    }
}

public class DummyInterceptor : IInterceptionBehavior
{
    public IEnumerable<Type> GetRequiredInterfaces()
    {
        return Type.EmptyTypes;
    }

    public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext)
    {
        IMethodReturn ret = getNext()(input, getNext);
        if (ret.Exception != null)
            Console.WriteLine("Interceptor: " + ret.Exception.StackTrace + "\r\n");
        return ret;
    }

    public bool WillExecute
    {
        get { return true; }
    }
}

class Program
{
    static void Main(string[] args)
    {
        IUnityContainer container = new UnityContainer();
        container.AddNewExtension<Interception>();

        container.RegisterType<IExceptionService, ExceptionService>(
            new Interceptor<InterfaceInterceptor>(),
            new InterceptionBehavior<DummyInterceptor>());

        try
        {
            container.Resolve<IExceptionService>().ThrowEx();
        }
        catch (Exception e)
        {
            Console.WriteLine("Call Site: " + e.StackTrace);
        }

    }
}

Here's the console output from running that program:

Interceptor:
at ConsoleDemo.ExceptionService.ThrowEx() in    C:\code\ServiceDemo\ConsoleDemo\Program.cs:line 25
at DynamicModule.ns.Wrapped_IExceptionService_248fe3264f81461f96d34670a0a7d45d.<ThrowEx_DelegateImplementation>__0(IMethodInvocation inputs, GetNextInterceptionBehaviorDelegate getNext)

Call Site:
at DynamicModule.ns.Wrapped_IExceptionService_248fe3264f81461f96d34670a0a7d45d.ThrowEx()
at ConsoleDemo.Program.Main(String[] args) in C:\code\ServiceDemo\ConsoleDemo\Program.cs:line 63

The stack trace in the interceptor is fine and will suffice for logging at the service level. However, we lose everything past the interception proxy call at the call site;

I can wrap the exception in the interceptor in a ServiceException or some such, and that will keep the call stack in the inner exception, but that leads to awkward logging and debug inspection scenarios (though less awkward than losing the trace entirely).

I've also noticed we get more or less what we want when we use the TransparentProxyInterceptor, but that is noted as being slower than InterfaceInterception, and that triggers alarm bells for some groups.

Is there any cleaner way to get a full stack trace with Unity interception at the call site on a proxy?

like image 343
Nick Avatar asked Nov 03 '22 19:11

Nick


1 Answers

In .NET 4.5 there will be ExceptionDispatchInfo for this purpose.

For all other versions you can see this question:
In C#, how can I rethrow InnerException without losing stack trace?

like image 154
Andrey Shchekin Avatar answered Nov 15 '22 07:11

Andrey Shchekin