[ PSerializable ]
[ MulticastAttributeUsage ( Inheritance = MulticastInheritance.Strict ) ]
class ServiceExceptionDetourAttribute : OnExceptionAspect
{
    private static LogSource _log = LogSource.Get ().WithLevels ( LogLevel.Debug, LogLevel.Warning ) ;

    public override void OnException ( MethodExecutionArgs margs )
    {
        var argCount  = margs.Arguments.Count ;
        var arguments = new StringBuilder () ;
        for ( var i = 0 ; i < argCount ; i ++ )
        {
            arguments.Append ( margs.Arguments.GetArgument ( i ) ) ;
            if ( argCount > 1 )
                arguments.Append ( ',' ) ;
        }

        string targetName = margs.Exception.TargetSite.ReflectedType.Name ;
        var properties = new Dictionary <string, string>
                         {
                             { "Target", targetName },
                             { "Args", arguments.ToString () },
                             { "Exception", margs.Exception.ToString () },
                             { "Message", margs.Exception.Message }
                         } ;
        MarkCustomEvent ( properties ) ;
        _log.Error.Write ( Formatted ( "[Exception Monitor]: Swallowed an exception from {targetName} with: [{arguments}]{NewLine}{Message}",
                                       targetName,
                                       arguments,
                                       Environment.NewLine,
                                       margs.Exception.Message ) ) ;
    }

    public void MarkCustomEvent ( Dictionary <string, string> properties )
    {
        try
        {
            var monitor = new Metrics.Monitor () ;
            monitor.Telemetry.TrackEvent ( "Exception", properties ) ;
            _log.Debug.Write ( Formatted ( "[Exception Monitor]: Successfully tracking custom events on Application Insights." ) ) ;
        }
        catch ( Exception ex )
        {
            _log.Error.Write ( Formatted ( "[Exception Monitor]: Failed to issue a custom event to Application Insights.{NewLine}{Message}",
                                           Environment.NewLine,
                                           ex.Message ) ) ;
        }
    }
}