-
Notifications
You must be signed in to change notification settings - Fork 199
opentelemetry-http: Add documentation #3340
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
bryce-anderson
merged 15 commits into
apple:main
from
bryce-anderson:bl_anderson/otel-docs
Oct 3, 2025
Merged
Changes from all commits
Commits
Show all changes
15 commits
Select commit
Hold shift + click to select a range
77e8e7c
phase 1 - adding doc site
bryce-anderson 89b1fd7
Phase 2: add an example
bryce-anderson 324fbe2
Finish polishing structure
bryce-anderson 276be5b
Add some other filters in the examples
bryce-anderson 0822a76
One omission
bryce-anderson 3777ab8
Why is lockfile not happy?
bryce-anderson 1747523
Merge remote-tracking branch 'origin/main' into bl_anderson/otel-docs
bryce-anderson e21ef88
Fix lockfile
bryce-anderson dcbe51d
Revert debug changes to check-lockfile
bryce-anderson 7c3abec
Apply Idel suggestions from code review
bryce-anderson d683853
More Idel feedback
bryce-anderson ee6efcb
Merge remote-tracking branch 'origin/main' into bl_anderson/otel-docs
bryce-anderson 657d6f9
Update lockfile
bryce-anderson 9d8586c
Remove dead comment line
bryce-anderson 9e94b73
Note that adding the filter at connection level is optional
bryce-anderson File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
38 changes: 38 additions & 0 deletions
38
servicetalk-examples/http/opentelemetry-tracing/build.gradle
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
/* | ||
* Copyright © 2025 Apple Inc. and the ServiceTalk project authors | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
apply plugin: "java" | ||
apply from: "../../gradle/idea.gradle" | ||
|
||
dependencies { | ||
implementation platform("io.opentelemetry:opentelemetry-bom:$opentelemetryVersion") | ||
|
||
implementation project(":servicetalk-annotations") | ||
implementation project(":servicetalk-http-netty") | ||
implementation project(":servicetalk-http-utils") // For HttpRequestAutoDrainingServiceFilter | ||
implementation project(":servicetalk-opentelemetry-http") // OpenTelemetry client/server filters | ||
|
||
runtimeOnly project(":servicetalk-opentelemetry-asynccontext") // OpenTelemetry async context propagation | ||
|
||
// OpenTelemetry Java SDK | ||
implementation "io.opentelemetry:opentelemetry-api" | ||
implementation "io.opentelemetry:opentelemetry-sdk" | ||
implementation "io.opentelemetry:opentelemetry-exporter-logging" | ||
implementation "io.opentelemetry:opentelemetry-exporter-otlp" | ||
|
||
implementation "org.slf4j:slf4j-api:$slf4jVersion" | ||
runtimeOnly "org.apache.logging.log4j:log4j-slf4j-impl:$log4jVersion" | ||
} |
56 changes: 56 additions & 0 deletions
56
servicetalk-examples/http/opentelemetry-tracing/gradle.lockfile
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
# This is a Gradle generated file for dependency locking. | ||
# Manual edits can break the build and are not advised. | ||
# This file is expected to be part of source control. | ||
com.google.code.findbugs:jsr305:3.0.2=compileClasspath,runtimeClasspath | ||
com.squareup.okhttp3:okhttp:4.12.0=runtimeClasspath | ||
com.squareup.okio:okio-jvm:3.6.0=runtimeClasspath | ||
com.squareup.okio:okio:3.6.0=runtimeClasspath | ||
io.netty:netty-bom:4.1.127.Final=runtimeClasspath | ||
io.netty:netty-buffer:4.1.127.Final=runtimeClasspath | ||
io.netty:netty-codec-dns:4.1.127.Final=runtimeClasspath | ||
io.netty:netty-codec-http2:4.1.127.Final=runtimeClasspath | ||
io.netty:netty-codec-http:4.1.127.Final=runtimeClasspath | ||
io.netty:netty-codec:4.1.127.Final=runtimeClasspath | ||
io.netty:netty-common:4.1.127.Final=runtimeClasspath | ||
io.netty:netty-handler:4.1.127.Final=runtimeClasspath | ||
io.netty:netty-resolver-dns-classes-macos:4.1.127.Final=runtimeClasspath | ||
io.netty:netty-resolver-dns-native-macos:4.1.127.Final=runtimeClasspath | ||
io.netty:netty-resolver-dns:4.1.127.Final=runtimeClasspath | ||
io.netty:netty-resolver:4.1.127.Final=runtimeClasspath | ||
io.netty:netty-tcnative-boringssl-static:2.0.73.Final=runtimeClasspath | ||
io.netty:netty-tcnative-classes:2.0.73.Final=runtimeClasspath | ||
io.netty:netty-transport-classes-epoll:4.1.127.Final=runtimeClasspath | ||
io.netty:netty-transport-classes-kqueue:4.1.127.Final=runtimeClasspath | ||
io.netty:netty-transport-native-epoll:4.1.127.Final=runtimeClasspath | ||
io.netty:netty-transport-native-kqueue:4.1.127.Final=runtimeClasspath | ||
io.netty:netty-transport-native-unix-common:4.1.127.Final=runtimeClasspath | ||
io.netty:netty-transport:4.1.127.Final=runtimeClasspath | ||
io.opentelemetry.instrumentation:opentelemetry-instrumentation-api:2.14.0=runtimeClasspath | ||
io.opentelemetry.instrumentation:opentelemetry-instrumentation-bom:2.14.0=runtimeClasspath | ||
io.opentelemetry.semconv:opentelemetry-semconv:1.30.0=runtimeClasspath | ||
io.opentelemetry:opentelemetry-api-incubator:1.48.0-alpha=runtimeClasspath | ||
io.opentelemetry:opentelemetry-api:1.48.0=compileClasspath,runtimeClasspath | ||
io.opentelemetry:opentelemetry-bom:1.48.0=compileClasspath,runtimeClasspath | ||
io.opentelemetry:opentelemetry-context:1.48.0=compileClasspath,runtimeClasspath | ||
io.opentelemetry:opentelemetry-exporter-common:1.48.0=runtimeClasspath | ||
io.opentelemetry:opentelemetry-exporter-logging:1.48.0=compileClasspath,runtimeClasspath | ||
io.opentelemetry:opentelemetry-exporter-otlp-common:1.48.0=runtimeClasspath | ||
io.opentelemetry:opentelemetry-exporter-otlp:1.48.0=compileClasspath,runtimeClasspath | ||
io.opentelemetry:opentelemetry-exporter-sender-okhttp:1.48.0=runtimeClasspath | ||
io.opentelemetry:opentelemetry-sdk-common:1.48.0=compileClasspath,runtimeClasspath | ||
io.opentelemetry:opentelemetry-sdk-extension-autoconfigure-spi:1.48.0=runtimeClasspath | ||
io.opentelemetry:opentelemetry-sdk-logs:1.48.0=compileClasspath,runtimeClasspath | ||
io.opentelemetry:opentelemetry-sdk-metrics:1.48.0=compileClasspath,runtimeClasspath | ||
io.opentelemetry:opentelemetry-sdk-trace:1.48.0=compileClasspath,runtimeClasspath | ||
io.opentelemetry:opentelemetry-sdk:1.48.0=compileClasspath,runtimeClasspath | ||
org.apache.logging.log4j:log4j-api:2.23.1=runtimeClasspath | ||
org.apache.logging.log4j:log4j-core:2.23.1=runtimeClasspath | ||
org.apache.logging.log4j:log4j-slf4j-impl:2.23.1=runtimeClasspath | ||
org.jctools:jctools-core:4.0.5=runtimeClasspath | ||
org.jetbrains.kotlin:kotlin-stdlib-common:1.9.10=runtimeClasspath | ||
org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.9.10=runtimeClasspath | ||
org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.9.10=runtimeClasspath | ||
org.jetbrains.kotlin:kotlin-stdlib:1.9.10=runtimeClasspath | ||
org.jetbrains:annotations:13.0=runtimeClasspath | ||
org.slf4j:slf4j-api:1.7.36=compileClasspath,runtimeClasspath | ||
empty=annotationProcessor,jmhCompileClasspath,jmhRuntimeClasspath |
82 changes: 82 additions & 0 deletions
82
...n/java/io/servicetalk/examples/http/opentelemetry/tracing/OpenTelemetryTracingClient.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
/* | ||
* Copyright © 2025 Apple Inc. and the ServiceTalk project authors | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
package io.servicetalk.examples.http.opentelemetry.tracing; | ||
|
||
import io.servicetalk.http.api.BlockingHttpClient; | ||
import io.servicetalk.http.api.HttpResponse; | ||
import io.servicetalk.http.netty.HttpClients; | ||
import io.servicetalk.opentelemetry.http.OpenTelemetryHttpRequesterFilter; | ||
|
||
import java.nio.charset.StandardCharsets; | ||
import io.opentelemetry.api.GlobalOpenTelemetry; | ||
import io.opentelemetry.api.OpenTelemetry; | ||
import io.opentelemetry.exporter.logging.LoggingSpanExporter; | ||
import io.opentelemetry.sdk.OpenTelemetrySdk; | ||
import io.opentelemetry.sdk.trace.SdkTracerProvider; | ||
import io.opentelemetry.sdk.trace.export.BatchSpanProcessor; | ||
|
||
/** | ||
* A client that demonstrates OpenTelemetry distributed tracing with ServiceTalk. | ||
* This example shows how to: | ||
* <ul> | ||
* <li>Configure OpenTelemetry SDK with logging exporter</li> | ||
* <li>Set up ServiceTalk HTTP client with OpenTelemetry tracing filter</li> | ||
* <li>Demonstrate proper client-side filter ordering</li> | ||
* <li>Automatically capture HTTP request/response spans</li> | ||
* <li>Propagate trace context to downstream services</li> | ||
* </ul> | ||
*/ | ||
public final class OpenTelemetryTracingClient { | ||
public static void main(String[] args) throws Exception { | ||
// Configure OpenTelemetry SDK | ||
final String serviceName = "servicetalk-example-client"; | ||
|
||
final OpenTelemetry openTelemetry = OpenTelemetrySdk.builder() | ||
.setTracerProvider(SdkTracerProvider.builder() | ||
.addSpanProcessor(BatchSpanProcessor.builder(LoggingSpanExporter.create()).build()) | ||
.build()) | ||
.build(); | ||
|
||
// Set the global OpenTelemetry instance | ||
GlobalOpenTelemetry.set(openTelemetry); | ||
|
||
OpenTelemetryHttpRequesterFilter filter = new OpenTelemetryHttpRequesterFilter.Builder() | ||
.componentName(serviceName) | ||
.build(); | ||
|
||
try (BlockingHttpClient client = HttpClients.forSingleAddress("localhost", 8080) | ||
// IMPORTANT: OpenTelemetry filter should be placed EARLY in the filter chain | ||
// This ensures proper span creation and context propagation for downstream filters | ||
.appendClientFilter(filter) | ||
// Optional: adding the filter a second time as a connection filter will enable 'physical spans' | ||
// where there will be a higher level 'logical' span and a sub-physical span for each | ||
// request sent over the wire. | ||
.appendConnectionFilter(filter) | ||
.buildBlocking()) { | ||
bryce-anderson marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
System.out.println("Making first request..."); | ||
HttpResponse response1 = client.request(client.get("/hello")); | ||
System.out.println("Response 1: " + response1.toString((name, value) -> value)); | ||
System.out.println("Body 1: " + response1.payloadBody().toString(StandardCharsets.UTF_8)); | ||
|
||
System.out.println("\nMaking second request..."); | ||
HttpResponse response2 = client.request(client.get("/world")); | ||
System.out.println("Response 2: " + response2.toString((name, value) -> value)); | ||
System.out.println("Body 2: " + response2.payloadBody().toString(StandardCharsets.UTF_8)); | ||
|
||
} | ||
} | ||
} |
86 changes: 86 additions & 0 deletions
86
...n/java/io/servicetalk/examples/http/opentelemetry/tracing/OpenTelemetryTracingServer.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
/* | ||
* Copyright © 2025 Apple Inc. and the ServiceTalk project authors | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
package io.servicetalk.examples.http.opentelemetry.tracing; | ||
|
||
import io.servicetalk.http.api.HttpExceptionMapperServiceFilter; | ||
import io.servicetalk.http.netty.HttpServers; | ||
import io.servicetalk.http.utils.HttpRequestAutoDrainingServiceFilter; | ||
import io.servicetalk.opentelemetry.http.OpenTelemetryHttpServiceFilter; | ||
|
||
import io.opentelemetry.api.GlobalOpenTelemetry; | ||
import io.opentelemetry.api.OpenTelemetry; | ||
import io.opentelemetry.exporter.logging.LoggingSpanExporter; | ||
import io.opentelemetry.sdk.OpenTelemetrySdk; | ||
import io.opentelemetry.sdk.trace.SdkTracerProvider; | ||
import io.opentelemetry.sdk.trace.export.BatchSpanProcessor; | ||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
|
||
/** | ||
* A server that demonstrates OpenTelemetry distributed tracing with ServiceTalk. | ||
* This example shows how to: | ||
* <ul> | ||
* <li>Configure OpenTelemetry SDK with logging exporter</li> | ||
* <li>Set up ServiceTalk HTTP server with OpenTelemetry tracing filter</li> | ||
* <li>Demonstrate proper filter ordering for accurate tracing</li> | ||
* <li>Automatically capture HTTP request/response spans</li> | ||
* </ul> | ||
*/ | ||
public final class OpenTelemetryTracingServer { | ||
private static final Logger LOGGER = LoggerFactory.getLogger(OpenTelemetryTracingServer.class); | ||
|
||
public static void main(String[] args) throws Exception { | ||
// Configure OpenTelemetry SDK | ||
final OpenTelemetry openTelemetry = OpenTelemetrySdk.builder() | ||
.setTracerProvider(SdkTracerProvider.builder() | ||
.addSpanProcessor(BatchSpanProcessor.builder(LoggingSpanExporter.create()).build()) | ||
.build()) | ||
.build(); | ||
|
||
// Set the global OpenTelemetry instance | ||
GlobalOpenTelemetry.set(openTelemetry); | ||
|
||
HttpServers.forPort(8080) | ||
// CRITICAL: OpenTelemetry filter MUST be first for proper context propagation | ||
// Use non-offloading filter to maintain async context across threads | ||
.appendNonOffloadingServiceFilter(new OpenTelemetryHttpServiceFilter.Builder() | ||
.build()) | ||
|
||
// IMPORTANT: Request draining MUST come after OpenTelemetry filter | ||
// This ensures tracing information is captured for auto-drained requests (e.g., GET requests) | ||
// If auto-draining occurs before OpenTelemetry filter processes the request, | ||
// tracing information may be incomplete or incorrect. | ||
.appendNonOffloadingServiceFilter(HttpRequestAutoDrainingServiceFilter.INSTANCE) | ||
// Similarly, exception mapping should also come after the OTEL filter so that the OTEL span properly | ||
// reflects what was sent back to the client. | ||
.appendNonOffloadingServiceFilter(HttpExceptionMapperServiceFilter.INSTANCE) | ||
|
||
|
||
// Other filters can be added after the critical ordering above | ||
// Exception mapping, logging, etc. should come after OpenTelemetry and request draining | ||
.listenBlockingAndAwait((ctx, request, responseFactory) -> { | ||
LOGGER.info("Processing request: {} {}", request.method(), request.requestTarget()); | ||
|
||
// Simulate some processing work | ||
Thread.sleep(50); | ||
|
||
return responseFactory.ok() | ||
.addHeader("content-type", "text/plain") | ||
.payloadBody(ctx.executionContext().bufferAllocator() | ||
.fromAscii("Hello from OpenTelemetry server!")); | ||
}).awaitShutdown(); | ||
} | ||
} |
22 changes: 22 additions & 0 deletions
22
...racing/src/main/java/io/servicetalk/examples/http/opentelemetry/tracing/package-info.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
/* | ||
* Copyright © 2025 Apple Inc. and the ServiceTalk project authors | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
/** | ||
* OpenTelemetry examples showing distributed tracing with ServiceTalk. | ||
*/ | ||
@ElementsAreNonnullByDefault | ||
package io.servicetalk.examples.http.opentelemetry.tracing; | ||
|
||
import io.servicetalk.annotations.ElementsAreNonnullByDefault; |
29 changes: 29 additions & 0 deletions
29
servicetalk-examples/http/opentelemetry-tracing/src/main/resources/log4j2.xml
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<!-- | ||
~ Copyright © 2025 Apple Inc. and the ServiceTalk project authors | ||
~ | ||
~ Licensed under the Apache License, Version 2.0 (the "License"); | ||
~ you may not use this file except in compliance with the License. | ||
~ You may obtain a copy of the License at | ||
~ | ||
~ http://www.apache.org/licenses/LICENSE-2.0 | ||
~ | ||
~ Unless required by applicable law or agreed to in writing, software | ||
~ distributed under the License is distributed on an "AS IS" BASIS, | ||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
~ See the License for the specific language governing permissions and | ||
~ limitations under the License. | ||
--> | ||
<Configuration status="info"> | ||
<Appenders> | ||
<Console name="Console" target="SYSTEM_OUT"> | ||
<PatternLayout pattern="%d %30t [%-5level] %-15logger{1} - %msg%n"/> | ||
</Console> | ||
</Appenders> | ||
<Loggers> | ||
<!-- Use `-Dservicetalk.logger.level=DEBUG` to change the root logger level via command line --> | ||
<Root level="${sys:servicetalk.logger.level:-INFO}"> | ||
<AppenderRef ref="Console"/> | ||
</Root> | ||
</Loggers> | ||
</Configuration> |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.