Skip to content

Commit 982aa48

Browse files
Steffen911claude
andauthored
feat!: remove endpoints deprecated in Langfuse v4 (#49)
Langfuse v4 moves to an observations-first data model, and the endpoints built on the v3 model are deprecated: Langfuse Cloud serves them until November 16, 2026, and self-hosted deployments lose them on upgrade to v4. This prunes them from the generated client so it only exposes the API surface that survives the cutover. Removed entirely (every endpoint deprecated): ingestion POST /ingestion observations GET /observations, /observations/{id} metrics GET /metrics (v1) sessions GET /sessions, /sessions/{id} scorev2 GET /v2/scores, /v2/scores/{id} datasetrunitems POST/GET /dataset-run-items Pruned to the non-deprecated operations: trace dropped get()/list(), kept delete()/deleteMultiple() — trace deletion is not deprecated and is now the documented way to delete experiment data datasets dropped getRun()/deleteRun()/getRuns(), kept the /v2/datasets operations Also drops the 34 types under resources/commons/types that the removal orphaned (the v3-model read models: Trace*, Session*, Observation, ObservationsView, the Score/ScoreV1 unions, DatasetRun*, Usage) and unwires the six clients from LangfuseClient/AsyncLangfuseClient. Orphan status was verified with an import-graph reachability pass and diffed against HEAD so pre-existing orphans stayed out of scope. Score writes are unaffected: POST /scores and DELETE /scores/{scoreId} stay supported after the cutover. Only score reads move to /v3/scores. The README now leads with OpenTelemetry as the recommended and going-forward only supported path for tracing, and documents the per-endpoint migration mapping. It also records that the prune has to be re-applied after each regeneration, since the generator reproduces deprecated endpoints. Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
1 parent bd07ee8 commit 982aa48

132 files changed

Lines changed: 68 additions & 42009 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎README.md‎

Lines changed: 43 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,23 @@
33
This repository contains an auto-generated Langfuse API client for Java based on our [API specification](https://github.com/langfuse/langfuse/tree/main/fern/apis/server).
44
See the [Langfuse API reference](https://api.reference.langfuse.com) for more details on the available endpoints.
55

6-
**Note:** We recommend to solve tracing via the [OpenTelemetry Instrumentation](https://langfuse.com/docs/opentelemetry/get-started) instead of using the Ingestion API directly. You can use the [OpenTelemetry Java SDK](https://github.com/open-telemetry/opentelemetry-java) and export spans to the [Langfuse OTel endpoint](https://langfuse.com/integrations/native/opentelemetry).
7-
This allows for a more detailed and standardized tracing experience without the need to handle batching and updates internally.
8-
Check out our [Spring AI Example](https://langfuse.com/docs/integrations/spring-ai) for more details.
6+
## Use OpenTelemetry for tracing
7+
8+
**OpenTelemetry is the recommended — and, going forward, the only supported — way to send tracing data to Langfuse from Java.**
9+
This client no longer exposes the legacy ingestion API; it is deprecated and is removed in [Langfuse v4](https://langfuse.com/docs/v4).
10+
11+
Instrument your application with the [OpenTelemetry Java SDK](https://github.com/open-telemetry/opentelemetry-java) and export spans over OTLP/HTTP to the [Langfuse OTel endpoint](https://langfuse.com/integrations/native/opentelemetry):
12+
13+
```bash
14+
OTEL_EXPORTER_OTLP_ENDPOINT="https://cloud.langfuse.com/api/public/otel"
15+
OTEL_EXPORTER_OTLP_HEADERS="Authorization=Basic ${AUTH_STRING},x-langfuse-ingestion-version=4"
16+
```
17+
18+
The `x-langfuse-ingestion-version: 4` header selects the v4 ingestion path. It is not sufficient on its own — spans also have to follow the v4 span format. Read [Migrate custom ingestion to Langfuse v4](https://langfuse.com/integrations/native/opentelemetry/migration-to-v4) before switching production traffic; it covers the [v4-ready checklist](https://langfuse.com/integrations/native/opentelemetry/migration-to-v4#v4-ready-ingestion-checklist), the [legacy event → OTel span mapping](https://langfuse.com/integrations/native/opentelemetry/migration-to-v4#migrate-from-the-legacy-ingestion-api), and [propagating trace context to every observation](https://langfuse.com/integrations/native/opentelemetry/migration-to-v4#propagate-trace-context-to-observations).
19+
20+
Going through OpenTelemetry also means you do not have to handle batching, retries, or observation updates yourself. Check out our [Spring AI example](https://langfuse.com/integrations/frameworks/spring-ai) for a full setup.
21+
22+
Use this client for everything that is *not* tracing ingestion: prompts, datasets, scores, models, comments, annotation queues, and the reading APIs.
923

1024
## Installation
1125

@@ -50,6 +64,30 @@ try {
5064
}
5165
```
5266

67+
## Langfuse v4: removed endpoints
68+
69+
Langfuse v4 uses an [observations-first data model](https://langfuse.com/docs/v4). The endpoints built on the v3 model are deprecated: Langfuse Cloud serves them until **November 16, 2026**, and they become unavailable in self-hosted deployments as soon as those upgrade to v4.
70+
71+
Those endpoints have been **removed from this client** so that it only exposes the API surface that survives the v4 cutover. The canonical, per-endpoint migration reference is [Migration of deprecated APIs](https://langfuse.com/faq/all/deprecated-api-migration); the [Versions & Compatibility matrix](https://langfuse.com/docs/compatibility) lists which endpoints work against which server version, and [Make your project ready for the upgrade to Langfuse v4](https://langfuse.com/faq/all/upgrade-to-langfuse-v4) is the step-by-step upgrade guide.
72+
73+
| Removed from this client | Deprecated endpoint | Replacement |
74+
| --------------------------------------------------------------------------------- | ------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
75+
| `client.ingestion().batch(...)` | `POST /api/public/ingestion` | [OpenTelemetry ingestion](https://langfuse.com/faq/all/deprecated-api-migration#ingestion) — see above |
76+
| `client.observations().get(...)` / `.getMany(...)` | `GET /api/public/observations`, `/observations/{id}` | `client.observationsV2().getMany(...)` ([Observations API v2](https://langfuse.com/faq/all/deprecated-api-migration#observations)) |
77+
| `client.trace().get(...)` / `.list(...)` | `GET /api/public/traces`, `/traces/{id}` | `client.observationsV2().getMany(...)` filtered by `traceId` ([Traces](https://langfuse.com/faq/all/deprecated-api-migration#traces)) |
78+
| `client.sessions().get(...)` / `.list(...)` | `GET /api/public/sessions`, `/sessions/{id}` | `client.observationsV2().getMany(...)` filtered by `sessionId` ([Sessions](https://langfuse.com/faq/all/deprecated-api-migration#sessions)) |
79+
| `client.metrics().metrics(...)` | `GET /api/public/metrics` | `client.metricsV2().metrics(...)` ([Metrics API v2](https://langfuse.com/faq/all/deprecated-api-migration#metrics)) |
80+
| `client.scoreV2().get(...)` / `.getById(...)` | `GET /api/public/v2/scores`, `/v2/scores/{id}` | [Scores API v3](https://langfuse.com/faq/all/deprecated-api-migration#scores) — **not generated yet**, call `GET /api/public/v3/scores` directly for now |
81+
| `client.datasets().getRuns(...)` / `.getRun(...)` / `.deleteRun(...)` | `GET`/`DELETE /api/public/datasets/{name}/runs[/{runName}]` | [Experiments API](https://langfuse.com/faq/all/deprecated-api-migration#dataset-runs) — **not generated yet**, call `GET /api/public/experiments` directly for now |
82+
| `client.datasetRunItems().create(...)` / `.list(...)` | `POST`/`GET /api/public/dataset-run-items` | [Experiment Items API](https://langfuse.com/faq/all/deprecated-api-migration#dataset-runs) / OTel experiment attributes — **not generated yet** |
83+
84+
Notes:
85+
86+
- **Score writes are unaffected.** `client.score().create(...)` (`POST /api/public/scores`) and `client.score().delete(...)` stay supported after the v4 cutover. Only score *reads* move to v3.
87+
- **Trace deletion is not deprecated.** `client.trace().delete(...)` and `client.trace().deleteMultiple(...)` are kept; they are also how you delete experiment data now that `DELETE /datasets/{name}/runs/{runName}` is gone.
88+
- **Datasets themselves are not deprecated.** `client.datasets()` still exposes the `/api/public/v2/datasets` endpoints; only the dataset *run* endpoints were removed.
89+
- The `/api/public/v3/scores`, `/api/public/experiments`, and `/api/public/experiment-items` endpoints exist in the Langfuse API but are not part of this client yet. They will be picked up by the next regeneration; until then, call them directly.
90+
5391
## Testing
5492

5593
### Unit tests
@@ -117,4 +155,5 @@ To publish to Maven Central, you need to configure the following secrets in your
117155
4. Manually set the `package` across all files to `com.langfuse.client`.
118156
5. Verify that `LangfuseClientBuilder.setAuthentication()` uses `Basic` auth (not `Bearer`).
119157
6. Adjust Javadoc strings with HTML properties as the apidocs package does not support them.
120-
7. Commit the changes in langfuse-java and push them to the repository.
158+
7. Re-apply the deprecated-endpoint prune. Regeneration reintroduces every endpoint marked `availability: status: deprecated` in the API definition — the ones listed under [Langfuse v4: removed endpoints](#langfuse-v4-removed-endpoints). Drop those resource packages and methods again, remove the now-orphaned types under `resources/commons/types`, and unwire them from `LangfuseClient`/`AsyncLangfuseClient`.
159+
8. Commit the changes in langfuse-java and push them to the repository.

‎src/main/java/com/langfuse/client/AsyncLangfuseClient.java‎

Lines changed: 0 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,12 @@
99
import com.langfuse.client.resources.blobstorageintegrations.AsyncBlobStorageIntegrationsClient;
1010
import com.langfuse.client.resources.comments.AsyncCommentsClient;
1111
import com.langfuse.client.resources.datasetitems.AsyncDatasetItemsClient;
12-
import com.langfuse.client.resources.datasetrunitems.AsyncDatasetRunItemsClient;
1312
import com.langfuse.client.resources.datasets.AsyncDatasetsClient;
1413
import com.langfuse.client.resources.health.AsyncHealthClient;
15-
import com.langfuse.client.resources.ingestion.AsyncIngestionClient;
1614
import com.langfuse.client.resources.llmconnections.AsyncLlmConnectionsClient;
1715
import com.langfuse.client.resources.media.AsyncMediaClient;
18-
import com.langfuse.client.resources.metrics.AsyncMetricsClient;
1916
import com.langfuse.client.resources.metricsv2.AsyncMetricsV2Client;
2017
import com.langfuse.client.resources.models.AsyncModelsClient;
21-
import com.langfuse.client.resources.observations.AsyncObservationsClient;
2218
import com.langfuse.client.resources.observationsv2.AsyncObservationsV2Client;
2319
import com.langfuse.client.resources.opentelemetry.AsyncOpentelemetryClient;
2420
import com.langfuse.client.resources.organizations.AsyncOrganizationsClient;
@@ -28,8 +24,6 @@
2824
import com.langfuse.client.resources.scim.AsyncScimClient;
2925
import com.langfuse.client.resources.score.AsyncScoreClient;
3026
import com.langfuse.client.resources.scoreconfigs.AsyncScoreConfigsClient;
31-
import com.langfuse.client.resources.scorev2.AsyncScoreV2Client;
32-
import com.langfuse.client.resources.sessions.AsyncSessionsClient;
3327
import com.langfuse.client.resources.trace.AsyncTraceClient;
3428

3529
public class AsyncLangfuseClient {
@@ -43,28 +37,20 @@ public class AsyncLangfuseClient {
4337

4438
protected final Supplier<AsyncDatasetItemsClient> datasetItemsClient;
4539

46-
protected final Supplier<AsyncDatasetRunItemsClient> datasetRunItemsClient;
47-
4840
protected final Supplier<AsyncDatasetsClient> datasetsClient;
4941

5042
protected final Supplier<AsyncHealthClient> healthClient;
5143

52-
protected final Supplier<AsyncIngestionClient> ingestionClient;
53-
5444
protected final Supplier<AsyncLlmConnectionsClient> llmConnectionsClient;
5545

5646
protected final Supplier<AsyncMediaClient> mediaClient;
5747

5848
protected final Supplier<AsyncMetricsV2Client> metricsV2Client;
5949

60-
protected final Supplier<AsyncMetricsClient> metricsClient;
61-
6250
protected final Supplier<AsyncModelsClient> modelsClient;
6351

6452
protected final Supplier<AsyncObservationsV2Client> observationsV2Client;
6553

66-
protected final Supplier<AsyncObservationsClient> observationsClient;
67-
6854
protected final Supplier<AsyncOpentelemetryClient> opentelemetryClient;
6955

7056
protected final Supplier<AsyncOrganizationsClient> organizationsClient;
@@ -79,12 +65,8 @@ public class AsyncLangfuseClient {
7965

8066
protected final Supplier<AsyncScoreConfigsClient> scoreConfigsClient;
8167

82-
protected final Supplier<AsyncScoreV2Client> scoreV2Client;
83-
8468
protected final Supplier<AsyncScoreClient> scoreClient;
8569

86-
protected final Supplier<AsyncSessionsClient> sessionsClient;
87-
8870
protected final Supplier<AsyncTraceClient> traceClient;
8971

9072
public AsyncLangfuseClient(ClientOptions clientOptions) {
@@ -93,27 +75,21 @@ public AsyncLangfuseClient(ClientOptions clientOptions) {
9375
this.blobStorageIntegrationsClient = Suppliers.memoize(() -> new AsyncBlobStorageIntegrationsClient(clientOptions));
9476
this.commentsClient = Suppliers.memoize(() -> new AsyncCommentsClient(clientOptions));
9577
this.datasetItemsClient = Suppliers.memoize(() -> new AsyncDatasetItemsClient(clientOptions));
96-
this.datasetRunItemsClient = Suppliers.memoize(() -> new AsyncDatasetRunItemsClient(clientOptions));
9778
this.datasetsClient = Suppliers.memoize(() -> new AsyncDatasetsClient(clientOptions));
9879
this.healthClient = Suppliers.memoize(() -> new AsyncHealthClient(clientOptions));
99-
this.ingestionClient = Suppliers.memoize(() -> new AsyncIngestionClient(clientOptions));
10080
this.llmConnectionsClient = Suppliers.memoize(() -> new AsyncLlmConnectionsClient(clientOptions));
10181
this.mediaClient = Suppliers.memoize(() -> new AsyncMediaClient(clientOptions));
10282
this.metricsV2Client = Suppliers.memoize(() -> new AsyncMetricsV2Client(clientOptions));
103-
this.metricsClient = Suppliers.memoize(() -> new AsyncMetricsClient(clientOptions));
10483
this.modelsClient = Suppliers.memoize(() -> new AsyncModelsClient(clientOptions));
10584
this.observationsV2Client = Suppliers.memoize(() -> new AsyncObservationsV2Client(clientOptions));
106-
this.observationsClient = Suppliers.memoize(() -> new AsyncObservationsClient(clientOptions));
10785
this.opentelemetryClient = Suppliers.memoize(() -> new AsyncOpentelemetryClient(clientOptions));
10886
this.organizationsClient = Suppliers.memoize(() -> new AsyncOrganizationsClient(clientOptions));
10987
this.projectsClient = Suppliers.memoize(() -> new AsyncProjectsClient(clientOptions));
11088
this.promptVersionClient = Suppliers.memoize(() -> new AsyncPromptVersionClient(clientOptions));
11189
this.promptsClient = Suppliers.memoize(() -> new AsyncPromptsClient(clientOptions));
11290
this.scimClient = Suppliers.memoize(() -> new AsyncScimClient(clientOptions));
11391
this.scoreConfigsClient = Suppliers.memoize(() -> new AsyncScoreConfigsClient(clientOptions));
114-
this.scoreV2Client = Suppliers.memoize(() -> new AsyncScoreV2Client(clientOptions));
11592
this.scoreClient = Suppliers.memoize(() -> new AsyncScoreClient(clientOptions));
116-
this.sessionsClient = Suppliers.memoize(() -> new AsyncSessionsClient(clientOptions));
11793
this.traceClient = Suppliers.memoize(() -> new AsyncTraceClient(clientOptions));
11894
}
11995

@@ -133,10 +109,6 @@ public AsyncDatasetItemsClient datasetItems() {
133109
return this.datasetItemsClient.get();
134110
}
135111

136-
public AsyncDatasetRunItemsClient datasetRunItems() {
137-
return this.datasetRunItemsClient.get();
138-
}
139-
140112
public AsyncDatasetsClient datasets() {
141113
return this.datasetsClient.get();
142114
}
@@ -145,10 +117,6 @@ public AsyncHealthClient health() {
145117
return this.healthClient.get();
146118
}
147119

148-
public AsyncIngestionClient ingestion() {
149-
return this.ingestionClient.get();
150-
}
151-
152120
public AsyncLlmConnectionsClient llmConnections() {
153121
return this.llmConnectionsClient.get();
154122
}
@@ -161,10 +129,6 @@ public AsyncMetricsV2Client metricsV2() {
161129
return this.metricsV2Client.get();
162130
}
163131

164-
public AsyncMetricsClient metrics() {
165-
return this.metricsClient.get();
166-
}
167-
168132
public AsyncModelsClient models() {
169133
return this.modelsClient.get();
170134
}
@@ -173,10 +137,6 @@ public AsyncObservationsV2Client observationsV2() {
173137
return this.observationsV2Client.get();
174138
}
175139

176-
public AsyncObservationsClient observations() {
177-
return this.observationsClient.get();
178-
}
179-
180140
public AsyncOpentelemetryClient opentelemetry() {
181141
return this.opentelemetryClient.get();
182142
}
@@ -205,18 +165,10 @@ public AsyncScoreConfigsClient scoreConfigs() {
205165
return this.scoreConfigsClient.get();
206166
}
207167

208-
public AsyncScoreV2Client scoreV2() {
209-
return this.scoreV2Client.get();
210-
}
211-
212168
public AsyncScoreClient score() {
213169
return this.scoreClient.get();
214170
}
215171

216-
public AsyncSessionsClient sessions() {
217-
return this.sessionsClient.get();
218-
}
219-
220172
public AsyncTraceClient trace() {
221173
return this.traceClient.get();
222174
}

0 commit comments

Comments
 (0)