Gregor Zeitlinger 87615cc9d9 add support for OTEL_RESOURCE_ATTRIBUTES, OTEL_SERVICE_NAME, OTEL_EXPORTER_OTLP_HEADERS and OTEL_EXPORTER_OTLP_PROTOCOL for spring boot starter (#9950) hace 1 año
..
src 87615cc9d9 add support for OTEL_RESOURCE_ATTRIBUTES, OTEL_SERVICE_NAME, OTEL_EXPORTER_OTLP_HEADERS and OTEL_EXPORTER_OTLP_PROTOCOL for spring boot starter (#9950) hace 1 año
README.md 87615cc9d9 add support for OTEL_RESOURCE_ATTRIBUTES, OTEL_SERVICE_NAME, OTEL_EXPORTER_OTLP_HEADERS and OTEL_EXPORTER_OTLP_PROTOCOL for spring boot starter (#9950) hace 1 año
build.gradle.kts 87615cc9d9 add support for OTEL_RESOURCE_ATTRIBUTES, OTEL_SERVICE_NAME, OTEL_EXPORTER_OTLP_HEADERS and OTEL_EXPORTER_OTLP_PROTOCOL for spring boot starter (#9950) hace 1 año

README.md

OpenTelemetry Spring Auto-Configuration

Auto-configures OpenTelemetry instrumentation for spring-web , spring-webmvc, and spring-webflux. Leverages Spring Aspect Oriented Programming, dependency injection, and bean post-processing to trace spring applications. To include all features listed below use the opentelemetry-spring-boot-starter.

Quickstart

Add these dependencies to your project

Replace OPENTELEMETRY_VERSION with the latest stable release.

  • Minimum version: 1.17.0

For Maven, add to your pom.xml dependencies:

<dependencies>
  <!-- opentelemetry -->
  <dependency>
    <groupId>io.opentelemetry.instrumentation</groupId>
    <artifactId>opentelemetry-spring-boot</artifactId>
    <version>OPENTELEMETRY_VERSION</version>
  </dependency>

  <dependency>
    <groupId>io.opentelemetry</groupId>
    <artifactId>opentelemetry-api</artifactId>
    <version>OPENTELEMETRY_VERSION</version>
  </dependency>

   <!-- simple span exporter -->
   <!-- outputs spans to console -->
   <!-- provides opentelemetry-sdk artifact -->
   <dependency>
    <groupId>io.opentelemetry</groupId>
    <artifactId>opentelemetry-exporter-logging</artifactId>
    <version>OPENTELEMETRY_VERSION</version>
  </dependency>

</dependencies>

For Gradle, add to your dependencies:

//opentelemetry spring auto-configuration
implementation("io.opentelemetry.instrumentation:opentelemetry-spring-boot:OPENTELEMETRY_VERSION")
//opentelemetry
implementation("io.opentelemetry:opentelemetry-api:OPENTELEMETRY_VERSION")
//opentelemetry exporter
implementation("io.opentelemetry:opentelemetry-exporters-otlp:OPENTELEMETRY_VERSION")

Features

Dependencies

The following dependencies are optional but are required to use the corresponding features.

Replace SPRING_VERSION with the version of spring you're using.

  • Minimum version: 3.1

Replace SPRING_WEBFLUX_VERSION with the version of spring-webflux you're using.

  • Minimum version: 5.0

For Maven, add to your pom.xml dependencies:

<dependencies>
  <!-- opentelemetry exporters-->
  <dependency>
    <groupId>io.opentelemetry</groupId>
    <artifactId>opentelemetry-exporter-jaeger</artifactId>
    <version>OPENTELEMETRY_VERSION</version>
  </dependency>
  <dependency>
    <groupId>io.opentelemetry</groupId>
    <artifactId>opentelemetry-exporter-zipkin</artifactId>
    <version>OPENTELEMETRY_VERSION</version>
  </dependency>
  <dependency>
    <groupId>io.opentelemetry</groupId>
    <artifactId>opentelemetry-exporter-otlp</artifactId>
    <version>OPENTELEMETRY_VERSION</version>
  </dependency>

  <!-- Used to autoconfigure spring-web -->
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-web</artifactId>
    <version>SPRING_VERSION</version>
  </dependency>

  <!-- Used to autoconfigure spring-webmvc -->
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>SPRING_VERSION</version>
  </dependency>

  <!-- Used to autoconfigure spring-webflux -->
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webflux</artifactId>
    <version>SPRING_WEBFLUX_VERSION</version>
  </dependency>

  <!-- Used to enable instrumentation using @WithSpan  -->
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-aop</artifactId>
    <version>SPRING_VERSION</version>
  </dependency>
  <dependency>
    <groupId>io.opentelemetry</groupId>
    <artifactId>opentelemetry-extension-annotations</artifactId>
    <version>OPENTELEMETRY_VERSION</version>
  </dependency>
</dependencies>

For Gradle, add to your dependencies:

//opentelemetry exporter
implementation("io.opentelemetry:opentelemetry-exporter-jaeger:OPENTELEMETRY_VERSION")
implementation("io.opentelemetry:opentelemetry-exporter-zipkin:OPENTELEMETRY_VERSION")
implementation("io.opentelemetry:opentelemetry-exporter-otlp:OPENTELEMETRY_VERSION")

//Used to autoconfigure spring-web
implementation("org.springframework:spring-web:SPRING_VERSION")

//Used to autoconfigure spring-webmvc
implementation("org.springframework:spring-webmvc:SPRING_VERSION")

//Used to autoconfigure spring-webflux
implementation("org.springframework:spring-webflux:SPRING_WEBFLUX_VERSION")

//Enables instrumentation using @WithSpan
implementation("org.springframework:spring-aop:SPRING_VERSION")
implementation("io.opentelemetry:opentelemetry-extension-annotations:OPENTELEMETRY_VERSION")

OpenTelemetry Auto Configuration

Spring Web Auto Configuration

Provides auto-configuration for the OpenTelemetry RestTemplate trace interceptor defined in opentelemetry-spring-web-3.1. This auto-configuration instruments all requests sent using Spring RestTemplate beans by applying a RestTemplate bean post processor. This feature is supported for spring web versions 3.1+. Spring Web - RestTemplate Client Span show cases a sample client span generated by this auto-configuration. Check out opentelemetry-spring-web-3.1 to learn more about the OpenTelemetry RestTemplateInterceptor.

Spring Web MVC Auto Configuration

This feature autoconfigures instrumentation for Spring WebMVC controllers by adding a telemetry producing servlet Filter bean to the application context. This filter decorates the request execution with an OpenTelemetry server span, propagating the incoming tracing context if received in the HTTP request. Check out opentelemetry-spring-webmvc-5.3 instrumentation library to learn more about the OpenTelemetry Spring WebMVC instrumentation.

Spring WebFlux Auto Configuration

Provides auto-configurations for the OpenTelemetry WebClient ExchangeFilter defined in opentelemetry-spring-webflux-5.3. This auto-configuration instruments all outgoing http requests sent using Spring's WebClient and WebClient Builder beans by applying a bean post processor. This feature is supported for spring webflux versions 5.0+. Spring Web-Flux - WebClient Span showcases a sample span generated by the WebClientFilter. Check out opentelemetry-spring-webflux-5.3 to learn more about the OpenTelemetry WebClientFilter.

Manual Instrumentation Support - @WithSpan

This feature uses spring-aop to wrap methods annotated with @WithSpan in a span. The arguments to the method can be captured as attributed on the created span by annotating the method parameters with @SpanAttribute.

Note - This annotation can only be applied to bean methods managed by the spring application context. Check out spring-aop to learn more about aspect weaving in spring.

Usage
import org.springframework.stereotype.Component;

import io.opentelemetry.instrumentation.annotations.SpanAttribute;
import io.opentelemetry.instrumentation.annotations.WithSpan;
import io.opentelemetry.api.trace.Span;
import io.opentelemetry.api.trace.SpanKind;

/**
 * Test WithSpan
 */
@Component
public class TracedClass {

    @WithSpan
    public void tracedMethod() {
    }

    @WithSpan(value="span name")
    public void tracedMethodWithName() {
        Span currentSpan = Span.current();
        currentSpan.addEvent("ADD EVENT TO tracedMethodWithName SPAN");
        currentSpan.setAttribute("isTestAttribute", true);
    }

    @WithSpan(kind = SpanKind.CLIENT)
    public void tracedClientSpan() {
    }

    public void tracedMethodWithAttribute(@SpanAttribute("attributeName") String parameter) {
    }
}

Sample Traces

The traces below were exported using Zipkin.

Spring Web MVC - Server Span
   {
      "traceId":"0371febbbfa76b2e285a08b53a055d17",
      "id":"9b782243ad7df179",
      "kind":"SERVER",
      "name":"webmvctracingfilter.dofilterinteral",
      "timestamp":1596841405866633,
      "duration":355648,
      "localEndpoint":{
         "serviceName":"sample_trace",
         "ipv4":"XXX.XXX.X.XXX"
      },
      "tags":{
         "http.client_ip":"0:0:0:0:0:0:0:1",
         "http.flavor":"1.1",
         "http.method":"GET",
         "http.status_code":"200",
         "http.url":"/spring-webmvc/sample",
         "http.user_agent":"PostmanRuntime/7.26.2",
         "net.sock.peer.addr":"0:0:0:0:0:0:0:1",
         "net.sock.peer.port":"33916",
         "net.sock.family":"inet6"
         "sampling.probability":"1.0"
      }
   }
Spring Web - RestTemplate Client Span
{
  "traceId": "0371febbbfa76b2e285a08b53a055d17",
  "parentId": "9b782243ad7df179",
  "id": "43990118a8bdbdf5",
  "kind": "CLIENT",
  "name": "http get",
  "timestamp": 1596841405949825,
  "duration": 21288,
  "localEndpoint": {
    "serviceName": "sample_trace",
    "ipv4": "XXX.XXX.X.XXX"
  },
  "tags": {
    "http.method": "GET",
    "http.status_code": "200",
    "http.url": "/spring-web/sample/rest-template",
    "net.peer.name": "localhost",
    "net.peer.port": "8081"
  }
}
Spring Web-Flux - WebClient Span
{
  "traceId": "0371febbbfa76b2e285a08b53a055d17",
  "parentId": "9b782243ad7df179",
  "id": "1b14a2fc89d7a762",
  "kind": "CLIENT",
  "name": "http post",
  "timestamp": 1596841406109125,
  "duration": 25137,
  "localEndpoint": {
    "serviceName": "sample_trace",
    "ipv4": "XXX.XXX.X.XXX"
  },
  "tags": {
    "http.method": "POST",
    "http.status_code": "200",
    "http.url": "/spring-webflux/sample/web-client",
    "net.peer.name": "localhost",
    "net.peer.port": "8082"
  }
}
@WithSpan Instrumentation
[
   {
      "traceId":"0371febbbfa76b2e285a08b53a055d17",
      "parentId":"9b782243ad7df179",
      "id":"c3ef24b9bff5901c",
      "name":"tracedclass.withspanmethod",
      "timestamp":1596841406165439,
      "duration":6912,
      "localEndpoint":{
         "serviceName":"sample_trace",
         "ipv4":"XXX.XXX.X.XXX"
      },
      "tags":{
         "test.type":"@WithSpan annotation",
         "test.case":'@WithSpan',
         "test.hasEvent":'true',
      }
   },
   {
      "traceId":"0371febbbfa76b2e285a08b53a055d17",
      "parentId":"9b782243ad7df179",
      "id":"1a6cb395a8a33cc0",
      "name":"@withspan set span name",
      "timestamp":1596841406182759,
      "duration":2187,
      "localEndpoint":{
         "serviceName":"sample_trace",
         "ipv4":"XXX.XXX.X.XXX"
      },
      "annotations":[
         {
            "timestamp":1596841406182920,
            "value":"ADD EVENT TO tracedMethodWithName SPAN"
         }
      ],
      "tags":{
         "test.type":"@WithSpan annotation",
         "test.case":'@WithSpan(value="@withspan set span name")',
         "test.hasEvent":'true',
      }
   },
   {
      "traceId":"0371febbbfa76b2e285a08b53a055d17",
      "parentId":"9b782243ad7df179",
      "id":"74dd19a8a9883f80",
      "kind":"CLIENT",
      "name":"tracedClientSpan",
      "timestamp":1596841406194210,
      "duration":130,
      "localEndpoint":{
         "serviceName":"sample_trace",
         "ipv4":"XXX.XXX.X.XXX"
      }
      "tags":{
         "test.type":"@WithSpan annotation",
         "test.case":"@WithSpan(kind=SpanKind.Client)",
      }
   },
]

Spring Support

Auto-configuration is natively supported by Springboot applications. To enable these features in "vanilla" use @EnableOpenTelemetry to complete a component scan of this package.

Usage
import io.opentelemetry.instrumentation.spring.autoconfigure.EnableOpenTelemetry;
import org.springframework.context.annotation.Configuration;

@Configuration
@EnableOpenTelemetry
public class OpenTelemetryConfig {}

Exporter Configurations

This package provides auto configurations for OTLP, Jaeger, Zipkin, and Logging Span Exporters.

If an exporter is present in the classpath during runtime and a spring bean of the exporter is missing from the spring application context. An exporter bean is initialized and added to a simple span processor in the active tracer provider. Check out the implementation here.

Configuration Properties

Enabling/Disabling Exporters

All exporters can be enabled or disabled as in the SDK auto-configuration. This is the preferred way to enable/disable exporters and takes precedence over the properties below.

Feature Property Default Value ConditionalOnClass
Otlp Exporter otel.exporter.otlp.enabled true -
Otlp Span Exporter otel.exporter.otlp.traces.enabled true OtlpGrpcSpanExporter
Otlp Metrics Exporter otel.exporter.otlp.metrics.enabled true OtlpGrpcMetricExporter
Otlp Logs Exporter otel.exporter.otlp.logs.enabled true OtlpGrpcLogRecordExporter
Jaeger Exporter otel.exporter.jaeger.enabled true JaegerGrpcSpanExporter
Zipkin Exporter otel.exporter.zipkin.enabled true ZipkinSpanExporter
Logging Exporter otel.exporter.logging.enabled false LoggingSpanExporter
Enabling/Disabling Features
Feature Property Default Value ConditionalOnClass
spring-web otel.instrumentation.spring-webmvc.enabled true RestTemplate
spring-webmvc otel.instrumentation.spring-web.enabled true OncePerRequestFilter
spring-webflux otel.instrumentation.spring-webflux.enabled true WebClient
@WithSpan otel.instrumentation.annotations.enabled true WithSpan, Aspect
Resource Properties
Feature Property Default Value
Resource otel.springboot.resource.enabled true
otel.resource.attributes (old: otel.springboot.resource.attributes) empty map

otel.resource.attributes supports a pattern-based resource configuration in the application.properties like this:

otel.resource.attributes.environment=dev
otel.resource.attributes.xyz=foo

It's also possible to specify the resource attributes in application.yaml:

otel:
  resource:
    attributes:
      environment: dev
      xyz: foo

Finally, the resource attributes can be specified as a comma-separated list, as described in the specification:

export OTEL_RESOURCE_ATTRIBUTES="key1=value1,key2=value2"

The service name is determined by the following precedence, in accordance with the OpenTelemetry specification:

  1. otel.service.name spring property or OTEL_SERVICE_NAME environment variable (highest precedence)
  2. service.name in otel.resource.attributes system/spring property or OTEL_RESOURCE_ATTRIBUTES environment variable
  3. service.name in otel.springboot.resource.attributes system/spring property
  4. spring.application.name spring property
  5. the default value unknown_service:java (lowest precedence)
Exporter Properties
Feature Property Default Value
Otlp Exporter otel.exporter.otlp.endpoint localhost:4317
otel.exporter.otlp.protocol grpc
otel.exporter.otlp.headers
otel.exporter.otlp.timeout 1s
Jaeger Exporter otel.exporter.jaeger.endpoint localhost:14250
otel.exporter.jaeger.timeout 1s
Zipkin Exporter otel.exporter.jaeger.endpoint http://localhost:9411/api/v2/spans

The otel.exporter.otlp.headers property can be specified as a comma-separated list, which is compliant with the specification. Similar to the resource attributes, the headers can be specified in application.properties or application.yaml:

otel:
  exporter:
    otlp:
      headers:
        - key: "header1"
          value: "value1"
        - key: "header2"
          value: "value2"
Tracer Properties
Feature Property Default Value
Tracer otel.traces.sampler.probability 1.0

Starter Guide

Check out OpenTelemetry Manual Instrumentation to learn more about using the OpenTelemetry API to instrument your code.