Skip to content

Split View: 수집한 다음 — Langfuse 대시보드, 메트릭 API, 그리고 트레이스에 붙는 평가

✨ Learn with Quiz
|

수집한 다음 — Langfuse 대시보드, 메트릭 API, 그리고 트레이스에 붙는 평가

들어가며 — 수집은 시작이고 질문이 목적이다

여기까지 오면 데이터는 모입니다. 데이터 모델을 알고, 계측을 붙였고, 저장 계층을 이해했고, 시스템을 띄웠고, 양을 조절했습니다. 그런데 이 모든 것의 목적은 질문에 답하는 일입니다.

문제는 대시보드를 먼저 열면 답할 질문이 떠오르지 않는다는 점입니다. 그래프가 이미 그려져 있으면 그 그래프가 답하는 질문만 하게 됩니다. 답해야 할 질문을 먼저 적고, 그 질문이 어떤 측정값을 어떤 차원으로 쪼개는지 확인하는 순서로 뒤집어야 합니다.

구성과 설정 이름은 2026-08-15에 공식 문서에서 확인했습니다. Langfuse는 버전에 따라 아키텍처가 달라지므로 사용 중인 버전의 문서를 다시 확인하세요. 이 글에서 다루는 메트릭 API는 v4에서 도입된 v2 형태입니다.

대시보드가 보여 주는 세 축

메트릭 개요 문서가 정리하는 지표는 세 갈래입니다.

  • 품질입니다. 사용자 피드백, 모델 기반 채점, 사람이 개입한 표본 채점, 그리고 SDK와 API로 넣은 커스텀 score로 측정합니다. 시간, 프롬프트 버전, 모델, 사용자에 걸쳐 평가할 수 있습니다.
  • 비용과 지연입니다. 문서는 이를 사용자, 세션, 지역, 기능, 모델, 프롬프트 버전으로 나눠 볼 수 있다고 밝힙니다.
  • 볼륨입니다. 수집된 트레이스와 사용된 토큰을 기준으로 계산됩니다.

세 축이 서로를 설명한다는 점이 중요합니다. 품질이 떨어진 구간이 있다면 그 구간의 지연과 비용이 어떻게 움직였는지를 같이 봐야 원인이 좁혀집니다. 지연만 보면 모델이 느려진 것인지, 프롬프트가 길어진 것인지, 검색 단계가 늘어난 것인지 알 수 없습니다.

무엇으로 쪼개 보나

측정값보다 중요한 것이 차원입니다. 문서가 명시하는 분석 차원은 트레이스 이름, 사용자 식별자, 태그, 그리고 릴리스와 버전 번호입니다. 여기에 비용과 지연 쪽에서 언급되는 모델과 프롬프트 버전이 더해집니다.

실무에서 나오는 질문을 이 차원으로 옮겨 보면 이렇게 됩니다.

질문측정값쪼개는 차원
어느 기능이 비용을 가장 많이 쓰나비용트레이스 이름, 태그
지난 배포 이후 느려졌나지연릴리스 또는 버전
특정 모델만 실패율이 높은가실패 건수모델
헤비 유저의 비용 구조가 다른가비용, 토큰사용자 식별자
새 프롬프트가 품질을 올렸나score프롬프트 버전

여기서 1편의 이야기가 되돌아옵니다. 이 차원들은 계측 시점에 값이 들어가 있어야 존재합니다. user_id를 넣지 않았다면 사용자별 비용 질의가 애초에 불가능하고, 태그를 붙이지 않았다면 기능별 분해도 불가능합니다. 대시보드를 만들다가 막히는 대부분의 이유가 여기 있습니다.

메트릭 API — 질의를 코드로 쓰기

화면에서 클릭해 만드는 대시보드와 별개로, 지표를 프로그램으로 가져오는 경로가 있습니다. 메트릭 API 문서가 정의하는 엔드포인트는 GET /api/public/v2/metrics입니다.

질의는 하나의 객체로 표현됩니다. 문서에 나오는 필드는 다음과 같습니다.

  • view — 어떤 데이터를 볼 것인가
  • metricsmeasureaggregation 쌍의 배열
  • dimensionsfield를 갖는 배열
  • filters — 필터 조건의 배열
  • fromTimestamptoTimestamp — ISO 8601 형식의 기간
  • orderByfielddirection을 갖는 배열
  • configrow_limit을 갖는 객체이며 기본값 100, 최대 1,000

문서가 제시하는 요청 예시는 이런 모양입니다.

