I have problem with applying middleware for logging in masstransit. I wanted to log every message which is published to the bus. So I follow these steps which I found here: http://masstransit-project.com/MassTransit/advanced/middleware/custom.html and then I endup with something like this:
public static class MassTransitLoggerExtenions
{
public static void UseLogger<T>(this IPipeConfigurator<T> configurator,ILoggingBusControl loggingBusControl)
where T : class, PipeContext
{
configurator.AddPipeSpecification(new ExceptionLoggerSpecification<T>(loggingBusControl));
}
}
public class ExceptionLoggerSpecification<T> :
IPipeSpecification<T>
where T : class, PipeContext
{
private readonly ILoggingBusControl loggingBusControl;
public ExceptionLoggerSpecification(ILoggingBusControl loggingBusControl)
{
this.loggingBusControl = loggingBusControl;
}
public IEnumerable<ValidationResult> Validate()
{
return Enumerable.Empty<ValidationResult>();
}
public void Apply(IPipeBuilder<T> builder)
{
builder.AddFilter(new ExceptionLoggerFilter<T>(loggingBusControl));
}
}
public class ExceptionLoggerFilter<T> : IFilter<T> where T : class, PipeContext
{
private readonly ILoggingBusControl loggingBusControl;
public ExceptionLoggerFilter(ILoggingBusControl loggingBusControl)
{
this.loggingBusControl = loggingBusControl;
}
public void Probe(ProbeContext context)
{
}
public async Task Send(T context, IPipe<T> next)
{
throw new Exception("Foo");
try
{
await next.Send(context);
}
catch (Exception ex)
{
}
}
}
There is my simple abstraction over IBusControl
public class LoggingBusControl : ILoggingBusControl
{
private readonly IBusControl busControl;
public LoggingBusControl()
{
busControl = GetBusControl();
busControl.Start();
}
private static IBusControl GetBusControl()
{
var busControl = Bus.Factory.CreateUsingRabbitMq(x =>
{
var host = x.Host(new Uri("rabbitmq://localhost/#/queues/%2F/logging_queue"), h =>
{
h.Username("guest");
h.Password("guest");
});
});
return busControl;
}
public void Log<T>(T log) where T : ILog
{
busControl.Publish<ILog>(log);
}
}
Usage
builder.Register(context =>
{
var busControl = Bus.Factory.CreateUsingRabbitMq(rabbitMqConfig =>
{
var host = rabbitMqConfig.Host(new Uri(ConfigurationManager.AppSettings["RabbitMQHost"]), h =>
{
h.Username("guest");
h.Password("guest");
});
var logger = context.Resolve<ILoggingBusControl>();
rabbitMqConfig.UseLogger(logger);
});
return busControl;
})
.SingleInstance()
.As<IBusControl>()
.As<IBus>()
.OnActivated(args => args.Instance.Start());
Then I inject IBusControl in controller constructor
public OrderController(IOrderService orderService,IBusControl busControl)
{
this.orderService = orderService;
this.busControl = busControl;
}
Messages are publised correctly and ExceptionLoggerFilter, ExceptionLoggerSpecification constructors are called, but methods Probe and Send in ExceptionLoggerFilter are never invoked. What I am doing wrong ?
ILoggingBusControlthing, whatever is it for, and in the container registration? - Alexey ZimarevILoggingBusControlis shared across multiple web services. Just for centralized logging. But this have no impact for my problem. Without it, this doesnt work either. - TjDillashawUseLoggercustom extension method? - Alexey ZimarevMassTransitLoggerExtenionsclass - TjDillashawOnActivatedis not really a good choice there. I would also suggest using Audit for this purpose masstransit-project.com/MassTransit/advanced/audit. You just need to implement theIMessageAuditStoreinterface (it has one method). - Alexey Zimarev