How do we use OpenTelemetry for a spring boot application to track http request and response json on app insights

Vipin Sharma 121 Reputation points
2023-04-10T13:33:21.2066667+00:00

I am working on a spring boot app and spring cloud function, both are deployed over app service on azure. spring boot version 2.7.5, latest versions have some app insights related bugs. I want to track request and response json messages along with other details app insights provide by default. I am using spring RestTemplate and it supports a custom interceptor ( ClientHttpRequestInterceptor), that can help us to capture details. I can write this code, took reference from https://github.com/open-telemetry/opentelemetry-java-instrumentation/tree/main/instrumentation/spring/spring-web/spring-web-3.1/library Imports are different than the example, somehow these is what complies fine for me.

package com.msci.mis.mcp.fapp;


import io.opentelemetry.api.OpenTelemetry;
import io.opentelemetry.instrumentation.spring.web.v3_1.SpringWebTelemetry;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

@Configuration
public class RestTemplateConfig {

  @Bean
  public RestTemplate restTemplate(OpenTelemetry openTelemetry) {

    RestTemplate restTemplate = new RestTemplate();
    SpringWebTelemetry telemetry = SpringWebTelemetry.create(openTelemetry);
    restTemplate.getInterceptors().add(telemetry.newInterceptor());

    return restTemplate;
  }

}

Now for above code I need to create OpenTelemetry bean, this is what I am trying and not able to create a necessary SpanProcessor, that can send data into app insights. is there any working example that I can follow?

@Configuration
public class OpenTelemetryConfig {

  @Bean
  public OpenTelemetry openTelemetry() {

    // How do we create spanProcessor that send data into app insights?
    io.opentelemetry.sdk.trace.SpanProcessor spanProcessor;
                                
    // Configure the SdkTracerProvider with the BatchSpanProcessor and default Sampler.
    SdkTracerProvider tracerProvider = SdkTracerProvider.builder()
                                                        .addSpanProcessor(spanProcessor)
                                                        .build();

    // Create an OpenTelemetry instance with the configured SdkTracerProvider.
    return OpenTelemetrySdk.builder()
                           .setTracerProvider(tracerProvider)
                           .build();
  }
}

I tried to see documentation given at https://learn.microsoft.com/en-us/azure/azure-monitor/app/opentelemetry-enable?tabs=java , it talks about Creating Span with an attribute but that is too low level, in this way I may not be able to use features OpenTelemetery provides and may need to create Span/Attributes for all use cases I have.

Azure Monitor
Azure Monitor
An Azure service that is used to collect, analyze, and act on telemetry data from Azure and on-premises environments.
3,645 questions
Azure App Service
Azure App Service
Azure App Service is a service used to create and deploy scalable, mission-critical web apps.
8,930 questions
{count} votes

1 answer

Sort by: Most helpful
  1. VasimTamboli 5,215 Reputation points
    2023-04-26T18:55:08.4433333+00:00

    Please try below solution if it helps. Example

    To use OpenTelemetry with App Insights in a Spring Boot application,

    1. Add the following dependencies to your pom.xml file:
    <dependency>
      <groupId>io.opentelemetry</groupId>
      <artifactId>opentelemetry-api</artifactId>
      <version>1.10.0</version>
    </dependency>
    <dependency>
      <groupId>io.opentelemetry</groupId>
      <artifactId>opentelemetry-sdk</artifactId>
      <version>1.10.0</version>
    </dependency>
    <dependency>
      <groupId>io.opentelemetry</groupId>
      <artifactId>opentelemetry-exporter-azuremonitor</artifactId>
      <version>1.0.2</version>
    </dependency>
    <dependency>
      <groupId>io.opentelemetry</groupId>
      <artifactId>opentelemetry-instrumentation-spring-web</artifactId>
      <version>1.10.0</version>
    </dependency>
    
    
    1. Create a RestTemplate bean with a custom interceptor that captures request and response details. You can use the SpringWebTelemetry class provided by OpenTelemetry to create the interceptor:
    @Bean
    public RestTemplate restTemplate(OpenTelemetry openTelemetry) {
      RestTemplate restTemplate = new RestTemplate();
      restTemplate.getInterceptors().add(new RestTemplateInterceptor(openTelemetry));
      return restTemplate;
    }
    
    private static class RestTemplateInterceptor implements ClientHttpRequestInterceptor {
      private final SpringWebTelemetry telemetry;
    
      public RestTemplateInterceptor(OpenTelemetry openTelemetry) {
        this.telemetry = SpringWebTelemetry.create(openTelemetry);
      }
    
      @Override
      public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
        Span span = this.telemetry.startSpan(request, request.getURI().toString(), request.getHeaders());
        try (Scope ignored = span.makeCurrent()) {
          ClientHttpResponse response = execution.execute(request, body);
          this.telemetry.onResponse(span, response);
          return response;
        } catch (Exception e) {
          this.telemetry.endExceptionally(span, e);
          throw e;
        } finally {
          this.telemetry.end(span);
        }
      }
    }
    
    
    1. Create an OpenTelemetry bean with an AzureMonitorSpanExporter that sends data to App Insights:
    @Bean
    public OpenTelemetry openTelemetry() {
      AzureMonitorExporter exporter = new AzureMonitorExporterBuilder()
          .connectionString(System.getenv("APPINSIGHTS_CONNECTION_STRING"))
          .buildExporter();
    
      BatchSpanProcessor spanProcessor = BatchSpanProcessor.builder(exporter)
          .setMaxExportBatchSize(1024)
          .setMaxQueueSize(1024 * 1024)
          .build();
    
      TracerSdkProvider tracerProvider = TracerSdkProvider.builder()
          .addSpanProcessor(spanProcessor)
          .build();
    
      return OpenTelemetrySdk.builder()
          .setTracerProvider(tracerProvider)
          .buildAndRegisterGlobal();
    }
    
    
    1. Set the APPINSIGHTS_CONNECTION_STRING environment variable to the connection string for your App Insights instance. You can find this connection string in the Azure portal by going to your App Insights resource and selecting "Export" from the menu.

    With these changes, your Spring Boot application should now send telemetry data to App Insights, including request and response details captured by the custom interceptor.

    0 comments No comments

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.