0
votes

I've been trying to setup the custom metrics inside NewRelic for MassTransit similar to how NServiceBus works with NewRelic. It seems that this is pretty easy to achieve using the NewRelic .Net Custom Transactions documentation.

So far from checking out the MassTransit code on GitHub I've manage to put together a simple instrumentation file for MassTransit but this only contains Message Sends, but I really want message received as well but i cant seem to find the first interception which is not tied to a transport implementation.

<?xml version="1.0" encoding="utf-8"?>
<extension xmlns="urn:newrelic-extension">
    <instrumentation>
        <tracerFactory metricName="MassTransit/Send">
            <match assemblyName="MassTransit" className="MassTransit.Transports.SendEndpoint">
                <exactMethodMatcher methodName="Send" parameters="!!0,System.Threading.CancellationToken" />
                <exactMethodMatcher methodName="Send" parameters="!!0,MassTransit.Pipeline.IPipe`1[MassTransit.SendContext`1[!!0]],System.Threading.CancellationToken" />
            </match>
        </tracerFactory>
    </instrumentation>
</extension>

The example of the NServiceBus instrumentation file that I'm trying to create the equivalent MassTransit one is below:

<?xml version="1.0" encoding="utf-8"?>
<extension xmlns="urn:newrelic-extension">
    <instrumentation>
        <tracerFactory>
            <match assemblyName="NServiceBus.Core" className="NServiceBus.InvokeHandlersBehavior">
                <exactMethodMatcher methodName="Invoke" parameters="NServiceBus.Pipeline.Contexts.IncomingContext,System.Action" />
            </match>
        </tracerFactory>
        <tracerFactory>
            <match assemblyName="NServiceBus.Core" className="NServiceBus.Unicast.UnicastBus">
                <exactMethodMatcher methodName="SendMessage" parameters="NServiceBus.Unicast.SendOptions,NServiceBus.Unicast.Messages.LogicalMessage" />
            </match>
        </tracerFactory>
    </instrumentation>
</extension>

UPDATE

As suggested by Chris Patterson I've updated to the new package so there is a method I can hook on to within the ReceivePipe.

I've tried to then instrument this method but with no success, i can how ever see the that its possible to instrument within the logs when turning on the ALL logging:

[Trace] 2015-10-19 09:08:45 Possibly instrumenting: (Module: D:\Liberis\Services\Liberis.Salesforce.Service\MassTransit.dll, AppDomain: Liberis.Salesforce.Service.exe)[MassTransit]MassTransit.Pipeline.Pipes.ReceivePipe.MassTransit.Pipeline.IPipe<MassTransit.ReceiveContext>.Send(MassTransit.ReceiveContext)

I've also tried updating the the configuration to the following to match the above but still had no success:

<?xml version="1.0" encoding="utf-8"?>
<extension xmlns="urn:newrelic-extension">
    <instrumentation>
        <tracerFactory name="NewRelic.Agent.Core.Tracer.Factories.BackgroundThreadTracerFactory" metricName="MassTransit/Receive">
            <match assemblyName="MassTransit" className="MassTransit.Pipeline.Pipes.ReceivePipe.MassTransit.Pipeline.IPipe<MassTransit.ReceiveContext>">
                <exactMethodMatcher methodName="Send" parameters="MassTransit.ReceiveContext" />
            </match>
        </tracerFactory>
    </instrumentation>
</extension>

I've also tried to use the nrconfig tool but that only outputs the following for the ReceivePipe class:

  <match assemblyName="MassTransit" className="MassTransit.Pipeline.Pipes.ReceivePipe">
    <exactMethodMatcher methodName=".ctor" parameters="MassTransit.Pipeline.IPipe`1&lt;MassTransit.ReceiveContext&gt;,MassTransit.Pipeline.IConsumePipe" />
  </match>

I have a feeling that I need to instrument it differently due to the class implicitly implementing the IPipe<ReceiveContext> interface?

2
Added to the google group too just to increase Visibility, will keep them both updated. Thanks - Kevin Smith
np. note that new posters to the group are moderated, so it might not show up straight away. - stuartd
So this is instrumenting the code itself, not hooking into it at the API level? - Chris Patterson
Just instrumenting the code similar to Fody, so they are just wrapping method calls. - Kevin Smith

2 Answers

1
votes

You should be able to hook the ReceivePipe.Send method in a similar fashion.

https://github.com/MassTransit/MassTransit/blob/master/src/MassTransit/Pipeline/Pipes/ReceivePipe.cs#L30

<?xml version="1.0" encoding="utf-8"?>
<extension xmlns="urn:newrelic-extension">
    <instrumentation>
        <tracerFactory metricName="MassTransit/Receive">
            <match assemblyName="MassTransit" className="MassTransit.Pipeline.Pipe.ReceivePipe">
                <exactMethodMatcher methodName="Send" parameters="ReceiveContext" />
            </match>
        </tracerFactory>
    </instrumentation>
</extension>

At least, that's my guess on the XML syntax, but the method is sound.

0
votes

With some help from @Chris Patterson I've managed to figure it out, lot more effort than I thought it should of been.

Below is the configuration xml that is required:

<?xml version="1.0" encoding="utf-8"?>
<extension xmlns="urn:newrelic-extension">
    <instrumentation>
        <tracerFactory name="NewRelic.Agent.Core.Tracer.Factories.BackgroundThreadTracerFactory" metricName="MassTransit/Send">
            <match assemblyName="MassTransit" className="MassTransit.Transports.SendEndpoint">
                <exactMethodMatcher methodName="Send" parameters="!!0,System.Threading.CancellationToken" />
                <exactMethodMatcher methodName="Send" parameters="!!0,MassTransit.Pipeline.IPipe`1[MassTransit.SendContext`1[!!0]],System.Threading.CancellationToken" />
            </match>
        </tracerFactory>
        <tracerFactory name="NewRelic.Agent.Core.Tracer.Factories.BackgroundThreadTracerFactory" metricName="MassTransit/Receive">
            <match assemblyName="MassTransit" className="MassTransit.Pipeline.Pipes.ReceivePipe">
                <exactMethodMatcher methodName="MassTransit.Pipeline.IPipe&lt;MassTransit.ReceiveContext&gt;.Send" parameters="MassTransit.ReceiveContext" />
            </match>
        </tracerFactory>
    </instrumentation>
</extension>

Seems like the method signature totally changes due to implicitly implementing the IPipe interface.

I've also added this to a github repository - https://github.com/LiberisLabs/NewRelic.Agent.CustomTransactions