{
  "view": "observations",
  "metrics": [{ "measure": "totalCost", "aggregation": "sum" }],
  "dimensions": [{ "field": "providedModelName" }],
  "filters": [],
  "fromTimestamp": "2025-12-01T00:00:00Z",
  "toTimestamp": "2025-12-16T00:00:00Z",
  "orderBy": [{ "field": "sum_totalCost", "direction": "desc" }],
  "config": { "row_limit": 1000 }
}

orderBy의 필드 이름을 눈여겨보세요. 집계 함수와 측정값을 이어 붙인 형태입니다. 즉 결과 컬럼 이름이 질의 구조에서 결정됩니다.

호출은 공개 API 인증을 그대로 씁니다.

# 예시: 질의 객체를 쿼리 파라미터로 넘긴다
curl -sS -u "${LANGFUSE_PUBLIC_KEY}:${LANGFUSE_SECRET_KEY}" \
  --get "https://cloud.langfuse.com/api/public/v2/metrics" \
  --data-urlencode "query@./query.json"

정확한 파라미터 전달 형식과 사용 가능한 측정값, 차원, 집계 함수 목록은 사용 중인 버전의 API 문서에서 확인하세요. 이 목록은 버전에 따라 늘거나 이름이 바뀝니다.

v2에서 달라진 것 — traces 뷰가 없다

여기가 버전 차이가 가장 눈에 띄는 지점입니다. 문서는 v2에서 사용 가능한 뷰를 네 개로 밝힙니다. observations, scores-numeric, scores-categorical, scores-boolean입니다. 그리고 traces 뷰는 v2에서 더 이상 제공되지 않는다고 명시합니다.

이 변화는 3편에서 본 저장 형태와 정확히 맞물립니다. Langfuse는 개념적으로 하나의 observation 테이블을 두고 각 행에 trace 수준 속성의 사본을 담습니다. trace 수준 속성이 observation 행에 이미 있으니, observation 뷰 하나로 trace 축의 질문에도 답할 수 있습니다.

v3 시절 자료를 보고 만든 통합이 v4에서 깨지는 이유도 여기 있습니다. 버전 정책 문서는 v3에서 v4로 넘어오며 구형 읽기 API가 제거되고 Observations API v2와 메트릭 API v2가 도입되었다고 밝힙니다. 대시보드나 리포트 파이프라인을 API 위에 만들어 두었다면 업그레이드 계획에 이 항목을 반드시 넣어야 합니다.

그리고 3편에서 강조한 원칙이 여기서 실효를 갖습니다. 애플리케이션이 의존하는 지표는 ClickHouse를 직접 찌르지 말고 이 API로 가져오세요. 스키마는 안정적인 계약이 아니지만 공개 API는 버전 정책의 대상입니다.

score를 붙이는 흐름

품질 축은 저절로 생기지 않습니다. score를 만들어 붙여야 생깁니다. 스코어 문서가 나열하는 생성 경로는 다섯 가지입니다.

  1. LLM 심사 자동 평가자
  2. 코드 평가자 (파이썬과 타입스크립트)
  3. 화면에서 사람이 직접 채점
  4. 주석 대기열
  5. API 또는 SDK로 프로그램에서 추가

붙는 자리는 1편에서 본 네 곳입니다. trace, observation, session, 데이터셋 실행입니다. 세션 문서는 세션에 사람 평가를 주석으로 달 수 있고 세션 수준 score를 SDK나 API로 프로그램에서 추가할 수 있다고 밝힙니다. 여러 턴에 걸친 대화의 품질은 turn 하나로 판정할 수 없으니 이 축이 필요합니다.

데이터 타입 선택은 나중에 무엇을 집계할 수 있는지를 결정합니다. NUMERIC과 CATEGORICAL, BOOLEAN은 메트릭 API의 뷰 이름에 그대로 대응합니다. 반면 TEXT score는 실험, LLM 심사 평가자, 분석에서 쓸 수 없다고 문서가 명시합니다. 자유 서술을 남기고 싶다면 score의 comment 필드를 쓰고, 집계 축은 별도의 CATEGORICAL로 두는 편이 안전합니다.

score를 만드는 SDK 메서드의 정확한 이름과 인자는 사용 중인 SDK 버전의 레퍼런스에서 확인하세요. 파이썬 SDK v4와 JS/TS SDK v5가 서버 v4의 정식 지원 대상입니다.

평가자가 observation 수준으로 내려온 것

v4의 변화 중 실무에 가장 크게 영향을 주는 것이 이것입니다. 버전 정책 문서는 v3에서 v4로 넘어오며 평가자가 trace 수준에서 observation 수준으로 이동했다고 밝힙니다.

