Skip to content

Commit eb4be57

Browse files
authored
Minimal extension example (#886)
1 parent 546655e commit eb4be57

File tree

13 files changed

+298
-1
lines changed

13 files changed

+298
-1
lines changed

.github/scripts/run-oats-tests.sh

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ pushd javaagent-declarative-configuration
1010
../gradlew bootJar
1111
popd
1212

13+
./gradlew :doc-snippets:extensions-testapp:jar :doc-snippets:extensions-minimal:shadowJar
14+
1315
# renovate: datasource=github-releases depName=k3d-io/k3d
1416
K3D_VERSION=v5.8.3
1517
wget -q -O - https://raw.githubusercontent.com/k3d-io/k3d/${K3D_VERSION}/install.sh | TAG=${K3D_VERSION} bash
@@ -19,3 +21,4 @@ OATS_VERSION=v0.4.1
1921
go install github.com/grafana/oats@${OATS_VERSION}
2022
oats -timeout 5m logging-k8s-stdout-otlp-json/
2123
oats -timeout 5m javaagent-declarative-configuration/oats/
24+
oats -timeout 5m doc-snippets/extensions-minimal/oats/

.github/workflows/oats-tests.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ on:
77
paths:
88
- .github/workflows/oats-tests.yml
99
- 'logging-k8s-stdout-otlp-json/**'
10-
- 'javaagent-declarative-configuration/oats/**'
10+
- 'javaagent-declarative-configuration/**'
11+
- 'doc-snippets/extensions-minimal/**'
1112
workflow_dispatch:
1213

1314
permissions:
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# Extensions - Minimal example
2+
3+
This code is used on the documentation site to demonstrate a "quick start" minimal example that someone can use
4+
as a starting point when writing a new extension. The functionality is that it configures a SpanProcessor to add
5+
a custom attribute "custom.processor:active" to the spans.
6+
7+
**NOTE:** This code is used for populating code examples on opentelemetry.io, so please ensure that any changes
8+
maintain the clarity and simplicity of the example and are synced correctly with the documentation site.
9+
10+
## Building
11+
12+
To build the extension JAR:
13+
14+
```bash
15+
cd /path/to/opentelemetry-java-examples
16+
./gradlew :doc-snippets:extensions-minimal:shadowJar
17+
```
18+
19+
The output JAR will be at: `build/libs/extensions-minimal-0.1.0-SNAPSHOT-all.jar`
20+
21+
## Testing
22+
23+
This module includes OATS (OpenTelemetry Acceptance Tests) to verify the extension works correctly.
24+
25+
### Prerequisites
26+
27+
Install OATS:
28+
```bash
29+
go install github.com/grafana/oats@latest
30+
```
31+
32+
Build both the extension and the test application:
33+
```bash
34+
cd /path/to/opentelemetry-java-examples
35+
./gradlew :doc-snippets:extensions-testapp:jar :doc-snippets:extensions-minimal:shadowJar
36+
```
37+
38+
### Run the tests
39+
40+
```bash
41+
cd doc-snippets/extensions-minimal
42+
oats oats/oats.yaml
43+
```
44+
45+
The test will verify that the custom `custom.processor: "active"` attribute is added to all spans.
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
plugins {
2+
id("java")
3+
id("com.gradleup.shadow")
4+
}
5+
6+
dependencies {
7+
// Use BOM to manage OpenTelemetry dependency versions
8+
compileOnly(platform("io.opentelemetry:opentelemetry-bom:1.56.0"))
9+
10+
// OpenTelemetry SDK autoconfiguration SPI (provided by agent)
11+
compileOnly("io.opentelemetry:opentelemetry-sdk-extension-autoconfigure-spi")
12+
13+
// OpenTelemetry SDK (needed for SpanProcessor and trace classes)
14+
compileOnly("io.opentelemetry:opentelemetry-sdk")
15+
16+
// Annotation processor for automatic SPI registration
17+
compileOnly("com.google.auto.service:auto-service:1.1.1")
18+
annotationProcessor("com.google.auto.service:auto-service:1.1.1")
19+
20+
// Add any external dependencies with 'implementation' scope
21+
// implementation("org.apache.commons:commons-lang3:3.19.0")
22+
}
23+
24+
tasks.assemble {
25+
dependsOn(tasks.shadowJar)
26+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
FROM eclipse-temurin:21.0.9_10-jre@sha256:bbcd43c7120c41cc5c9fc844b4403e6865a6f911fec1624ff5dda6f9118cc115
2+
3+
WORKDIR /usr/src/app/
4+
5+
# renovate: datasource=github-releases depName=opentelemetry-java-instrumentation packageName=open-telemetry/opentelemetry-java-instrumentation
6+
ENV OPENTELEMETRY_JAVA_INSTRUMENTATION_VERSION=v2.21.0
7+
8+
# Add the test application JAR
9+
ADD ./extensions-testapp/build/libs/extensions-testapp-1.0-SNAPSHOT.jar ./app.jar
10+
11+
# Add the custom extension JAR
12+
ADD ./extensions-minimal/build/libs/extensions-minimal-0.1.0-SNAPSHOT-all.jar ./extensions/
13+
14+
# Download the OpenTelemetry Java agent
15+
ADD --chmod=644 https://github.com/open-telemetry/opentelemetry-java-instrumentation/releases/download/$OPENTELEMETRY_JAVA_INSTRUMENTATION_VERSION/opentelemetry-javaagent.jar ./opentelemetry-javaagent.jar
16+
17+
# Configure the Java agent with the custom extension
18+
ENV JAVA_TOOL_OPTIONS=-javaagent:./opentelemetry-javaagent.jar
19+
ENV OTEL_JAVAAGENT_EXTENSIONS=./extensions/extensions-minimal-0.1.0-SNAPSHOT-all.jar
20+
21+
EXPOSE 8080
22+
ENTRYPOINT [ "java", "-jar", "./app.jar" ]
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
version: '3'
2+
services:
3+
app:
4+
build:
5+
context: ../../
6+
dockerfile: extensions-minimal/oats/Dockerfile
7+
environment:
8+
OTEL_SERVICE_NAME: "extensions-minimal-test-app"
9+
OTEL_EXPORTER_OTLP_ENDPOINT: http://lgtm:4318
10+
OTEL_EXPORTER_OTLP_TRACES_ENDPOINT: http://lgtm:4318/v1/traces
11+
OTEL_EXPORTER_OTLP_PROTOCOL: http/protobuf
12+
ports:
13+
- "8080:8080"
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# OATS is an acceptance testing framework for OpenTelemetry - https://github.com/grafana/oats
2+
3+
docker-compose:
4+
files:
5+
- ./docker-compose.yml
6+
app-service: app
7+
app-docker-tag: extensions-minimal:latest
8+
app-docker-port: 8080
9+
10+
input:
11+
- path: /hello
12+
interval: 5000ms
13+
14+
expected:
15+
traces:
16+
- traceql: '{ span.http.route = "/hello" }'
17+
spans:
18+
- name: "GET /hello"
19+
attributes:
20+
http.request.method: "GET"
21+
http.route: "/hello"
22+
# This custom attribute is added by MySpanProcessor
23+
custom.processor: "active"
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package otel;
2+
3+
import com.google.auto.service.AutoService;
4+
import io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizer;
5+
import io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizerProvider;
6+
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
7+
import io.opentelemetry.sdk.trace.SdkTracerProviderBuilder;
8+
import io.opentelemetry.sdk.trace.SpanLimits;
9+
10+
@AutoService(AutoConfigurationCustomizerProvider.class)
11+
public class MyExtensionProvider implements AutoConfigurationCustomizerProvider {
12+
13+
@Override
14+
public void customize(AutoConfigurationCustomizer config) {
15+
config.addTracerProviderCustomizer(this::configureTracer);
16+
}
17+
18+
private SdkTracerProviderBuilder configureTracer(
19+
SdkTracerProviderBuilder tracerProvider, ConfigProperties config) {
20+
return tracerProvider
21+
.setSpanLimits(SpanLimits.builder().setMaxNumberOfAttributes(1024).build())
22+
.addSpanProcessor(new MySpanProcessor());
23+
}
24+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package otel;
2+
3+
import io.opentelemetry.context.Context;
4+
import io.opentelemetry.sdk.common.CompletableResultCode;
5+
import io.opentelemetry.sdk.trace.ReadWriteSpan;
6+
import io.opentelemetry.sdk.trace.ReadableSpan;
7+
import io.opentelemetry.sdk.trace.SpanProcessor;
8+
9+
public class MySpanProcessor implements SpanProcessor {
10+
11+
@Override
12+
public void onStart(Context parentContext, ReadWriteSpan span) {
13+
// Add custom attributes when span starts
14+
span.setAttribute("custom.processor", "active");
15+
}
16+
17+
@Override
18+
public boolean isStartRequired() {
19+
return true;
20+
}
21+
22+
@Override
23+
public void onEnd(ReadableSpan span) {
24+
// Process span when it ends (optional)
25+
}
26+
27+
@Override
28+
public boolean isEndRequired() {
29+
return false;
30+
}
31+
32+
@Override
33+
public CompletableResultCode shutdown() {
34+
return CompletableResultCode.ofSuccess();
35+
}
36+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# Extensions - Test Application
2+
3+
This is a simple HTTP server application used for testing OpenTelemetry Java agent extensions. It provides one endpoint:
4+
5+
- `GET /hello` - Returns a simple greeting
6+
7+
## Building
8+
9+
To build the application JAR:
10+
11+
```bash
12+
cd /path/to/opentelemetry-java-examples
13+
./gradlew :doc-snippets:extensions-testapp:jar
14+
```
15+
16+
The output JAR will be at: `build/libs/extensions-testapp-1.0-SNAPSHOT.jar`
17+
18+
## Running
19+
20+
To run the application with the OpenTelemetry Java agent:
21+
22+
```bash
23+
java -javaagent:path/to/opentelemetry-javaagent.jar \
24+
-Dotel.service.name=test-app \
25+
-jar build/libs/extensions-testapp-1.0-SNAPSHOT.jar
26+
```
27+
28+
The server will start on port 8080. You can test it with:
29+
30+
```bash
31+
curl http://localhost:8080/hello
32+
```
33+
34+
## Usage with Extensions
35+
36+
This application is designed to be used with the extensions-minimal module to test custom OpenTelemetry extensions.
37+
See the extensions-minimal readme for details on running OATS tests.

0 commit comments

Comments
 (0)