Distributed Tracing with Application Insights with Java talking with Azure Functions

Tsuyoshi Ushio
4 min readJan 2, 2019

I’m writing a sample of the Distributed Tracing sample with Application Insights. NOTE: This blog is under experiment. I might change the contents in the near future.

Distributed Tracing with Application Insights with Java and Azure Functions

Goal

My customer wants distributed tracing like this.

Http -> HttpTrigger(Azure Functions) -> Storage Queue-> Storage Queue Trigger (Azure Functions) -> Http -> Spring boot -> Service Bus Queue

I’m a beginner of Java Programming these days. I don’t know how to implement Java part.

In this article, I focus on Java and Http Correlation Protocol implementation.

Prerequisite

If you don’t familiar with the concept of the distributed tracing tracking with Application Insights, please refer this blog post.

Sending Request Telemetry

Sending Request Telemetry is very easy. Just follow the official document.
In short, all you need to do is

  • Getting Instrument Key from Application Insights on Azure
  • Adding dependency to your Gradle or Maven
  • Add ApplicationInsights.xml
  • Add an Http filter

The request telemetry is automatically send to the Application Insights.

Where the correlation Id reside?

In care of Http Request, it is sent by HTTP Header “Request-Id” You can refer which Request-Id is coming.

String parentRequestId = requestEntity.getHeaders().getFirst("Request-Id");

The filter receive the “Request-Id” and generate the new Id for correlation. You can see the source code in here.

Where is the Activity class in Java SDK

In C#, Activity class plays key role of the Correlation. It plays

  • Generate a new Id from parent Id
  • Has a Correlation properties(Id, RootId, ParentId)
  • Share the Activity object using AsyncLocal with Activity.Current

In case of Java SDK, they have helper class instead.

For the Http Correlation protocol, you can refer the TelemetryCorrelationUtils,

FYI, For the W3C Trace Context, you can use TraceContextCorrelation

What the filter do?

The filter will do

  • Generate new Id from the parent Id which is obtained from “Request-Id”
  • Create RequestTelemetryContext and RequestTelemetry object
  • Store the RequestTelemetryContext on the ThreadContext class
  • Send the RequestTelemetry using TelemetryClient

How can I get the new RequestTelemetryId?

The filter automatically create a new Id and send a telemetry. It is fine. However, if you want to send dependency telemetry, you need the parent id which means RequestTelemetry.getId().

You can get the current RequestTelemetryId using ThreadContext class.

RequestTelemetryContext context = ThreadContext.getRequestTelemetryContext();RequestTelemetry requestTelemetry = context.getHttpRequestTelemetry();System.out.println(String.format(currentTemplate,requestTelemetry.getId(),requestTelemetry.getContext().getOperation().getId(), // RootIdrequestTelemetry.getContext().getOperation().getParentId() ));

As you can get the RequestTelemetryContext from the ThreadContext class. Inside of the class, they use ThreadLocal to share the context object. Then you can get RequestTelemetry object from the context.

The correalation telemetry has been set already.

  • RequestTelemetry.Id : requestTelemetry.getId()
  • RootId : requestTelemetry.getContext().getOperation().getId()
  • ParentId: requestTelemetry.getContext().getOperation().getParentId()

If you want to manually send the telemetry, you can set the same parameter to that property.

Sending Dependency telemetry

Now you are ready to send dependency telemetry.

Generate Dependency Id

TelemetryCorrelationUtils class helps you out.

String dependencyId = TelemetryCorrelationUtils.generateChildDependencyId();

Inside of the generateChildDepndencyId it is refer the current RequestTelemetry by the ThreadContext class then create a new ID from the parent id which is the requst id.

Create DependencyTelemetry

We have RemoteDependencyTelemetry for this purpose. Simply create the instance, pass the name of the telemetry and pass the correlation id from the request Id.

RemoteDependencyTelemetry dependencyTelemetry = new RemoteDependencyTelemetry("Send ServiceBus Queue");dependencyTelemetry.setId(dependencyId);dependencyTelemetry.getContext().getOperation().setId(requestTelemetry.getContext().getOperation().getId());dependencyTelemetry.getContext().getOperation().setParentId(requestTelemetry.getId());

For the Duration of the DependencyTelemetry, you can use com.microsoft.applicationinsights.telemetry.Duration class.

Duration duration = new Duration(0,0,0,0,10); // set the duration 10 millisec as an example.dependencyTelemetry.setDuration(duration);

Send Dependency Telemetry

Now ready to send the dependnecy telemetry.

TelemetryConfiguration configuration = TelemetryConfiguration.getActive();TelemetryClient telemetryClient = new TelemetryClient(configuration);telemetryClient.trackDependency(dependencyTelemetry);

If you send a message to this controller, you can find the request/dependency telemetry is sent to the Application Insights.

Application Insights support HTTP dependency telemetry. However, in this case, I need to send Service Bus queue. All I need to do is sending the dependencyTelemetry.getId() as the ParentId with the Queue metadata.

Application Insights End to end tracing result

Whole Controller code is here.

You can find whole Azure Functions and Spring Boot sample in here.

Conclusion

I successfully sent the Request/Dependency telemetry by Spring Boot Java application. The next step will be

  • Send Correlation information to the ServiceBus
  • W3C TraceContext sample
  • Create a following sample of the Azure Functions

I hope this article is helpful for someone.

--

--