Message Correlation
The Envelope
class in Jasper tracks several properties for message correlation that you can utilize in your own logging
to track how messages are related to one another:
Id
- The message identifier. This is unique to a message body and destinationCausationId
- The identifier to the parent message -- if any -- whose handling triggered the current messageCorrelationId
- Tracks a set of related messages originating from the same original messages. All messages sent from a singleIMessageContext
will share the sameCorrelationId
. In the case of messages resulting from the handling of a first message, the resulting messages will share the sameCorrelationId
as the originalEnvelope
.
All of the above properties are of type Guid
, and the values are assigned through a sequential Guid
to optimize any database storage of Envelope
information.
Customized Message Logging
Jasper internally uses the concept of semantic logging for messaging events with the following interface registered with a default MessageLogger
implementation in the underlying IoC container.
public interface IMessageLogger
{
void LogException(Exception ex, Guid correlationId = default(Guid), string message = "Exception detected:");
void Sent(Envelope envelope);
void Received(Envelope envelope);
void ExecutionStarted(Envelope envelope);
void ExecutionFinished(Envelope envelope);
void MessageSucceeded(Envelope envelope);
void MessageFailed(Envelope envelope, Exception ex);
void NoHandlerFor(Envelope envelope);
void NoRoutesFor(Envelope envelope);
void MovedToErrorQueue(Envelope envelope, Exception ex);
void DiscardedEnvelope(Envelope envelope);
}
The default implementation just writes formatted string messages to the built in ASP.Net Core ILogger
mechanisms. You can of course substitute in your own custom logging to track more structured logging by writing your own custom IMessageLogger
. The easiest way to do that is to subclass MessageLogger
and just intercept the events you care about as in this example:
public class CustomMessageLogger : MessageLogger
{
private readonly ILogger<CustomMessageLogger> _logger;
public CustomMessageLogger(ILoggerFactory factory, IMetrics metrics, ILogger<CustomMessageLogger> logger) :
base(factory, metrics)
{
_logger = logger;
}
public override void ExecutionStarted(Envelope envelope)
{
base.ExecutionStarted(envelope);
_logger.LogInformation(
$"Executing envelope {envelope.Id}, caused by {envelope.CausationId}, correlated by {envelope.CorrelationId}");
}
// And any other events you might care about
}
Lastly, you can override the IMessageLogger
in the IoC container like so:
public class AppWithCustomLogging : JasperOptions
{
public AppWithCustomLogging()
{
Services.AddSingleton<IMessageLogger, CustomMessageLogger>();
}
}