무엇이 달라지는지는 1편의 RAG 트리를 다시 보면 명확합니다. trace 수준 평가만 가능하던 시절에는 "이 답변이 좋은가"만 물을 수 있었지만, observation 수준 평가가 가능해지면 "검색이 제대로 된 문서를 가져왔는가"를 검색 단계에만 따로 물을 수 있습니다.

진단에서 큰 차이가 납니다. 최종 답변 품질만 떨어졌는데 검색 단계 score가 그대로라면 문제는 생성 쪽입니다. 검색 단계 score도 함께 떨어졌다면 인덱스나 임베딩 쪽을 봐야 합니다. 하나의 숫자로는 이 구분이 나오지 않습니다.

평가 설계 자체를 더 깊게 보고 싶다면 LLM 평가와 관측성 완전 가이드가 평가 하네스와 LLM 심사, 회귀 방지를 다룹니다.

코드 평가자를 자체 호스팅에서 켜기

코드 평가자는 사용자가 작성한 코드를 서버가 실행하는 기능이므로 자체 호스팅에서는 실행 환경을 정해 줘야 합니다. 설정 문서에 나오는 관련 변수는 다음과 같습니다.

# 실행 방식 선택
LANGFUSE_CODE_EVAL_DISPATCHER=aws-lambda          # aws-lambda 또는 insecure-local

# 워커가 실행 큐를 소비하도록 켠다 (기본 false)
QUEUE_CONSUMER_CODE_EVAL_EXECUTION_QUEUE_IS_ENABLED=true

# Lambda 함수 이름 (괄호 안이 문서 기준 기본값)
LANGFUSE_CODE_EVAL_AWS_LAMBDA_NODE_FUNCTION_NAME=code-based-eval-executor-node
LANGFUSE_CODE_EVAL_AWS_LAMBDA_PYTHON_FUNCTION_NAME=code-based-eval-executor-python

insecure-local이라는 이름 자체가 경고입니다. 문서가 제시하는 두 선택지 중 하나는 격리된 Lambda이고 다른 하나는 로컬 실행입니다. 프로덕션에서 무엇을 골라야 하는지는 이름이 이미 말하고 있습니다. 이 밖에 큐 샤드 수, 워커 동시성, 로컬 실행 타임아웃을 조절하는 변수가 각각 있습니다.

질문에서 시작하는 대시보드 설계

정리하면 설계 순서는 이렇게 됩니다.

  1. 지난 분기에 실제로 받았던 질문을 적습니다. 상상한 질문이 아니라 받았던 질문입니다.
  2. 각 질문을 측정값과 차원의 조합으로 옮깁니다. 옮겨지지 않는 질문은 계측이 부족한 것입니다.
  3. 필요한 차원이 트레이스에 들어가 있는지 확인합니다. 없으면 2편으로 돌아가 계측을 고칩니다.
  4. 그 조합을 대시보드로 만들거나 메트릭 API 질의로 씁니다.
  5. 품질 축이 필요한 질문에는 score를 붙이는 경로를 하나 고릅니다.

이 순서를 따르면 아무도 보지 않는 그래프가 줄어듭니다. 대시보드가 늘어나는데 장애 회의에서는 여전히 로그를 뒤지고 있다면, 순서가 뒤집혀 있다는 신호입니다.

마치며 — 여섯 편을 관통하는 하나의 문장

이 시리즈를 한 문장으로 줄이면 이렇게 됩니다. 나중에 던질 질문이 지금 남기는 데이터의 모양을 결정한다.

데이터 모델은 무엇을 남길 수 있는지를, 계측은 실제로 무엇을 남기는지를, 저장 계층은 그것을 어떤 질의로 꺼낼 수 있는지를, 보존과 샘플링은 얼마나 오래 남는지를 정했습니다. 마지막 편의 질의와 평가는 그 결정들의 결과를 확인하는 자리입니다.

마지막 점검은 처음과 같습니다. 답해야 할 질문 세 개를 적고, 지금 구조로 답할 수 있는지 확인하세요. 답할 수 없다면 고칠 곳은 이 글이 아니라 2편입니다.

직접 해보기

  • SLO 에러 버짓 계산기 — 품질과 지연에 목표를 걸고 한 달치 여유가 얼마나 되는지 계산해 보세요.
  • DuckDB 데이터 분석 놀이터 — 측정값과 차원의 조합을 직접 질의로 써 보면 대시보드가 무엇을 하고 있는지 보입니다.
  • 하네스 엔지니어링 RPG — 관측과 배포 판단을 게임으로 굴려 보며 어떤 지표가 실제로 결정을 바꾸는지 확인해 보세요.

