Skip to content

Commit d90aa1c

Browse files
committed
gpt 5.1
1 parent b2c175e commit d90aa1c

File tree

1 file changed

+220
-45
lines changed

1 file changed

+220
-45
lines changed
Lines changed: 220 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,70 +1,155 @@
11
# Spring Boot Declarative Configuration Example
22

3-
This example demonstrates how to use [declarative configuration](https://opentelemetry.io/docs/specs/otel/configuration/#declarative-configuration) with the OpenTelemetry Spring Boot Starter (requires version 2.22.0+). Declarative configuration allows you to control tracing and metrics behavior using a YAML file, without code changes.
3+
This example demonstrates how to use [declarative configuration](https://opentelemetry.io/docs/specs/otel/configuration/#declarative-configuration)
4+
with the OpenTelemetry Spring Boot Starter to configure tracing, metrics, and logging for a Spring Boot application.
45

5-
The configuration file is located at [`application.yaml`](./application.yaml).
6+
Instead of using the OpenTelemetry Java Agent and an `otel-agent-config.yaml` file, this module uses the
7+
[OpenTelemetry Spring Boot Starter](https://github.com/open-telemetry/opentelemetry-java-instrumentation/tree/main/instrumentation/spring/spring-boot-autoconfigure)
8+
and configures declarative behavior via standard Spring Boot configuration in `application.yaml`.
9+
10+
> **Requirement:** Declarative configuration via the Spring Boot Starter requires version **2.22.0 or newer** of the
11+
> OpenTelemetry Spring Boot Starter.
12+
13+
The main configuration file for this example is:
14+
15+
- [`src/main/resources/application.yaml`](./src/main/resources/application.yaml)
16+
17+
For the underlying declarative configuration schema and additional examples, see the
18+
[opentelemetry-configuration](https://github.com/open-telemetry/opentelemetry-configuration) repository.
19+
Remember that when you copy examples from that repository into a Spring Boot app, you must nest them under the
20+
`otel:` root node (two-space indentation for all keys shown below).
621

722
This Spring Boot application includes two endpoints:
8-
- `/actuator/health` - A health check endpoint (from Spring Boot Actuator) that is configured to be excluded from tracing
9-
- `/api/example` - A simple API endpoint that will be traced normally
23+
24+
- `/actuator/health` – A health check endpoint (from Spring Boot Actuator) that is configured to be **excluded** from tracing
25+
- `/api/example` – A simple API endpoint that **will be traced** normally
1026

1127
## End-to-End Instructions
1228

1329
### Prerequisites
14-
* Java 17 or higher
15-
* OpenTelemetry Spring Boot Starter version 2.22.0 or newer
16-
17-
Add the starter to your `build.gradle`:
18-
```kotlin
19-
dependencies {
20-
implementation("io.opentelemetry.instrumentation:opentelemetry-spring-boot-starter:2.22.0")
21-
}
22-
```
30+
31+
- Java 17 or higher
32+
- OpenTelemetry Spring Boot Starter **2.22.0+** on the classpath of this application (already configured in this
33+
example’s build files)
2334

2435
### Step 1: Build the Application
2536

37+
From the `spring-declarative-configuration` directory:
38+
2639
```bash
27-
# Build the JAR - Run from the spring-declarative-configuration directory
2840
../gradlew bootJar
2941
```
3042

31-
### Step 2: Run the Application
43+
This builds the Spring Boot fat JAR for the example application.
44+
45+
### Step 2: Run the Spring Boot Application
46+
47+
Run the application as a normal Spring Boot JAR – no `-javaagent` flag and no separate `otel-agent-config.yaml` file
48+
are needed. Declarative configuration is picked up from `application.yaml` by the Spring Boot Starter.
3249

3350
```bash
34-
# From the spring-declarative-configuration directory
3551
java -jar build/libs/spring-declarative-configuration.jar
3652
```
3753

54+
The Spring Boot Starter will automatically:
55+
56+
- Initialize OpenTelemetry SDK
57+
- Read declarative configuration under the `otel:` root in `application.yaml`
58+
- Apply exporters, processors, and sampler rules defined there
59+
3860
### Step 3: Test the Endpoints
3961

40-
Open a new terminal and test both endpoints:
62+
In a separate terminal, call both endpoints:
4163

4264
```bash
43-
# This endpoint will NOT be traced (excluded by configuration)
65+
# This endpoint will NOT be traced (excluded by declarative configuration)
4466
curl http://localhost:8080/actuator/health
4567

4668
# This endpoint WILL be traced normally
4769
curl http://localhost:8080/api/example
4870
```
4971

50-
### Step 4: Verify Tracing Behavior
72+
### Step 4: Verify Tracing, Metrics, and Logs
73+
74+
By default, this example configures:
5175

52-
Check your tracing backend or logs to see:
53-
- Health check requests (`/actuator/health`) should NOT generate traces (excluded by configuration)
54-
- API requests (`/api/example`) should generate traces
76+
- An OTLP HTTP exporter for traces, metrics, and logs
77+
- A console exporter for traces for easy local inspection
5578

56-
## Declarative Configuration
79+
Check the application logs to see that:
5780

58-
Declarative configuration is enabled by setting the `file_format` property in your `application.yaml` under the `otel:` root node. All configuration must be indented under `otel:` for Spring Boot.
81+
- Health check requests (`/actuator/health`) **do not** generate spans (dropped by sampler rules)
82+
- Requests to `/api/example` **do** generate spans and are exported to console and/or OTLP
5983

60-
See [OpenTelemetry Configuration Schema and Examples](https://github.com/open-telemetry/opentelemetry-configuration) for details.
84+
If you have an OTLP-compatible backend (e.g., the OpenTelemetry Collector, Jaeger, Tempo, etc.) listening on
85+
`http://localhost:4318`, you can inspect the exported telemetry there as well.
6186

62-
Example configuration to exclude health checks from tracing:
87+
## Declarative Configuration with Spring Boot
88+
89+
The declarative configuration used by this example lives in [`application.yaml`](./src/main/resources/application.yaml)
90+
under the `otel:` root key.
6391

6492
```yaml
6593
otel:
66-
file_format: declarative
94+
# ... see src/main/resources/application.yaml for the full configuration
95+
```
96+
97+
This layout follows the declarative configuration schema defined in the
98+
[opentelemetry-configuration](https://github.com/open-telemetry/opentelemetry-configuration) repository, but adapted
99+
for Spring Boot:
100+
101+
- All OpenTelemetry configuration keys live under the `otel:` root
102+
- Configuration blocks from the reference repo (such as `tracer_provider`, `meter_provider`, `logger_provider`, etc.)
103+
are indented by **two spaces** beneath `otel:`
104+
- The configuration is loaded via the OpenTelemetry Spring Boot Starter instead of the Java Agent
105+
106+
### Opting In with `file_format`
107+
108+
Declarative configuration is **opt-in**. In this Spring Boot example, you enable declarative configuration by setting
109+
`file_format` under `otel:` in `application.yaml`:
110+
111+
```yaml
112+
otel:
113+
file_format: "1.0-rc.2"
114+
# ... other configuration
115+
```
116+
117+
The `file_format` value follows the versions defined in the
118+
[declarative configuration specification](https://github.com/open-telemetry/opentelemetry-configuration).
119+
If `file_format` is missing, declarative configuration is not applied.
120+
121+
### Example: Exporters and Sampler Rules (Spring Style)
122+
123+
Below is a simplified view of the configuration used in this module. All keys are indented under `otel:` as required by
124+
Spring Boot declarative configuration. Refer to the actual
125+
[`application.yaml`](./src/main/resources/application.yaml) for the complete version.
126+
127+
```yaml
128+
otel:
129+
file_format: "1.0-rc.2"
130+
131+
resource:
132+
attributes:
133+
- name: service.name
134+
value: spring-boot-declarative-config-example
135+
136+
propagator:
137+
composite:
138+
- tracecontext:
139+
- baggage:
140+
67141
tracer_provider:
142+
processors:
143+
- batch:
144+
exporter:
145+
otlp_http:
146+
# Note: Spring uses : instead of :- as separator for the default value
147+
endpoint: ${OTEL_EXPORTER_OTLP_ENDPOINT:http://localhost:4318}/v1/traces
148+
149+
- batch:
150+
exporter:
151+
console:
152+
68153
sampler:
69154
rule_based_routing:
70155
fallback_sampler:
@@ -74,28 +159,118 @@ otel:
74159
- action: DROP
75160
attribute: url.path
76161
pattern: /actuator.*
162+
163+
meter_provider:
164+
readers:
165+
- periodic:
166+
exporter:
167+
otlp_http:
168+
endpoint: ${OTEL_EXPORTER_OTLP_ENDPOINT:http://localhost:4318}/v1/metrics
169+
170+
logger_provider:
171+
processors:
172+
- batch:
173+
exporter:
174+
otlp_http:
175+
endpoint: ${OTEL_EXPORTER_OTLP_ENDPOINT:http://localhost:4318}/v1/logs
77176
```
78177
79-
**Important Notes:**
80-
- Spring Boot uses `:` as the separator for default values in property expressions, e.g. `${OTEL_EXPORTER_OTLP_ENDPOINT:http://localhost:4318}/v1/traces` (not `:-`).
81-
- The auto-suggested properties in IDEs may be incorrect, as they are based on the non-declarative config schema.
82-
- The `file_format` property is required to opt-in to declarative configuration.
83-
- Refer to the [`application.yaml`](./application.yaml) configuration file in this module for the complete list of available properties and their descriptions.
178+
This configuration is conceptually equivalent to the Java Agent example’s `rule_based_routing` sampler (from
179+
`javaagent-declarative-configuration/otel-agent-config.yaml`):
180+
181+
- It uses the `rule_based_routing` sampler contribution
182+
- It restricts evaluation to `SERVER` spans
183+
- It drops (`DROP`) spans whose `url.path` matches `/actuator.*` (e.g., `/actuator/health`)
184+
- All other server requests are sampled by the `always_on` fallback sampler
185+
186+
## Spring Boot Starter–Specific Notes
187+
188+
### Spring Boot Starter Version
189+
190+
- Declarative configuration is supported by the OpenTelemetry Spring Boot Starter starting with version **2.22.0**
191+
- Ensure your dependencies use at least this version; otherwise, `file_format` and other declarative config features
192+
may be ignored
193+
194+
### Property Metadata and IDE Auto-Completion
84195

85-
## Programmatic Configuration Example
196+
Most IDEs derive auto-completion for Spring properties from Spring Boot configuration metadata. At the time of this
197+
example, that metadata is primarily based on the **non-declarative** configuration schema.
86198

87-
If you need to filter out health checks programmatically (instead of declarative config), see [`OpenTelemetryConfig.java`](../spring-native/src/main/java/io/opentelemetry/example/graal/OpenTelemetryConfig.java) in the `spring-native` module. The `configureSampler` method demonstrates how to drop actuator endpoints from tracing using the RuleBasedRoutingSampler:
199+
As a result:
88200

89-
```java
90-
// ...existing code...
91-
private RuleBasedRoutingSampler configureSampler(Sampler fallback, ConfigProperties config) {
92-
return RuleBasedRoutingSampler.builder(SpanKind.SERVER, fallback)
93-
.drop(UrlAttributes.URL_PATH, "^/actuator")
94-
.build();
95-
}
96-
// ...existing code...
201+
- Auto-suggested properties in IDEs may be incomplete or incorrect for declarative configuration under `otel:`
202+
- Some declarative configuration keys may not appear in auto-completion at all
203+
204+
When in doubt:
205+
206+
- Prefer the official schema and examples in
207+
[opentelemetry-configuration](https://github.com/open-telemetry/opentelemetry-configuration)
208+
- Then adapt those examples by nesting them under the `otel:` root in your `application.yaml`
209+
210+
### Placeholder Default Values: `:` vs `:-`
211+
212+
Spring Boot’s property placeholder syntax differs slightly from generic examples you might see in OpenTelemetry docs.
213+
214+
- Generic examples sometimes use `${VAR_NAME:-default}` for default values
215+
- **Spring Boot uses `:` instead of `:-`**
216+
217+
For example, in this module we configure the OTLP HTTP trace endpoint as:
218+
219+
```yaml
220+
otel:
221+
tracer_provider:
222+
processors:
223+
- batch:
224+
exporter:
225+
otlp_http:
226+
endpoint: ${OTEL_EXPORTER_OTLP_ENDPOINT:http://localhost:4318}/v1/traces
97227
```
98228

99-
## Further Reading
100-
- [OpenTelemetry Declarative Configuration Schema](https://github.com/open-telemetry/opentelemetry-configuration)
101-
- [Spring Boot Starter Documentation](https://github.com/open-telemetry/opentelemetry-java-instrumentation/tree/main/instrumentation/spring/spring-boot-autoconfigure)
229+
Here, `http://localhost:4318` is used as the default if `OTEL_EXPORTER_OTLP_ENDPOINT` is not set.
230+
231+
When copying configuration from non-Spring examples, always convert `:-` to `:` in placeholders.
232+
233+
## Declarative vs Programmatic Configuration
234+
235+
Declarative configuration, as used in this example, allows you to express routing and sampling rules entirely in
236+
configuration files. This is ideal for:
237+
238+
- Operational teams that need to adjust sampling or filtering without changing code
239+
- Environments where configuration is managed externally (Kubernetes ConfigMaps, Spring Cloud Config, etc.)
240+
241+
For more advanced or dynamic scenarios, you can still use **programmatic** configuration. The `spring-native` module in
242+
this repository contains an example of this:
243+
244+
- See `configureSampler` in
245+
[`OpenTelemetryConfig`](../spring-native/src/main/java/io/opentelemetry/example/graal/OpenTelemetryConfig.java)
246+
- It uses `RuleBasedRoutingSampler` programmatically to drop spans for actuator endpoints (`/actuator*`), replicating
247+
the behavior we achieve declaratively via YAML in this module
248+
249+
In many cases, you can start with declarative configuration (as in this module) and only fall back to programmatic
250+
customization for highly dynamic or application-specific logic.
251+
252+
## Troubleshooting and Tips
253+
254+
If the behavior is not what you expect, here are a few things to check:
255+
256+
- **Health checks are still traced**
257+
- Verify the `rules` section under `otel.tracer_provider.sampler.rule_based_routing` in `application.yaml`
258+
- Ensure the `pattern` matches your actual actuator paths (e.g., `/actuator.*`)
259+
- Confirm that `span_kind` is set to `SERVER` (or another correct span kind for your traffic)
260+
261+
- **No spans are exported**
262+
- Confirm that `otel.file_format` is set correctly (for example, `"1.0-rc.2"`)
263+
- Check that at least one exporter is configured (e.g., `otlp_http` or `console`)
264+
- Look for startup warnings or errors related to OpenTelemetry configuration
265+
266+
- **Properties seem to be ignored**
267+
- Make sure you are modifying the correct `application.yaml` for the active Spring profile
268+
- Verify that all configuration keys are indented correctly under the `otel:` root
269+
- Double-check that any placeholders use `:` for defaults (e.g., `${OTEL_EXPORTER_OTLP_ENDPOINT:http://localhost:4318}`)
270+
271+
If issues persist, compare your configuration to:
272+
273+
- This module’s [`application.yaml`](./src/main/resources/application.yaml)
274+
- The Java Agent example in [`javaagent-declarative-configuration`](../javaagent-declarative-configuration)
275+
- The reference schemas and examples in
276+
[opentelemetry-configuration](https://github.com/open-telemetry/opentelemetry-configuration)

0 commit comments

Comments
 (0)