Send a fixed question and answer to Langfuse using langfuse-otel-core 0.2.3 from Maven Central. The example makes no model calls. Each run creates three observations:
java-first-trace CHAIN
├── lookup-docs TOOL
└── answer-question GENERATION (model: demo-fixture)
You need a JDK 11 or newer, Git, internet access to Maven Central, and a Langfuse project with Observations API v2. Langfuse Cloud supports this; the reproducible self-hosted check uses Langfuse 4.41.0. The wrapper downloads Maven and the published library.
-
Create or open a Langfuse project. In Settings → API Keys, create a project key pair.
-
Clone this repository and enter its root directory:
git clone https://github.com/ChoMinGi/langfuse-otel-java.git cd langfuse-otel-java -
Set the project host and keys, then run:
export LANGFUSE_HOST="https://cloud.langfuse.com" export LANGFUSE_PUBLIC_KEY="pk-lf-..." export LANGFUSE_SECRET_KEY="sk-lf-..." ./mvnw -B -ntp -f examples/first-trace/pom.xml compile exec:java
On Windows PowerShell:
$env:LANGFUSE_HOST = "https://cloud.langfuse.com" $env:LANGFUSE_PUBLIC_KEY = "pk-lf-..." $env:LANGFUSE_SECRET_KEY = "sk-lf-..." .\mvnw.cmd -B -ntp -f examples/first-trace/pom.xml compile exec:java
Choose the host where you created the project:
| Project location | LANGFUSE_HOST |
|---|---|
| Cloud EU | https://cloud.langfuse.com |
| Cloud US | https://us.cloud.langfuse.com |
| Cloud Japan | https://jp.cloud.langfuse.com |
| Self-hosted | Your HTTPS origin, without /api or another path |
The official OTel integration guide lists endpoints. The library adds the OTLP/HTTP path and v4 ingestion header.
After dependency downloads, the application prints a trace ID and polls for up to about 90 seconds.
It exits successfully only after checking all three observations, their parent links, shared
metadata, fixture model label, and input/output content. A successful flush() alone is not enough.
Sent synthetic trace: <trace-id>
Waiting up to 90 seconds for Langfuse ingestion...
Verified 3 observations: CHAIN -> TOOL + GENERATION
Verified parent links, synthetic input/output, and shared metadata.
Open: https://<your-host>/project/<your-project>/traces/<trace-id>
Read-back evidence: .../examples/first-trace/target/first-trace.json
Open the printed URL while signed into the same Langfuse project. You should see java-first-trace
with lookup-docs and answer-question as children. The demo labels every observation
synthetic-no-model-call. Token counts, cost, and first-token timing are left empty.
FirstTrace.java contains the tracing example; ReadBack.java checks that the demo reached Langfuse. Keep that check out of your application's request path.
- Replace the tool and generation fixture bodies with your application calls. Record provider
model/usage values only when the provider supplies them. Inside each observation's block, catch
application failures, call that observation's
fail(failure), and rethrow;close()alone cannot infer that a call failed. The observation guide shows the full error-handling pattern. - The demo explicitly enables
ContentCapturePolicy.captureAll()for fixed public strings. Choose your own policy before recording application input or output. The default is metadata-only. - Each observation closes independently;
.parent(root.context())links children without keeping a thread-local scope open. For async work, completion, cancellation, and errors, see the observation guide. - Keep one
LangfuseOtelinstance for the application's lifetime. This short-lived CLI flushes and closes its owned SDK at the end. If your application already owns OTel, follow the external SDK setup. - When adding a manual generation around a model call, disable automatic model instrumentation for that call to avoid double-counting. See migration guidance.
| Symptom | Next check |
|---|---|
Set LANGFUSE_... |
Set all three environment variables in the same terminal that runs Maven. |
| Java/compilation error | java -version and ./mvnw -version must select JDK 11+. |
| Dependency resolution failed | Check network/proxy access to Maven Central. Retry the command with -U if a failed download was cached. |
| Read-back HTTP 401/403 | Use project public/secret keys, and the matching Cloud region or self-hosted origin. |
| Read-back HTTP 404 or redirect | Remove /api from the host and confirm the server exposes Observations API v2. |
| Certificate or HTTP error | This example accepts HTTPS only. Use a trusted certificate; the local Docker setup uses a TLS proxy. |
| Ingestion timeout / 0–2 observations | Search the printed trace ID in your project; inspect exporter errors and receiver/worker health. Do not treat the flush as proof of ingestion. |
| Verification succeeds but the UI cannot open | Sign into the same project. Search its traces for the printed trace ID if your UI version uses a different URL. |
Let us know how it went, in English or Korean. Include your Java/OS versions and any step that was confusing. Remove API keys, private prompts, and customer data before posting.
CI compiles and tests this published-artifact consumer on Java 11, 17, and 21. The observation read-back workflow runs the same example against the digest-pinned, disposable Langfuse 4.41.0 stack, with a fresh Maven repository. Keep this example's POM on a published version, independently of the library's development version. Docker and Node are needed only for maintainer checks and screenshot capture.
To regenerate the documentation screenshot, manually run Observation v4 read-back with
capture_screenshot=true. It installs the locked browser helper, signs into only the disposable
project, captures the trace page, and uploads the PNG alongside the JSON read-back. Inspect the
image before copying it into docs/images/; the workflow never commits documentation automatically.