Spitfirev0.71.0 · What's new

Version: 0.71.0This documentation is for Spitfire 0.71.0.

Connecting a Java service with OTel

The OpenTelemetry Java agent (-javaagent) collects traces, metrics and logs without touching the code. Values and general rules: Connecting services with OTel: overview.

Version table

Java Agent Note
8, 11, 17, 21, 25 and later opentelemetry-javaagent.jar 2.33.1 Every band uses the same agent
7 and earlier not supported Upgrade to Java 8+ or take server metrics only: Collector

Find your version: java -version.

Verified: 2026-11-02. Source: supported JVMs (OpenJDK and OpenJ9: 8, 11, 17, 21, 25, 27), release 2.33.1.

What you need

  • Spitfire address https://<spitfire> and OTLP receiver token sfotlp_…
  • Tower address http://<tower>:4318 and Collector token sfcol_…
  • Protocol http/protobuf
  • Service name <service-name>, version <service-version>, environment <environment>
  • With a private CA, the CA file /etc/spitfire-otel/ca.pem (Windows: C:\spitfire-otel\ca.pem)
  • With a proxy, the Tower and Spitfire in NO_PROXY
  • Sampling parentbased_traceidratio, 0.1

Linux (systemd)

  1. Download the agent:
bash
sudo mkdir -p /opt/spitfire-otel /etc/spitfire-otel
sudo curl -sSfL -o /opt/spitfire-otel/opentelemetry-javaagent.jar \
  https://github.com/open-telemetry/opentelemetry-java-instrumentation/releases/download/v2.33.1/opentelemetry-javaagent.jar
sudo chmod 644 /opt/spitfire-otel/opentelemetry-javaagent.jar
  1. Create the file /etc/spitfire-otel/<service-name>.env and paste this:
bash
IS_OTEL_ENABLED=true
OTEL_SERVICE_NAME=<service-name>
OTEL_RESOURCE_ATTRIBUTES=service.version=<service-version>,deployment.environment=<environment>
OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf
OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=https://<spitfire>/otlp/v1/traces
OTEL_EXPORTER_OTLP_TRACES_HEADERS=authorization=sfotlp_…
OTEL_EXPORTER_OTLP_LOGS_ENDPOINT=https://<spitfire>/otlp/v1/logs
OTEL_EXPORTER_OTLP_LOGS_HEADERS=authorization=sfotlp_…
OTEL_EXPORTER_OTLP_METRICS_ENDPOINT=http://<tower>:4318/v1/metrics
OTEL_EXPORTER_OTLP_METRICS_HEADERS=authorization=sfcol_…
OTEL_TRACES_EXPORTER=otlp
OTEL_METRICS_EXPORTER=otlp
OTEL_LOGS_EXPORTER=otlp
OTEL_TRACES_SAMPLER=parentbased_traceidratio
OTEL_TRACES_SAMPLER_ARG=0.1
NO_PROXY=<tower>,<spitfire>
#OTEL_EXPORTER_OTLP_CERTIFICATE=/etc/spitfire-otel/ca.pem
  1. Restrict its permission: sudo chmod 600 /etc/spitfire-otel/<service-name>.env
  2. Create the file /opt/spitfire-otel/otel-run and paste this:
bash
#!/bin/sh
# IS_OTEL_ENABLED=true: the agent is loaded; any other value: no agent, SDK off.
if [ "$IS_OTEL_ENABLED" = "true" ]; then
  export JAVA_TOOL_OPTIONS="-javaagent:/opt/spitfire-otel/opentelemetry-javaagent.jar ${JAVA_TOOL_OPTIONS:-}"
else
  export OTEL_SDK_DISABLED=true
fi
exec "$@"
  1. Make it executable: sudo chmod 755 /opt/spitfire-otel/otel-run
  2. Find the service's current start command: systemctl cat <unit> | grep ^ExecStart
  3. Open sudo systemctl edit <unit> and paste this (on the last line, replace the command after ExecStart= with the command from step 6):
ini
[Service]
EnvironmentFile=/etc/spitfire-otel/<service-name>.env
ExecStart=
ExecStart=/opt/spitfire-otel/otel-run /usr/bin/java -jar /srv/app/app.jar
  1. Restart: sudo systemctl daemon-reload && sudo systemctl restart <unit>
  2. See that the agent is loaded: journalctl -u <unit> -n 200 | grep opentelemetry-javaagent (the line opentelemetry-javaagent - version: 2.33.1).
Note

The same path works for Tomcat, WildFly or an application started by its own script: the JVM reads JAVA_TOOL_OPTIONS itself.

Docker

  1. Put the otel-run file (Linux step 4) next to the Dockerfile.
  2. Add this to the Dockerfile; /opt/spitfire-otel/otel-run goes at the start of ENTRYPOINT, the rest is your command:
