A Quarkus extension for Langfuse, the open-source LLM engineering platform. This extension provides a type-safe REST client (based on the Langfuse Java SDK), DevServices for zero-config local development, and a Dev UI card for quick access to the Langfuse dashboard.
Langfuse helps you ship AI Agents and Products from prototype to production and beyond. It provides observability (traces, sessions, scores), prompt management (versioning, deployment, A/B testing), and evaluation (datasets, experiments, LLM-as-a-judge) for LLM-powered applications.
- Type-safe Langfuse API client - Synchronous and asynchronous clients covering the full Langfuse public API (traces, ingestion, prompts, scores, datasets, observations, sessions, and more), built on the Quarkus REST Client Reactive.
- Higher-level API operations - Curated
LangfuseOperationsandAsyncLangfuseOperations(Mutiny) beans covering seventeen domains - models, datasets and dataset items, LLM connections, score configs, evaluation rules, evaluators and their versions, prompts, annotation queues and their items, comments, scores, observations, experiments and experiment items, and blob storage integrations. They offer find-by-id and find-by-name, existence checks, filtered views, lazy pagination with short-circuiting, idempotent resource initialization, and batch deletes that report an outcome per identifier, with anapi()escape hatch to the raw client. - CDI integration - Inject
LangfuseApi,LangfuseOperations, orAsyncLangfuseOperationsdirectly into your beans. - DevServices - Automatically starts a complete Langfuse stack (Langfuse server, PostgreSQL, ClickHouse, Redis, MinIO, and Worker) in dev and test mode using Testcontainers. No manual setup required.
- Dev UI - Provides a Dev UI card with a direct link to the Langfuse dashboard running in your local DevServices instance.
- Native image support - Compatible with GraalVM native image compilation.
- OpenTelemetry integration - When
quarkus-opentelemetryis on the classpath, automatically exports AI-related spans to Langfuse. Zero configuration needed with DevServices.
This version of the extension requires Langfuse v4. If you are upgrading from a previous version of the extension that targeted Langfuse v3, complete the Langfuse v4 migration before upgrading the extension.
The Langfuse v4 OpenAPI spec uses the const keyword (an OpenAPI 3.1 feature) while declaring version 3.0.1. The openapi-generator-maven-plugin cannot validate the spec with this incompatibility, so skipValidateSpec is set to true in the langfuse-client module's POM. This does not affect code generation -- only the upfront validation check is bypassed. This is tracked upstream as openapi-generator#10445.
Add the extension dependency to your project:
<dependency>
<groupId>io.quarkiverse.langfuse</groupId>
<artifactId>quarkus-langfuse</artifactId>
<version>${quarkus-langfuse.version}</version>
</dependency>implementation 'io.quarkiverse.langfuse:quarkus-langfuse:${quarkus-langfuse.version}'Configure your Langfuse connection in application.properties:
quarkus.langfuse.base-url=https://cloud.langfuse.com
quarkus.langfuse.public-key=pk-lf-...
quarkus.langfuse.secret-key=sk-lf-...Note: When DevServices is enabled (the default in dev/test mode),
base-url,username, andpasswordare automatically configured for you. You only need to set these properties when connecting to an external Langfuse instance or in production.
| Property | Type | Default | Description |
|---|---|---|---|
quarkus.langfuse.base-url |
String |
required | Base URL of the Langfuse server |
quarkus.langfuse.public-key |
String |
required | Langfuse project public key |
quarkus.langfuse.secret-key |
String |
required | Langfuse project secret key |
quarkus.langfuse.timeout |
Duration |
1m |
Default timeout for Langfuse API calls |
quarkus.langfuse.connect-timeout |
Duration |
${quarkus.langfuse.timeout} |
Timeout to establish a connection |
quarkus.langfuse.read-timeout |
Duration |
${quarkus.langfuse.timeout} |
Timeout for receiving a response |
quarkus.langfuse.log-requests |
boolean |
false |
Log outgoing requests |
quarkus.langfuse.log-responses |
boolean |
false |
Log incoming responses |
quarkus.langfuse.pretty-print |
boolean |
false |
Pretty-print JSON bodies in logs |
quarkus.langfuse.otel.enabled |
boolean |
true |
Enable/disable OpenTelemetry integration (build time, defaults to quarkus.otel.enabled) |
quarkus.langfuse.otel.export-target |
String |
ALL |
Export target (build time): ALL (Langfuse + other OTLP backends) or LANGFUSE_ONLY |
quarkus.langfuse.otel.trace-ingestion-url |
String |
<base-url>/api/public/otel/v1/traces |
Override the OTLP trace ingestion endpoint (applies when export-target=ALL) |
quarkus.langfuse.otel.span-filter |
String |
AI_ONLY |
Span filter: AI_ONLY (AI spans + ancestors) or ALL (applies when export-target=ALL) |
Simply inject LangfuseApi into your CDI beans. The extension automatically configures and provides the implementation:
import com.langfuse.api.LangfuseApi;
@ApplicationScoped
public class MyService {
@Inject
LangfuseApi langfuseApi;
public void listObservations() {
// Synchronous call
var observations = langfuseApi.observations().observationsGetMany(/* parameters */);
// Asynchronous call
var asyncObservations = langfuseApi.asyncObservations().observationsGetMany(/* parameters */);
}
public void listPrompts() {
var prompts = langfuseApi.prompts().promptsList(/* parameters */);
}
public void listScores() {
var scores = langfuseApi.scoresV3().scoresV3GetManyV3(/* parameters */);
}
public void checkHealth() {
var health = langfuseApi.health().healthHealth();
}
}The LangfuseApi bean provides access to the full Langfuse public API. Each API group is available as a method, with both synchronous and asynchronous variants (e.g., trace() / asyncTrace()):
| API Group | Description |
|---|---|
health() |
Health check endpoints |
opentelemetry() |
OpenTelemetry trace ingestion (recommended for v4) |
observations() |
Query observations with selective fields and cursor pagination (v2) |
scores() |
Create scores and query scores (v2, deprecated in events_only mode) |
scoresV3() |
Query scores with polymorphic values and cursor pagination (v3, recommended) |
experiments() |
List experiments and experiment items (dataset runs) |
prompts() |
Manage, version, and retrieve prompts |
promptVersion() |
Manage individual prompt versions |
scoreConfigs() |
Manage score configurations |
datasets() |
Create and manage datasets |
datasetItems() |
Manage dataset items |
datasetRunItems() |
Manage dataset run items |
models() |
Create, upsert, and manage model definitions and pricing |
evaluators() |
Create and manage evaluators (v2) |
evaluationRules() |
Create and manage evaluation rules (v2) |
projects() |
Manage projects and API keys |
organizations() |
Manage organization memberships |
comments() |
Manage comments on traces |
media() |
Upload and manage media attachments |
metrics() |
Query usage metrics (v2) |
annotationQueues() |
Manage annotation queues for human review |
llmConnections() |
Manage LLM provider connections |
blobStorageIntegrations() |
Manage blob storage integrations |
scim() |
SCIM user provisioning |
feedback() |
Submit feedback about Langfuse features |
unstableDashboardWidgets() |
Create, list, update, and delete dashboard widgets (unstable) |
unstableDashboards() |
Create, list, update, and delete dashboards with placements (unstable) |
ingestion() |
Legacy batch ingestion (deprecated — use opentelemetry()) |
trace() |
Legacy trace endpoints (deprecated in v4 events_only mode) |
sessions() |
Legacy session endpoints (deprecated in v4 events_only mode) |
legacyObservationsV1() |
Legacy observations (v1, deprecated — use observations()) |
legacyMetricsV1() |
Legacy metrics (v1, deprecated — use metrics()) |
legacyScoreV1() |
Legacy score deletion (v1, deprecated) |
When the quarkus-opentelemetry extension is on the classpath, the Langfuse extension automatically exports OpenTelemetry span data to Langfuse. No additional configuration is needed -- authentication is derived from your existing quarkus.langfuse.username and quarkus.langfuse.password settings.
The quarkus.langfuse.otel.export-target property (build time) controls how spans are exported:
-
ALL(default) -- The extension registers a dedicated Langfuse span processor that runs alongside any other OpenTelemetry exporters you have configured. Spans are exported to both Langfuse and your standard OTLP backend (Jaeger, Zipkin, or any other collector). In this mode, only AI-related spans are sent to Langfuse by default (see AI Span Filtering below), and thegen_ai.prompt/gen_ai.completionattributes are automatically mapped to the Langfuse trace input and output. -
LANGFUSE_ONLY-- The standard OpenTelemetry OTLP exporter is configured to send directly to Langfuse. No separate span processor is registered and no additional OTLP backend receives spans. All spans are exported to Langfuse without filtering. This is equivalent to the manual configuration described in the Quarkus LangChain4j docs, but handled automatically by the extension.
quarkus.langfuse.otel.export-target=LANGFUSE_ONLYWhen export-target=ALL (the default), only AI-related spans -- those carrying gen_ai.* OpenTelemetry Semantic Convention attributes -- and their ancestor spans are exported to Langfuse. This avoids cluttering your Langfuse dashboard with HTTP, database, or other infrastructure spans.
The gen_ai.prompt and gen_ai.completion attributes are automatically mapped to the Langfuse trace input and output, giving you immediate visibility into what was sent to and received from the LLM.
To export all spans instead, set:
quarkus.langfuse.otel.span-filter=ALLWhen both quarkus-opentelemetry and quarkus-langchain4j are on the classpath, the extension automatically enables LangChain4j prompt tracing. Prompt content, LLM responses, tool arguments, and tool results are all included in the OpenTelemetry spans emitted by LangChain4j -- and therefore visible in Langfuse traces -- without any manual configuration.
These defaults are set at a low priority, so you can override any of them in application.properties or via environment variables.
When DevServices is running, the OTel integration works out of the box with no configuration at all. The Langfuse base URL, public key, and secret key are all provided automatically.
To disable the OpenTelemetry integration entirely (for example, if you want to manage your own OTel exporters):
quarkus.langfuse.otel.enabled=falseWhen quarkus-opentelemetry is not on the classpath, the integration is automatically skipped.
In dev and test mode, the extension automatically starts a complete Langfuse stack using Testcontainers:
- Langfuse server - The main Langfuse application
- PostgreSQL - Primary database
- ClickHouse - Analytics database
- Redis - Cache
- MinIO - Object storage (for media/blob storage)
- Worker - Background job processing
No configuration is needed - just add the extension and run quarkus dev. The extension automatically configures quarkus.langfuse.base-url, quarkus.langfuse.username, and quarkus.langfuse.password to point to the DevServices instance.
DevServices can be customized under quarkus.langfuse.devservices:
| Property | Type | Default | Description |
|---|---|---|---|
quarkus.langfuse.devservices.enabled |
boolean |
true |
Enable/disable DevServices |
quarkus.langfuse.devservices.shared |
boolean |
true |
Share containers across applications |
quarkus.langfuse.devservices.service-name |
String |
langfuse |
Label for container discovery |
quarkus.langfuse.devservices.langfuse.image-name |
String |
(Langfuse default) | Langfuse server container image |
quarkus.langfuse.devservices.langfuse.port |
int |
8080 |
Langfuse server port |
quarkus.langfuse.devservices.langfuse.username |
String |
quarkus |
Project public key |
quarkus.langfuse.devservices.langfuse.password |
String |
quarkuslangfuse |
Project secret key |
quarkus.langfuse.devservices.langfuse.startup-timeout |
Duration |
PT3M |
Container startup timeout |
The Langfuse server also has properties to configure the initial organization, project, and user. See the full configuration reference for details.
When running in dev mode (quarkus dev), the extension adds a Langfuse card to the Quarkus Dev UI. The card includes a link to the Langfuse web dashboard running in your DevServices container, allowing you to browse traces, manage prompts, view scores, and more directly from your development environment.
The full documentation is available at https://docs.quarkiverse.io/quarkus-langfuse/dev/index.html.
Thanks goes to these wonderful people (emoji key):
Eric Deandrea 💻 🚧 |
Bill Burke 💻 🚧 🖋 📖 🤔 |
This project follows the all-contributors specification. Contributions of any kind welcome!