1
votes

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 ?

1
What is the point in configuring the bus in this ILoggingBusControl thing, whatever is it for, and in the container registration? - Alexey Zimarev
ILoggingBusControl is shared across multiple web services. Just for centralized logging. But this have no impact for my problem. Without it, this doesnt work either. - TjDillashaw
What is the code of UseLogger custom extension method? - Alexey Zimarev
I've post it also. Look at MassTransitLoggerExtenions class - TjDillashaw
I might suggest that OnActivated is 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 the IMessageAuditStore interface (it has one method). - Alexey Zimarev

1 Answers

0
votes

You have not specified if you try to use the middleware for messages being sent vs messages being consumed, but from your question it appears that you try to use it for messages being sent.

If this is the case (or for anyone that comes across this question with the same issue) please note that the middleware described in the Mass Transit documentation works only for messages being consumed, not for messages being sent.

For logging messages, especially messages being sent, you are better off using the Mass Transit audit feature as @Alexey Zimarev mentioned in his comment.