Reputation: 116070
I want to initialize some logging when a message comes in like this:
public class BaseMessage
{
public long TraceID { get; set; }
}
public class MyMessage : BaseMessage, ICommand
{
//..other properties
}
public class Handler : IHandleMessages<MyMessage>
{
public void Handle(MyMessage message)
{
log4net.ThreadContext.Properties["TraceID"] = message.TraceID
//Process message
}
}
The problem is I have a LOT of messages and I want to do this for all of them when a message comes in. I would like to be able to do something like this:
public class Handler : IInitializeHandlers, IHandleMessages<MyMessage>
{
public void Init(BaseMessage message)
{
log4net.ThreadContext.Properties["TraceID"] = ((BaseMessage)message).TraceID
}
public void Handle(MyMessage message)
{
//Process message
}
}
Upvotes: 0
Views: 490
Reputation: 116070
Here's how I solved it. I wanted to automatically create the Trace ID and send it in the body of the message rather than a header. I wasn't sure about the thread-safety of adding headers to the bus and I didn't want to have to change all of the calling code or modify ever IHandleMessages implementation. So here's what I came up with.
public class TraceIDMutator : IMutateIncomingMessages, IMutateOutgoingMessages
{
public object MutateIncoming(object message)
{
var baseMsg = message as MessageBase;
if (baseMsg != null)
ThreadContext.Properties[Constants.TraceID] = baseMsg.TraceID;
return message;
}
public object MutateOutgoing(object message)
{
var baseMsg = message as MessageBase;
if(baseMsg != null)
{
if(baseMsg.TraceID == 0)
{
var tid = ThreadContext.Properties[Constants.TraceID];
if (tid != null)
baseMsg.TraceID = (ulong)tid;
}
}
return message;
}
}
The IMutateIncomingMessages
and IMutateOutgoingMessages
interfaces allow me to tap in to the messaging pipeline of nservicebus. I only discovered it after digging through source code to figure out what was actually going on under the hood. You need to register this class with your IoC container in order for it to work.
ObjectFactory.Configure(x =>
{
x.For<IMutateIncomingMessages>().Use<TraceIDMutator>();
x.For<IMutateOutgoingMessages>().Use<TraceIDMutator>();
});
When the message is sent 'MutateOutgoing' will be called. At that point I grab the current trace id from the log4net.ThreadContext
if there is one and assign it to the message. When the message is received the MutateIncoming
is called and then I set the log4net.ThreadContext
trace id property for that thread.
Upvotes: 0
Reputation: 5273
Move the trace id to a header instead and use a unit of work(IManageUnitsOfWork) to register it with the log4net context
Upvotes: 1