# Langfuse — 자체 호스팅 ingestion API (2026-09-22 정리) 출처: `https://cloud.langfuse.com/generated/api/openapi.yml`, `langfuse.com/self-hosting`. SDK 안 쓰고 HTTP 로 직접 쏨(오프라인 wheels 반입 줄이려고). ## v4 는 OTLP 로 (2026-09-22 로컬 실측) 옛 `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 {"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"}},…]}]}]}]} ``` ### 속성 → 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 기준) 이미지 6개: `langfuse/langfuse:4`, `langfuse/langfuse-worker:4`, `clickhouse/clickhouse-server:25.12`, `cgr.dev/chainguard/minio`, `redis:7`, `postgres:17`. web 포트 3000. 필수 env: `DATABASE_URL`, `NEXTAUTH_URL`, `NEXTAUTH_SECRET`, `SALT`, `ENCRYPTION_KEY`(hex 64자), CLICKHOUSE_*, REDIS_*, LANGFUSE_S3_*. 헤드리스 초기화(첫 기동 때 조직·프로젝트·키·관리자 자동 생성, UI 클릭 없이): `LANGFUSE_INIT_ORG_ID`, `LANGFUSE_INIT_ORG_NAME`, `LANGFUSE_INIT_PROJECT_ID`, `LANGFUSE_INIT_PROJECT_NAME`, `LANGFUSE_INIT_PROJECT_PUBLIC_KEY`(pk-lf-…), `LANGFUSE_INIT_PROJECT_SECRET_KEY`(sk-lf-…), `LANGFUSE_INIT_USER_EMAIL`, `LANGFUSE_INIT_USER_NAME`, `LANGFUSE_INIT_USER_PASSWORD`. → 우리 `deploy/langfuse/.env` 가 이걸 채우고, 같은 pk/sk 를 백엔드 `.env` 의 LANGFUSE_* 에 넣음.