Dynamically Populate ExceptionHandlerData Properties

Topics: Building and extending application blocks, Exception Handling Application Block, Logging Application Block
Jan 4, 2012 at 10:19 PM

Hello,

I understand how to create ExceptionHandlerData Properties that can have simple or complex types and can be set via the config tool. The properties are used by the GetRegistrations Lambda and passed to the underlying new up object. BUT...and there is always a BUT(T).....I want to set some of those properties with dynamic data. For example I have a simple GUID property but I want to assign it the TraceActivityID that is generated by the WCF service at instantiation not generate a new one in the properties get accessor or a pre-configured value.

Soooo how do I pass the ActivityID to the handler property?

 

TIA

JB

Jan 5, 2012 at 2:20 AM

Where is your GUID property stored?  Are you using Trace.CorrelationManager.ActivityId?  If so, then the ActivityId is on the thread so you can access it using static property.  You can pass it into your handler or have the handler pull it off the thread.

--
Randy Levy
Enterprise Library support engineer
entlib.support@live.com 

Jan 10, 2012 at 5:22 PM

Well that's pretty cool. I mean it makes sense that I should be able to access the trace thread but I've been wrong on my assumptions before.

So then I should be able to access this way no?

[ConfigurationProperty(_AppFabricActivityIDName, IsRequired = true, DefaultValue = Trace.CorrelationManager.ActivityId)]
public Guid AppFabricEventName
{
     get { return (Guid)base[_AppFabricActivityIDName]; }
     set { base[_AppFabricActivityIDName] = value; }
}
Or is there a better / different way you would reccomend?
Jan 10, 2012 at 5:28 PM

Check that. Should have known the compiler wouldn't like getting a default that way.

Error 1 An attribute argument must be a constant expression, typeof expression or array creation expression of an attribute parameter

Jan 11, 2012 at 12:20 AM

Trace.CorrelationManager.ActivityId is on the thread so you can just pull it off the thread.  I would remove it from the configuration and pass it in when creating the actual Handler.  You should also account for the scenario where activity tracing is not on so the ActivityId could be Guid.Empty.

public override IEnumerable<TypeRegistration> GetRegistrations(string namePrefix)
{
    //TODO: Just compile baby
    AppFabric.AppFabricEventProvider QQQ = new AppFabric.AppFabricEventProvider();

    Guid activityId = System.Diagnostics.Trace.CorrelationManager.ActivityId;

    if (activityId == Guid.Empty)
    {
        activityId = Guid.NewGuid();
        System.Diagnostics.Trace.CorrelationManager.ActivityId = activityId;
    }

    yield return new TypeRegistration<IExceptionHandler>(
        () =>
        new AppFabricLoggingExceptionHandler(activityId, QQQ, "DonaldDuck", "String{0}{1}", "T", "15"))
                {
                    Name = BuildName(namePrefix),
                    Lifetime = TypeRegistrationLifetime.Transient
                };
}

--
Randy Levy
Enterprise Library support engineer
entlib.support@live.com 


Jan 11, 2012 at 11:23 PM
Edited Jan 12, 2012 at 12:10 AM

OK I understand what you are saying but check out what I got from this experiment. I have stripped each piece as I discovered I didn't need it and ActivityID I don't need! My object is down to this as IIS AppFabric handles the ActivityID for me.

public override IEnumerable<TypeRegistration> GetRegistrations(string namePrefix)
{
            
     yield return new TypeRegistration<IExceptionHandler>(
       () =>
       new AppFabricLoggingExceptionHandler(this.AppFabricEventName))
       {
            Name = BuildName(namePrefix),
            Lifetime = TypeRegistrationLifetime.Transient
       };
}
The only thing left is how to get more useful information into the Exception. 
For example I'd like to maybe append information to inner exception before the 
Exception Shielding Policy kicks in. Does the try catch block if included execute prior to the 
ExceptionShielding so I could manipulate first. While I wait I'll give it a try....
 

 OK so here is what I tried. I added a try catch block. In the catch I added ex.Data.Add("Parm1", "More Info"); and then threw it out of the catch block where the exceptionShielding then picked it up. So it seems that indeed I can add extra information to the exception prior to the policy handling it. Which makes sense as the policy is for unhandled so once thrown out of the catch it is unhandled.

Now and this is not your problem I am having trouble accessing the Data parm. I try string x = (string)ex.Data["Parm1"]; but that just gives me an array of two null values????

Anyway if I wanted to post this to Codeplex for others to use should I have it reviewed first or will your team do that before when submitted?

Thanks

JB

Jan 12, 2012 at 2:30 AM

Does your FaultContract have a property to hold the IDictionary?  E.g.:

 

        [DataMember]
        public System.Collections.IDictionary FaultData { get; set; }

 

And does the FaultContractExceptionHandler map the Data property to the FaultContract IDictionary?

You could take a look at the EntLibContrib project for your extension.

 

--
Randy Levy
Enterprise Library support engineer
entlib.support@live.com