시리즈

참고 자료

After You Have Collected It — Langfuse Dashboards, the Metrics API, and Scores on Traces

Opening — Collection Is the Start, Questions Are the Point

By this stage the data is arriving. You know the data model, you have instrumented, you understand the storage layer, you have stood up the system, and you have tuned the volume. But the point of all of it is answering questions.

The problem is that opening a dashboard first does not make questions occur to you. When the chart is already drawn, you only ask the question the chart answers. Flip the order: write down the question you have to answer, then work out which measure it needs and which dimension it slices by.

Component and configuration names here were verified against the official documentation on 2026-08-15. Langfuse's architecture differs by version, so re-check the docs for the version you are running. The metrics API discussed here is the v2 form introduced in v4.

The Three Axes a Dashboard Shows

The metrics overview groups the metrics into three.

  • Quality, measured through user feedback, model-based scoring, human-in-the-loop scored samples, and custom scores sent through the SDKs and API. It can be assessed across time, prompt versions, LLMs, and users.
  • Cost and latency, which the documentation says can be broken down by user, session, geography, feature, model, and prompt version.
  • Volume, calculated based on the ingested traces and tokens used.

What matters is that the three explain each other. If quality dipped over some window, you have to look at how latency and cost moved over the same window to narrow the cause. Latency alone cannot tell you whether the model got slower, the prompt got longer, or retrieval added a step.

What You Slice By

The dimensions matter more than the measures. The documentation names trace name, user ID, tags, and release and version numbers as the analysis dimensions, with model and prompt version added on the cost and latency side.

Translating real questions into those dimensions looks like this.

QuestionMeasureDimension to slice by
Which feature costs the most?CostTrace name, tags
Did we get slower after the last deploy?LatencyRelease or version
Is one model failing more than the rest?Failure countModel
Do heavy users have a different cost profile?Cost, tokensUser ID
Did the new prompt raise quality?ScorePrompt version

The first post comes back here. These dimensions only exist if the values were present at instrumentation time. Without user_id, per-user cost queries are impossible from the outset, and without tags there is no per-feature breakdown. That is why most dashboard work stalls.

The Metrics API — Writing Queries as Code

Separately from dashboards you build by clicking, there is a path for pulling metrics programmatically. The metrics API documentation defines the endpoint as GET /api/public/v2/metrics.

The query is expressed as a single object. The fields the documentation lists are:

  • view — which data to look at
  • metrics — an array of measure and aggregation pairs
  • dimensions — an array of objects carrying field
  • filters — an array of filter conditions
  • fromTimestamp and toTimestamp — the window, in ISO 8601
  • orderBy — an array with field and direction
  • config — an object with row_limit, default 100 and max 1,000

The example request the documentation gives looks like this.

{
  "view": "observations",
  "metrics": [{ "measure": "totalCost", "aggregation": "sum" }],
  "dimensions": [{ "field": "providedModelName" }],
  "filters": [],
  "fromTimestamp": "2025-12-01T00:00:00Z",
  "toTimestamp": "2025-12-16T00:00:00Z",
  "orderBy": [{ "field": "sum_totalCost", "direction": "desc" }],
  "config": { "row_limit": 1000 }
}

Note the field name inside orderBy. It is the aggregation and the measure joined together, meaning the result column names are determined by the query structure.

Calls use the ordinary public API authentication.

# Illustrative: passing the query object as a query parameter
curl -sS -u "${LANGFUSE_PUBLIC_KEY}:${LANGFUSE_SECRET_KEY}" \
  --get "https://cloud.langfuse.com/api/public/v2/metrics" \
  --data-urlencode "query@./query.json"

Check the exact parameter encoding and the list of available measures, dimensions, and aggregations in the API documentation for the version you are running. That list grows and gets renamed across versions.

What Changed in v2 — There Is No traces View

This is where the version difference is most visible. The documentation names four views available in v2: observations, scores-numeric, scores-categorical, and scores-boolean. And it states that the traces view is no longer available in v2.

That change lines up exactly with the storage shape from the third post. Langfuse conceptually keeps one observations table where each row carries a copy of the trace-level attributes. Since trace-level attributes are already on the observation row, the observations view alone can answer trace-axis questions.

It also explains why an integration built from v3-era material breaks on v4. The versioning documentation states that moving from v3 to v4 removed the legacy read APIs and introduced the Observations API v2 and the Metrics API v2. If you built a dashboard or a reporting pipeline on top of the API, that item belongs in your upgrade plan.