dockerfile
ADD --chmod=644 https://github.com/open-telemetry/opentelemetry-java-instrumentation/releases/download/v2.33.1/opentelemetry-javaagent.jar /opt/spitfire-otel/opentelemetry-javaagent.jar
COPY --chmod=755 otel-run /opt/spitfire-otel/otel-run
ENTRYPOINT ["/opt/spitfire-otel/otel-run", "java", "-jar", "/app/app.jar"]
  1. Save the environment file (Linux step 2) on the Docker machine as /etc/spitfire-otel/<service-name>.env.
  2. Run: docker run --env-file /etc/spitfire-otel/<service-name>.env … or, in compose, under the service env_file: /etc/spitfire-otel/<service-name>.env.
  3. When the environment file changes, recreate the container (restart is not enough): docker compose up -d --force-recreate <service>

Kubernetes

  1. Prepare the image as in the Docker section.
  2. Save the environment file (Linux step 2) as <service-name>.env and make it a Secret:
bash
kubectl create secret generic <service-name>-otel --from-env-file=<service-name>.env \
  --dry-run=client -o yaml | kubectl apply -f -
  1. In the Deployment, add this under the container:
yaml
envFrom:
  - secretRef:
      name: <service-name>-otel
  1. Restart: kubectl rollout restart deployment/<deployment>

Windows (service)

  1. Create the folder C:\spitfire-otel; download the agent (https://github.com/open-telemetry/opentelemetry-java-instrumentation/releases/download/v2.33.1/opentelemetry-javaagent.jar) and put it there as C:\spitfire-otel\opentelemetry-javaagent.jar.
  2. Open PowerShell as administrator, write the service's name (Name in the Get-Service list) in place of <windows-service> and run:
powershell
$Service = "<windows-service>"
$IS_OTEL_ENABLED = "true"
$Otel = @(
  "IS_OTEL_ENABLED=$IS_OTEL_ENABLED",
  "OTEL_SERVICE_NAME=<service-name>",
  "OTEL_RESOURCE_ATTRIBUTES=service.version=<service-version>,deployment.environment=<environment>",
  "OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf",
  "OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=https://<spitfire>/otlp/v1/traces",
  "OTEL_EXPORTER_OTLP_TRACES_HEADERS=authorization=sfotlp_…",
  "OTEL_EXPORTER_OTLP_LOGS_ENDPOINT=https://<spitfire>/otlp/v1/logs",
  "OTEL_EXPORTER_OTLP_LOGS_HEADERS=authorization=sfotlp_…",
  "OTEL_EXPORTER_OTLP_METRICS_ENDPOINT=http://<tower>:4318/v1/metrics",
  "OTEL_EXPORTER_OTLP_METRICS_HEADERS=authorization=sfcol_…",
  "OTEL_TRACES_EXPORTER=otlp",
  "OTEL_METRICS_EXPORTER=otlp",
  "OTEL_LOGS_EXPORTER=otlp",
  "OTEL_TRACES_SAMPLER=parentbased_traceidratio",
  "OTEL_TRACES_SAMPLER_ARG=0.1",
  "NO_PROXY=<tower>,<spitfire>"
)
# Private CA: $Otel += "OTEL_EXPORTER_OTLP_CERTIFICATE=C:\spitfire-otel\ca.pem"
if ($IS_OTEL_ENABLED -eq "true") {
  $Otel += "JAVA_TOOL_OPTIONS=-javaagent:C:\spitfire-otel\opentelemetry-javaagent.jar"
} else {
  $Otel += "OTEL_SDK_DISABLED=true"
}
$Key = "HKLM:\SYSTEM\CurrentControlSet\Services\$Service"
$Keep = @((Get-ItemProperty $Key).Environment | Where-Object { $_ -and $_ -notmatch '^(IS_OTEL_ENABLED|OTEL_|JAVA_TOOL_OPTIONS|NO_PROXY)=' })
Set-ItemProperty $Key -Name Environment -Type MultiString -Value ($Keep + $Otel)
Restart-Service -Name $Service -Force
  1. See the line opentelemetry-javaagent - version: 2.33.1 in the service's log.

Turning off and removing

  1. Turning off: set IS_OTEL_ENABLED=false in the environment file (in the script on Windows) and restart the service (Linux step 8, Docker step 5, Kubernetes step 4, or run the Windows script again).
  2. Removing: sudo systemctl revert <unit> and sudo rm -r /opt/spitfire-otel /etc/spitfire-otel; in Docker, delete the three lines added to the Dockerfile; on Windows, delete the OTel lines from the service's Environment value and remove C:\spitfire-otel.

Common problems

Symptom Cause Fix
No opentelemetry-javaagent line in the log otel-run did not run or IS_OTEL_ENABLED is not true Check that systemctl cat <unit> shows two ExecStart lines and EnvironmentFile
Picked up JAVA_TOOL_OPTIONS shows the agent twice The application already starts with -javaagent Remove the old -javaagent parameter
The image has no /bin/sh (distroless) otel-run cannot run Leave ENTRYPOINT as it is; add JAVA_TOOL_OPTIONS=-javaagent:/opt/spitfire-otel/opentelemetry-javaagent.jar to the environment file; to turn it off, OTEL_JAVAAGENT_ENABLED=false
No traces or metrics arrive Address, token or network Follow the Verifying steps