--- title: Spring Boot linkTitle: Spring Boot weight: 30 description: Spring Boot instrumentation for OpenTelemetry Java # prettier-ignore cSpell:ignore: autoconfigurations autoconfigures customizer datasource distro logback springboot webflux webmvc --- ## How to instrument Spring Boot with OpenTelemetry The [OpenTelemetry Java agent](..) with byte code instrumentation can cover most of your needs when instrumenting [Spring Boot](https://spring.io/projects/spring-boot) applications. Alternatively, the OpenTelemetry [Spring Boot starter] can help you in the following cases: - Spring Boot Native image applications for which the OpenTelemetry Java agent does not work - Startup overhead of the OpenTelemetry Java agent exceeds your requirements - OpenTelemetry Java agent might not work if your application already uses another Java monitoring agent - You can use the Spring Boot configuration files (`application.properties`, `application.yml`) to configure the OpenTelemetry Spring Boot starter which doesn't work with the OpenTelemetry Java agent [Spring Boot starter]: https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#using.build-systems.starters The OpenTelemetry Java agent has more automatic instrumentation features than the OpenTelemetry starter. You can use [OpenTelemetry instrumentations libraries](https://github.com/open-telemetry/opentelemetry-java-instrumentation/blob/main/docs/supported-libraries.md#libraries--frameworks) to complete the automatic instrumentation of the Spring Boot starter. ## OpenTelemetry Spring Boot starter ### Compatibility The OpenTelemetry Spring Boot starter works with Spring Boot 2.0 and 3.0, and Spring Boot native image applications. The [opentelemetry-java-examples/spring-native](https://github.com/open-telemetry/opentelemetry-java-examples/tree/main/spring-native) repository contains an example of a Spring Boot Native image application instrumented using the OpenTelemetry Spring Boot starter. ### Dependency management A Bill of Material ([BOM](https://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html#bill-of-materials-bom-poms)) ensures that versions of dependencies (including transitive ones) are aligned. Importing the `opentelemetry-bom` and `opentelemetry-instrumentation-bom-alpha` BOMs when using the OpenTelemetry starter is important to ensure version alignment across all OpenTelemetry dependencies. The following example shows how to import both BOMs using Maven: ```xml io.opentelemetry opentelemetry-bom {{% param vers.otel %}} pom import io.opentelemetry.instrumentation opentelemetry-instrumentation-bom-alpha {{% param vers.instrumentation %}}-alpha pom import ``` With Gradle and Spring Boot, you have [two ways](https://docs.spring.io/spring-boot/docs/current/gradle-plugin/reference/htmlsingle/) to import a BOM. You can use the Gradle’s native BOM support by adding `dependencies`: ```kotlin import org.springframework.boot.gradle.plugin.SpringBootPlugin plugins { id("java") id("org.springframework.boot") version "3.2.O" } dependencies { implementation(platform(SpringBootPlugin.BOM_COORDINATES)) implementation(platform("io.opentelemetry:opentelemetry-bom:{{% param vers.otel %}}")) implementation(platform("io.opentelemetry.instrumentation:opentelemetry-instrumentation-bom-alpha:{{% param vers.instrumentation %}}-alpha")) } ``` The other way with Gradle is to use the `io.spring.dependency-management` plugin and to import the BOMs in `dependencyManagement`: ```kotlin plugins { id("java") id("org.springframework.boot") version "3.2.O" id("io.spring.dependency-management") version "1.1.0" } dependencyManagement { imports { mavenBom("io.opentelemetry:opentelemetry-bom:{{% param vers.otel %}}") mavenBom("io.opentelemetry.instrumentation:opentelemetry-instrumentation-bom-alpha:{{% param vers.instrumentation %}}-alpha") } } ``` {{% alert title="Note" color="info" %}} Be careful not to mix up the different ways of configuring things with Gradle. For example, don't use `implementation(platform("io.opentelemetry:opentelemetry-bom:{{% param vers.otel %}}"))` with the `io.spring.dependency-management` plugin. {{% /alert %}} #### OpenTelemetry Starter dependency Add the dependency given below to enable the OpenTelemetry starter. The OpenTelemetry starter uses OpenTelemetry Spring Boot [autoconfiguration](https://docs.spring.io/spring-boot/docs/current/reference/html/using.html#using.auto-configuration). {{< tabpane text=true >}} {{% tab header="Maven (`pom.xml`)" lang=Maven %}} ```xml io.opentelemetry.instrumentation opentelemetry-spring-boot-starter ``` {{% /tab %}} {{% tab header="Gradle (`gradle.build`)" lang=Gradle %}} ```kotlin dependencies { implementation("io.opentelemetry.instrumentation:opentelemetry-spring-boot-starter") } ``` {{% /tab %}} {{< /tabpane>}} ### Configuration This spring starter supports [configuration metadata](https://docs.spring.io/spring-boot/docs/current/reference/html/configuration-metadata.html), which means that you can see and autocomplete all available properties in your IDE. #### General configuration The OpenTelemetry Starter supports all the [SDK Autoconfiguration](/docs/languages/java/automatic/configuration/#sdk-autoconfiguration) (since 2.2.0). You can set properties in the `application.properties` or the `application.yaml` file, or use environment variables. `application.properties` example: ```properties otel.propagators=tracecontext,b3 otel.resource.attributes=environment=dev,xyz=foo ``` `application.yaml` example: ```yaml otel: propagators: - tracecontext - b3 resource: attributes: environment: dev xyz: foo ``` Environment variables example: ```shell export OTEL_PROPAGATORS="tracecontext,b3" export OTEL_RESOURCE_ATTRIBUTES="environment=dev,xyz=foo" ``` Disable the OpenTelemetry Starter: {{% config_option name="otel.sdk.disabled" %}} Set the value to `true` to disable the starter, e.g. for testing purposes. {{% /config_option %}} #### Programmatic configuration You can use the `AutoConfigurationCustomizerProvider` for programmatic configuration. Programmatic configuration is recommended for advanced use cases, which are not configurable using properties. ##### Exclude actuator endpoints from tracing As an example, you can customize the sampler to exclude health check endpoints from tracing: {{< tabpane text=true >}} {{% tab header="Maven (`pom.xml`)" lang=Maven %}} ```xml io.opentelemetry.contrib opentelemetry-samplers 1.33.0-alpha ``` {{% /tab %}} {{% tab header="Gradle (`gradle.build`)" lang=Gradle %}} ```kotlin dependencies { implementation("io.opentelemetry.contrib:opentelemetry-samplers:1.33.0-alpha") } ``` {{% /tab %}} {{< /tabpane>}} ```java import io.opentelemetry.api.trace.SpanKind; import io.opentelemetry.contrib.sampler.RuleBasedRoutingSampler; import io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizerProvider; import io.opentelemetry.semconv.SemanticAttributes; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class Application { @Bean public AutoConfigurationCustomizerProvider otelCustomizer() { return p -> p.addSamplerCustomizer( (fallback, config) -> RuleBasedRoutingSampler.builder(SpanKind.SERVER, fallback) .drop(SemanticAttributes.URL_PATH, "^/actuator") .build()); } } ``` #### Resource Providers The OpenTelemetry Starter includes [common Resource Providers](https://github.com/open-telemetry/opentelemetry-java-instrumentation/tree/main/instrumentation/resources/library) and the following Spring Boot specific Resource Providers: ##### Distribution Resource Provider FQN: `io.opentelemetry.instrumentation.spring.autoconfigure.resources.DistroVersionResourceProvider` | Attribute | Value | | -------------------------- | ----------------------------------- | | `telemetry.distro.name` | `opentelemetry-spring-boot-starter` | | `telemetry.distro.version` | version of the starter | ##### Spring Resource Provider FQN: `io.opentelemetry.instrumentation.spring.autoconfigure.resources.SpringResourceProvider` | Attribute | Value | | ----------------- | ------------------------------------------------------------------------------------------------------------- | | `service.name` | `spring.application.name` or `build.version` from `build-info.properties` (see [Service name](#service-name)) | | `service.version` | `build.name` from `build-info.properties` | ##### AWS Resource Provider The [AWS Resource Provider](https://github.com/open-telemetry/opentelemetry-java-contrib/tree/main/aws-resources) can be added as a dependency: {{< tabpane text=true >}} {{% tab header="Maven (`pom.xml`)" lang=Maven %}} ```xml io.opentelemetry.contrib opentelemetry-aws-resources 1.33.0-alpha com.fasterxml.jackson.core jackson-core com.squareup.okhttp3 okhttp ``` {{% /tab %}} {{% tab header="Gradle (`gradle.build`)" lang=Gradle %}} ```kotlin implementation("io.opentelemetry.contrib:opentelemetry-aws-resources:1.33.0-alpha") { exclude("com.fasterxml.jackson.core", "jackson-core") exclude("com.squareup.okhttp3", "okhttp") } ``` {{% /tab %}} {{< /tabpane>}} ##### GCP Resource Provider The [GCP Resource Provider](https://github.com/open-telemetry/opentelemetry-java-contrib/tree/main/gcp-resources) can be added as a dependency: {{< tabpane text=true >}} {{% tab header="Maven (`pom.xml`)" lang=Maven %}} ```xml io.opentelemetry.contrib opentelemetry-gcp-resources 1.33.0-alpha com.fasterxml.jackson.core jackson-core ``` {{% /tab %}} {{% tab header="Gradle (`gradle.build`)" lang=Gradle %}} ```kotlin implementation("io.opentelemetry.contrib:opentelemetry-gcp-resources:1.33.0-alpha") { exclude("com.fasterxml.jackson.core", "jackson-core") } ``` {{% /tab %}} {{< /tabpane>}} #### Service name Using these resource providers, the service name is determined by the following precedence rules, in accordance with the OpenTelemetry [specification](/docs/languages/sdk-configuration/general/#otel_service_name): 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. `spring.application.name` spring property 4. `build-info.properties` 5. `Implementation-Title` from META-INF/MANIFEST.MF 6. The default value is `unknown_service:java` (lowest precedence) Use the following snippet in your pom.xml file to generate the `build-info.properties` file: {{< tabpane text=true >}} {{% tab header="Maven (`pom.xml`)" lang=Maven %}} ```xml ${project.artifactId} org.springframework.boot spring-boot-maven-plugin build-info repackage ``` {{% /tab %}} {{% tab header="Gradle (`gradle.build`)" lang=Gradle %}} ```kotlin springBoot { buildInfo { } } ``` {{% /tab %}} {{< /tabpane>}} ### Automatic instrumentation Automatic instrumentation is available for several frameworks: | Feature | Property | Default Value | | -------------- | ----------------------------------------------- | ------------- | | Logback | `otel.instrumentation.logback-appender.enabled` | true | | Spring Web | `otel.instrumentation.spring-web.enabled` | true | | Spring Web MVC | `otel.instrumentation.spring-webmvc.enabled` | true | | Spring WebFlux | `otel.instrumentation.spring-webflux.enabled` | true | #### Logback You can enable experimental features with system properties to capture attributes : | System property | Type | Default | Description | | -------------------------------------------------------------------------------------- | ------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------- | --- | | `otel.instrumentation.logback-appender.experimental-log-attributes` | Boolean | false | Enable the capture of experimental log attributes `thread.name` and `thread.id`. | | | `otel.instrumentation.logback-appender.experimental.capture-code-attributes` | Boolean | false | Enable the capture of [source code attributes]. Note that capturing source code attributes at logging sites might add a performance overhead. | | `otel.instrumentation.logback-appender.experimental.capture-marker-attribute` | Boolean | false | Enable the capture of Logback markers as attributes. | | `otel.instrumentation.logback-appender.experimental.capture-key-value-pair-attributes` | Boolean | false | Enable the capture of Logback key value pairs as attributes. | | `otel.instrumentation.logback-appender.experimental.capture-logger-context-attributes` | Boolean | false | Enable the capture of Logback logger context properties as attributes. | | `otel.instrumentation.logback-appender.experimental.capture-mdc-attributes` | String | | Comma separated list of MDC attributes to capture. Use the wildcard character `*` to capture all attributes. | [source code attributes]: /docs/specs/semconv/general/attributes/#source-code-attributes Alternatively, you can enable these features by adding the OpenTelemetry Logback appender in your `logback.xml` or `logback-spring.xml` file: ```xml %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n false true true true true * ``` #### Spring Web Autoconfiguration Provides autoconfiguration for the `RestTemplate` trace interceptor defined in [opentelemetry-spring-web-3.1](https://github.com/open-telemetry/opentelemetry-java-instrumentation/tree/main/instrumentation/spring/spring-web/spring-web-3.1/library). This autoconfiguration 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+. To learn more about the OpenTelemetry `RestTemplate` interceptor, see [opentelemetry-spring-web-3.1](https://github.com/open-telemetry/opentelemetry-java-instrumentation/tree/main/instrumentation/spring/spring-web/spring-web-3.1/library). #### Spring Web MVC Autoconfiguration This feature autoconfigures instrumentation for Spring WebMVC controllers by adding a [telemetry producing servlet `Filter`](https://github.com/open-telemetry/opentelemetry-java-instrumentation/blob/main/instrumentation/spring/spring-webmvc/spring-webmvc-5.3/library/src/main/java/io/opentelemetry/instrumentation/spring/webmvc/v5_3/WebMvcTelemetryProducingFilter.java) bean to the application context. The filter decorates the request execution with a server span, propagating the incoming tracing context if received in the HTTP request. To learn more about the OpenTelemetry Spring WebMVC instrumentation, see the [opentelemetry-spring-webmvc-5.3 instrumentation library](https://github.com/open-telemetry/opentelemetry-java-instrumentation/tree/main/instrumentation/spring/spring-webmvc/spring-webmvc-5.3/library). #### Spring WebFlux Autoconfiguration Provides autoconfigurations for the OpenTelemetry WebClient ExchangeFilter defined in [opentelemetry-spring-webflux-5.3](https://github.com/open-telemetry/opentelemetry-java-instrumentation/tree/main/instrumentation/spring/spring-webflux/spring-webflux-5.3/library). This autoconfiguration 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+. For details, see [opentelemetry-spring-webflux-5.3](https://github.com/open-telemetry/opentelemetry-java-instrumentation/tree/main/instrumentation/spring/spring-webflux/spring-webflux-5.3/library). ### Additional Instrumentations #### JDBC Instrumentation You have two ways to enable the JDBC instrumentation with the OpenTelemetry starter. If your application does not declare `DataSource` bean, you can update your `application.properties` file to have the data source URL starting with `jdbc:otel:` and set the driver class to `io.opentelemetry.instrumentation.jdbc.OpenTelemetryDriver`. ```properties spring.datasource.url=jdbc:otel:h2:mem:db spring.datasource.driver-class-name=io.opentelemetry.instrumentation.jdbc.OpenTelemetryDriver ``` You can also wrap the `DataSource` bean in an `io.opentelemetry.instrumentation.jdbc.datasource.OpenTelemetryDataSource`: ```java import io.opentelemetry.instrumentation.jdbc.datasource.JdbcTelemetry; @Configuration public class DataSourceConfig { @Bean public DataSource dataSource(OpenTelemetry openTelemetry) { DataSourceBuilder dataSourceBuilder = DataSourceBuilder.create(); //Data source configurations DataSource dataSource = dataSourceBuilder.build(); return JdbcTelemetry.create(openTelemetry).wrap(dataSource); } } ``` With the datasource configuration, you need to add the following dependency: {{< tabpane text=true >}} {{% tab header="Maven (`pom.xml`)" lang=Maven %}} ```xml io.opentelemetry.instrumentation opentelemetry-jdbc ``` {{% /tab %}} {{% tab header="Gradle (`gradle.build`)" lang=Gradle %}} ```kotlin dependencies { implementation("io.opentelemetry.instrumentation:opentelemetry-jdbc") } ``` {{% /tab %}} {{< /tabpane>}} #### Log4j2 Instrumentation You have to add the OpenTelemetry appender to your `log4j2.xml` file: ```xml ``` You can find more configuration options for the OpenTelemetry appender in the [Log4j](https://github.com/open-telemetry/opentelemetry-java-instrumentation/blob/main/instrumentation/log4j/log4j-appender-2.17/library/README.md) instrumentation library. #### Instrumentation Annotations 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. To learn more about aspect weaving in spring, see > [spring-aop](https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#aop). | Feature | Property | Default Value | ConditionalOnClass | | ----------- | ------------------------------------------ | ------------- | ------------------ | | `@WithSpan` | `otel.instrumentation.annotations.enabled` | true | WithSpan, Aspect | ```java 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) { } } ``` #### OpenTelemetry instrumentations libraries You can configure other instrumentations with [OpenTelemetry instrumentations libraries](https://github.com/open-telemetry/opentelemetry-java-instrumentation/blob/main/docs/supported-libraries.md#libraries--frameworks). ## Other solutions Instead of using the OpenTelemetry Spring starter, you can use the OpenTelemetry autoconfiguration features with an annotation or the Zipkin starter. ### Spring support Autoconfiguration is natively supported by Spring Boot applications. To enable these features in "vanilla" use `@EnableOpenTelemetry` to complete a component scan of this package. ```java import io.opentelemetry.instrumentation.spring.autoconfigure.EnableOpenTelemetry; import org.springframework.context.annotation.Configuration; @Configuration @EnableOpenTelemetry public class OpenTelemetryConfig {} ``` ### Zipkin starter OpenTelemetry Zipkin Exporter Starter is a starter package that includes the opentelemetry-api, opentelemetry-sdk, opentelemetry-extension-annotations, opentelemetry-logging-exporter, opentelemetry-spring-boot-autoconfigurations and spring framework starters required to setup distributed tracing. It also provides the [opentelemetry-exporters-zipkin](https://github.com/open-telemetry/opentelemetry-java/tree/main/exporters/zipkin) artifact and corresponding exporter autoconfiguration. Check out [opentelemetry-spring-boot-autoconfigure](https://github.com/open-telemetry/opentelemetry-java-instrumentation/blob/main/instrumentation/spring/spring-boot-autoconfigure/README.md#features) for the list of supported libraries and features. 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](https://github.com/open-telemetry/opentelemetry-java-instrumentation/blob/main/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/OpenTelemetryAutoConfiguration.java). {{< tabpane text=true >}} {{% tab header="Maven (`pom.xml`)" lang=Maven %}} ```xml io.opentelemetry opentelemetry-exporter-zipkin {{% param vers.otel %}} ``` {{% /tab %}} {{% tab header="Gradle (`gradle.build`)" lang=Gradle %}} ```kotlin dependencies { implementation("io.opentelemetry:opentelemetry-exporter-zipkin:{{% param vers.otel %}}") } ``` {{% /tab %}} {{< /tabpane>}} #### Configurations | Property | Default Value | ConditionalOnClass | | ------------------------------ | ------------- | -------------------- | | `otel.exporter.zipkin.enabled` | true | `ZipkinSpanExporter` |