fix(langfuse): v4 가 옛 ingestion 을 거부 — OTLP/HTTP JSON(/api/public/otel/v1/traces)으로 전환, 로컬 Langfuse 실측 통과. 사용자·세션 속성은 자식 span 에도 복사
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5.1
parent
0321050053
commit
55f2e8fb60
@@ -2,30 +2,32 @@
|
||||
|
||||
출처: `https://cloud.langfuse.com/generated/api/openapi.yml`, `langfuse.com/self-hosting`. SDK 안 쓰고 HTTP 로 직접 쏨(오프라인 wheels 반입 줄이려고).
|
||||
|
||||
## POST /api/public/ingestion
|
||||
## v4 는 OTLP 로 (2026-09-22 로컬 실측)
|
||||
|
||||
- 인증: Basic auth — user = `pk-lf-…`(public key), password = `sk-lf-…`(secret key)
|
||||
- 응답: **207** (배치 부분 성공). 각 이벤트 결과가 `successes[]`/`errors[]` 로 옴
|
||||
- Langfuse Cloud 에선 2026-11-16 폐기 예정이지만 **self-host 는 계속 지원**. OTel 엔드포인트(`/api/public/otel/v1/traces`)는 v3+ 만.
|
||||
옛 `POST /api/public/ingestion` 은 v4 기본(`LANGFUSE_MIGRATION_V4_WRITE_MODE=events_only`)에서 **trace/generation 을 400 으로 거부**함(score 만 받음).
|
||||
`dual` 로 열 수 있지만 다음 메이저에서 없어짐 → 우리는 OTLP 로 감.
|
||||
|
||||
### POST /api/public/otel/v1/traces
|
||||
- OTLP/HTTP **JSON** 도 받음(protobuf 안 써도 됨). gRPC 는 없음.
|
||||
- 헤더: `Authorization: Basic base64(pk-lf-…:sk-lf-…)`, `x-langfuse-ingestion-version: 4`(직접 쓰기, 15분 지연 없음)
|
||||
- 응답 200 `{}`. 일부 거부면 `partialSuccess.rejectedSpans`.
|
||||
- traceId = 16바이트 hex(32자), spanId = 8바이트 hex(16자). 시간은 `startTimeUnixNano`/`endTimeUnixNano` 문자열.
|
||||
|
||||
```json
|
||||
{
|
||||
"batch": [
|
||||
{"id": "evt-1", "timestamp": "2026-09-22T01:00:00Z", "type": "trace-create",
|
||||
"body": {"id": "trace-1", "name": "chat", "userId": "u@x.com", "sessionId": "ses_…", "input": "…", "output": "…", "metadata": {}, "tags": []}},
|
||||
{"id": "evt-2", "timestamp": "2026-09-22T01:00:05Z", "type": "generation-create",
|
||||
"body": {"id": "gen-1", "traceId": "trace-1", "name": "fabrix", "model": "581",
|
||||
"startTime": "…", "endTime": "…", "input": [...messages], "output": "…",
|
||||
"usage": {"input": 120, "output": 30, "total": 150}, "level": "DEFAULT", "statusMessage": "", "metadata": {}}}
|
||||
]
|
||||
}
|
||||
{"resourceSpans":[{"resource":{"attributes":[{"key":"service.name","value":{"stringValue":"codeassist-backend"}}]},
|
||||
"scopeSpans":[{"scope":{"name":"codeassist"},"spans":[
|
||||
{"traceId":"<32hex>","spanId":"<16hex>","name":"chat","kind":1,"startTimeUnixNano":"…","endTimeUnixNano":"…",
|
||||
"attributes":[{"key":"langfuse.trace.name","value":{"stringValue":"chat"}},{"key":"langfuse.user.id","value":{"stringValue":"u@x.com"}}],
|
||||
"status":{"code":1}},
|
||||
{"traceId":"<같은>","spanId":"<16hex>","parentSpanId":"<루트 spanId>","name":"fabrix.chat","kind":1,…,
|
||||
"attributes":[{"key":"langfuse.observation.type","value":{"stringValue":"generation"}},…]}]}]}]}
|
||||
```
|
||||
|
||||
- envelope: `id`(중복 제거용, 유일), `timestamp`(ISO 8601), `type`, `body`
|
||||
- 이벤트 타입: `trace-create`, `generation-create`, `span-create`, `event-create`, `score-create`, `*-update`
|
||||
- TraceBody: id·name·userId·sessionId·input·output·metadata·tags·version·release·environment·public
|
||||
- CreateGenerationBody: id·traceId·name·startTime·endTime·completionStartTime·model·modelParameters·input·output·usage{input,output,total,unit,inputCost,outputCost,totalCost}·usageDetails·costDetails·level(DEBUG/DEFAULT/WARNING/ERROR)·statusMessage·metadata·parentObservationId
|
||||
- 같은 traceId 로 trace-create 를 여러 번 보내도 됨(upsert). generation 먼저 와도 trace 가 나중에 붙음.
|
||||
### 속성 → Langfuse 필드
|
||||
- 관측(span) 단위: `langfuse.observation.type`(generation/span), `.model.name`, `.input`, `.output`, `.usage_details`(JSON `{"input","output","total"}`), `.model_parameters`, `.level`(DEBUG/DEFAULT/WARNING/ERROR), `.status_message`, `.metadata.<키>`, `.cost_details`
|
||||
(대안: `gen_ai.request.model`, `gen_ai.prompt`/`gen_ai.completion`, `gen_ai.usage.*`)
|
||||
- 트레이스 단위(아무 span 에나 실으면 트레이스 전체에 적용, 필터 쓰려면 루트에): `langfuse.trace.name`(없으면 루트 span 이름), `langfuse.user.id`, `langfuse.session.id`, `langfuse.trace.tags`(JSON 배열), `langfuse.trace.input`/`.output`, `langfuse.trace.metadata.<키>`, `langfuse.environment`, `langfuse.version`
|
||||
- 값 인코딩: 문자열은 stringValue, 객체/배열은 JSON 문자열로 넣으면 Langfuse 가 파싱해서 보여줌.
|
||||
|
||||
## 자체 호스팅 (v4 docker-compose, 2026-09 기준)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user