And the principle emphasized in the third post takes effect here. Pull the metrics your application depends on through this API rather than poking ClickHouse directly. The schema is not a stable contract, but the public API is subject to the versioning policy.

How Scores Get Attached

The quality axis does not appear by itself; you have to create scores and attach them. The scores documentation lists five creation paths.

  1. LLM-as-a-Judge automated evaluators
  2. Code evaluators, in Python and TypeScript
  3. Manual scoring in the UI
  4. Annotation queues
  5. Programmatic addition through the API or SDK

The places they attach are the four from the first post: traces, observations, sessions, and dataset runs. The sessions documentation states that sessions can be annotated with human evaluations through scores and that session-level scores can be added programmatically through the SDK or API. The quality of a multi-turn conversation cannot be judged from one turn, which is why that axis exists.

The data type you choose decides what you can aggregate later. NUMERIC, CATEGORICAL, and BOOLEAN map straight onto the metrics API view names. TEXT scores, by contrast, cannot be used in experiments, LLM-as-a-judge evaluators, or analytics, as the documentation states. If you want to keep free-form prose, use the score's comment field and keep a separate CATEGORICAL score as the aggregation axis.

Check the exact method names and arguments for creating scores in the reference for the SDK version you are running. Python SDK v4 and JS/TS SDK v5 are the generally available SDKs on server v4.

Evaluators Moving Down to Observation Level

Of the v4 changes, this one has the largest practical impact. The versioning documentation states that the move from v3 to v4 shifted evaluators from trace level to observation level.

What that changes is clearest against the RAG tree from the first post. When only trace-level evaluation existed, you could ask "is this answer good?" and nothing else. With observation-level evaluation you can ask "did retrieval fetch the right documents?" of the retrieval step alone.

That makes a real difference in diagnosis. When final answer quality drops but the retrieval score holds steady, the problem is on the generation side. When the retrieval score dropped too, look at the index or the embeddings. A single number does not give you that distinction.

If you want to go deeper on evaluation design itself, LLM Evaluation and Observability covers eval harnesses, LLM-as-judge, and regression prevention.

Enabling Code Evaluators When Self-Hosting

Code evaluators run user-authored code on the server, so self-hosting means choosing the execution environment. The relevant variables from the configuration documentation are as follows.

# choose the execution dispatcher
LANGFUSE_CODE_EVAL_DISPATCHER=aws-lambda          # aws-lambda or insecure-local

# enable the worker consumer for the execution queue (default false)
QUEUE_CONSUMER_CODE_EVAL_EXECUTION_QUEUE_IS_ENABLED=true

# Lambda function names (documented defaults shown)
LANGFUSE_CODE_EVAL_AWS_LAMBDA_NODE_FUNCTION_NAME=code-based-eval-executor-node
LANGFUSE_CODE_EVAL_AWS_LAMBDA_PYTHON_FUNCTION_NAME=code-based-eval-executor-python

The name insecure-local is itself the warning. Of the two options the documentation offers, one is an isolated Lambda and the other is local execution; the name already tells you which belongs in production. Beyond these there are separate variables for queue shard count, worker concurrency, and the local execution timeout.

Designing Dashboards From Questions

Putting it together, the design order goes like this.

  1. Write down the questions you actually received last quarter. Received, not imagined.
  2. Translate each one into a measure and dimension combination. A question that will not translate means instrumentation is missing.
  3. Confirm the required dimension is present on the trace. If it is not, go back to the second post and fix instrumentation.
  4. Turn that combination into a dashboard or a metrics API query.
  5. For questions that need the quality axis, pick one path for attaching scores.

Follow that and the number of charts nobody looks at goes down. If dashboards keep multiplying while incident reviews still involve digging through logs, that is the signal the order is inverted.

Closing — One Sentence Across Six Posts

Reduced to one sentence, this series says: the questions you will ask later determine the shape of the data you record now.

The data model settled what could be recorded, instrumentation settled what actually is, the storage layer settled which queries can retrieve it, and retention and sampling settled how long it survives. Querying and evaluation in this final post are where you see the result of all those decisions.

The last check is the same as the first. Write down three questions you have to answer and see whether your current structure can answer them. If it cannot, the place to fix is not this post but the second one.

Try It Yourself

  • SLO & Error Budget Calculator — put a target on quality and latency and calculate how much monthly headroom that buys.
  • DuckDB Data Playground — writing measure and dimension combinations as queries by hand shows you what a dashboard is really doing.
  • Harness Engineering RPG — play through observability and release decisions to see which metrics actually change a decision.

Series

References