question

KevinEverett-8120 avatar image
0 Votes"
KevinEverett-8120 asked SwathiDhanwada-MSFT commented

Correlate two AppInsights Resources based on NServiceBus communication

Currently, I have dozens of .NET services hosted on various machines that show up as Resources on my AppInsights Application Map, which also shows their dependencies with respect to each other, based on the HTTP requests they make.

However, the relationships between services that communicate through NServiceBus(RabbitMQ) are not shown. Now, I am able to show the messages either sent or handled by a service via calls to TelemetryClient.TrackXXX(), but not connect Resources on the map using this information.


I have even gone so far as to attach the parent operation ID from the NSB message sender to the message itself, and assign it to the telemetry object in the receiver, but there is still no line drawn between the services in the Application Map.

To reiterate, this is what I'm getting in the Application Map:

(NSB Message Sender) --> (Message sent/handled)


And this is what I want:

(NSB Sender) --> (Receiver)


The services in question are .NET Core 3.1

I cannot provide code, as this is for my work, but any help would be greatly appreciated. I've searched everywhere, and even sources that seemed like they would help, didn't.

azure-monitor
· 2
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

@KevinEverett-8120 Welcome to Microsoft Q & A Community Platform. Each of the components on application map could be different Application Insights resources, or different roles in a single resource. The app map finds components by following HTTP dependency calls made between servers with the Application Insights SDK installed.

From the information you have provided, I assume that you are trying to create dependency tracking among the components in application map. Ideally, application insights automatically collects dependencies and this document lists the calls that are automatically detected within the application map. As the NServiceBus is not part of aforementioned list, you may need to track it manually. On how to track the dependency calls manually, you may check this document.


0 Votes 0 ·
KevinEverett-0565 avatar image KevinEverett-0565 SwathiDhanwada-MSFT ·

Thanks for replying, Swathi. (i'm using my work account now)

I have been using Start/StopOperation with little success. Could you please elaborate?

What should be done in the sending service and the receiving service of these NSB messages? Do I have to somehow StartOperation in the sender, serialize the IOperationHolder, and StopOperation in the receiver?

0 Votes 0 ·

1 Answer

KevinEverett-0565 avatar image
1 Vote"
KevinEverett-0565 answered SwathiDhanwada-MSFT commented

Alright, I finally got it. My approach to correlate AppInsights resources using their NSB communication is to mimic HTTP telemetry correlation.

Below is an extension method I wrote for AppInsights' TelemetryClient. I made a subclass named RbmqMessage:NServiceBus.IMessage, given my applications use RBMQ, and gave it the following properties for the sake of correlation (all set in the service that sends the message) :
- parentId: equal to DependencyTelemetry.Id
- opId: value is the same in the sender's DependencyTelemetry and the receiver's RequestTelemetry. Equal to telemetry.context.operation.id
- startTime: DateTime.Now was good enough for my purposes

The code in the service that sends the NSB message:

 public static RbmqMessage TrackRbmq(this TelemetryClient client, RbmqMessage message)
  {
          var msg = message;
          // I ran into some issues with Reflection
          var classNameIdx = message.ToString().LastIndexOf('.') + 1;
          var messageClassName = message.ToString().Substring(classNameIdx);
          var telemetry = new DependencyTelemetry
          {   
                  Type = "RabbitMQ", 
                  Data = "SEND "+messageClassName,
                  Name = "SEND "+messageClassName,
                  Timestamp = DateTime.Now,
                  Target = "RECEIVE "+messageClassName  //matches name in the service receiving this message
           };
           client.TrackDependency(telemetry);
           msg.parentId = telemetry.Id;
           msg.opId = telemetry.Context.Operation.Id; //this wont have a value until TrackDependency is called
           msg.startTime = telemetry.Timestamp;
    
      return msg;
 }

The code where you send the NSB message:

 var msg = new MyMessage();   //make your existing messages inherit RbmqMessage
 var correlatedMessage = _telemetryClient.TrackRbmq(msg);
 MessageSession.Publish(correlatedMessage);   //or however the NSB message goes out in your application

The extension method in the NServiceBus message-receiving service:

   public static void TrackRbmq(this TelemetryClient client, RbmqMessage message)
  {
       var classnameIdx = message.ToString().LastIndexOf('.')+1;
       var telemetry = new RequestTelemetry
       {
             Timestamp = DateTime.Now,
             Name = "RECEIVE "+message.ToString().Substring(classNameIdx)
       };
       telemetry.Context.Operation.ParentId = message.parentId;
       telemetry.Context.Operation.Id = message.opId;
       telemetry.Duration = message.startTime - telemetry.Timestamp;
       client.TrackRequest(telemetry);
 }

And finally, just track and send the message:

 var msg = new MyMessage();
 _telemetryClient.TrackRbmq(msg);
 MessagePipeline.Send(msg);  //or however its sent in your app


I hope this saves someone the trouble I went through.





















· 1
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

@KevinEverett-8120 Glad to know that you have resolved the issue. Thanks for sharing the solution for the benefit of broader community. I would suggest you to accept the answer.

0 Votes 0 ·