Langfuse Observability
Langfuse Observability
Langfuse (GitHub)은 팀이 AI 애플리케이션을 협업적으로 개발, 모니터링, 디버깅하도록 돕는 오픈소스 LLM 엔지니어링 플랫폼이에요. Langfuse는 AI SDK와 통합해 다음을 제공해요:
- 애플리케이션 trace
- 사용 패턴
- 사용자 및 모델별 비용 데이터
- 세션 재생으로 문제 디버깅
- 평가 (Evaluations)
출처: 문서
본문
설정
AI SDK v7은 콜백 기반 텔레메트리 시스템을 사용해요. Langfuse는 @langfuse/vercel-ai-sdk를 통해 이와 통합하고, LangfuseSpanProcessor가 결과 OpenTelemetry span을 Langfuse로 내보내요.
AI SDK와 Langfuse 통합 패키지를 설치해요:
npm install ai @ai-sdk/openai @langfuse/client @langfuse/vercel-ai-sdk @langfuse/tracing @langfuse/otel @opentelemetry/sdk-node
@langfuse/vercel-ai-sdk 패키지는 AI SDK v7을 대상으로 하며 Node.js 22 이상이 필요해요.
Langfuse 자격 증명은 환경 변수로 또는 LangfuseSpanProcessor 생성자에 직접 설정할 수 있어요.
Langfuse API 키를 얻으려면 Langfuse를 셀프호스팅하거나 여기에서 Langfuse Cloud에 가입할 수 있어요. Langfuse 대시보드에서 프로젝트를 만들어 secretKey와 publicKey를 얻어요.
환경 변수
LANGFUSE_SECRET_KEY="sk-lf-..."
LANGFUSE_PUBLIC_KEY="pk-lf-..."
LANGFUSE_BASE_URL="https://cloud.langfuse.com" # EU region, use "https://us.cloud.langfuse.com" for US region
생성자
import { LangfuseSpanProcessor } from '@langfuse/otel';
new LangfuseSpanProcessor({
secretKey: 'sk-lf-...',
publicKey: 'pk-lf-...',
baseUrl: 'https://cloud.langfuse.com', // EU region
// baseUrl: 'https://us.cloud.langfuse.com', // US region
});
이제 애플리케이션 시작 시 한 번 OpenTelemetry에 Langfuse span 프로세서를 등록하고 Langfuse AI SDK 텔레메트리 통합을 등록해요.
Next.js
Next.js는 프레임워크 수준에서 OpenTelemetry 계측을 지원해요. 자세한 내용은 Next.js OpenTelemetry 가이드에서 확인하세요.
instrumentation.ts 파일을 만들거나 업데이트해요:
import { registerTelemetry } from 'ai';
import { LangfuseSpanProcessor } from '@langfuse/otel';
import { LangfuseVercelAiSdkIntegration } from '@langfuse/vercel-ai-sdk';
import { NodeSDK } from '@opentelemetry/sdk-node';
export const langfuseSpanProcessor = new LangfuseSpanProcessor();
const sdk = new NodeSDK({
spanProcessors: [langfuseSpanProcessor],
});
sdk.start();
registerTelemetry(new LangfuseVercelAiSdkIntegration());
서버리스 라우트에서 응답을 스트리밍한다면, 함수가 종료되기 전에 trace가 내보내지도록 응답이 스케줄된 후 span 프로세서를 flush해요.
Node.js
OpenTelemetry 설정에 LangfuseSpanProcessor를 추가하고 AI SDK에 LangfuseVercelAiSdkIntegration을 등록해요:
import { openai } from '@ai-sdk/openai';
import { registerTelemetry, generateText } from 'ai';
import { LangfuseSpanProcessor } from '@langfuse/otel';
import { LangfuseVercelAiSdkIntegration } from '@langfuse/vercel-ai-sdk';
import { NodeSDK } from '@opentelemetry/sdk-node';
const sdk = new NodeSDK({
spanProcessors: [new LangfuseSpanProcessor()],
});
sdk.start();
registerTelemetry(new LangfuseVercelAiSdkIntegration());
async function main() {
const result = await generateText({
model: openai('gpt-5.5'),
maxOutputTokens: 50,
prompt: 'Invent a new holiday and describe its traditions.',
telemetry: {
functionId: 'my-awesome-function',
},
});
console.log(result.text);
await sdk.shutdown(); // Flushes the trace to Langfuse
}
main().catch(console.error);
끝이에요! 통합이 등록되면 AI SDK v7 호출은 기본적으로 텔레메트리를 내보내고, Langfuse는 span을 trace, generation, tool call, embedding, rerank로 매핑해요.
예시 애플리케이션
현재 설정에 대해서는 Langfuse의 Vercel AI SDK 통합 가이드를 참고하세요. Langfuse는 langfuse/langfuse-vercel-ai-nextjs-example에 샘플 저장소도 유지하고 있어요.
구성
커스텀 속성 전달
@langfuse/tracing의 propagateAttributes를 사용해 사용자, 세션, 태그, trace 메타데이터 같은 Langfuse trace 속성을 콜백 안에서 생성된 모든 observation에 첨부할 수 있어요.
import { propagateAttributes } from '@langfuse/tracing';
const result = await propagateAttributes(
{
traceName: 'story-generation',
userId: 'user-123',
sessionId: 'session-456',
tags: ['story', 'cat'],
metadata: {
route: 'api/story',
experiment: 'variant-a',
},
},
() =>
generateText({
model: openai('gpt-6-astra'),
prompt: 'Write a short story about a cat.',
telemetry: {
functionId: 'story-generation',
},
}),
);
Langfuse 메타데이터에 런타임 컨텍스트 포함
AI SDK v7은 각 최상위 키가 명시적으로 포함되지 않는 한 runtimeContext를 텔레메트리 이벤트에서 제외해요. Langfuse는 포함된 런타임 컨텍스트 키를 observation 메타데이터로 매핑해요.
const result = await generateText({
model: openai('gpt-6-astra'),
prompt: 'Write a short story about a cat.',
runtimeContext: {
route: 'api/story',
feature: 'cat-story',
},
telemetry: {
functionId: 'story-generation',
includeRuntimeContext: {
route: true,
feature: true,
},
},
});
Langfuse 프롬프트를 generation에 연결
가져온 프롬프트를 runtimeContext.langfusePrompt로 전달하고 해당 키를 텔레메트리에 포함하면, Langfuse Prompt Management 버전을 AI SDK 모델 호출 observation에 연결할 수 있어요.
import { openai } from '@ai-sdk/openai';
import { generateText } from 'ai';
import { LangfuseClient } from '@langfuse/client';
const langfuseClient = new LangfuseClient();
const langfusePrompt = await langfuseClient.getPrompt('support-chat/default');
const result = await generateText({
model: openai('gpt-6-astra'),
prompt: langfusePrompt.compile({ topic: 'RAG' }),
runtimeContext: {
route: 'support-chat',
langfusePrompt,
},
telemetry: {
functionId: 'support-chat',
includeRuntimeContext: {
route: true,
langfusePrompt: true,
},
},
});
Langfuse는 포함된 런타임 컨텍스트 키를 observation 메타데이터로 매핑하며, langfusePrompt는 프롬프트 연결에 사용되므로 제외해요. Langfuse의 프롬프트에 대해 더 알아보려면 여기를 참고하세요.
하나의 trace에 여러 실행 그룹화
활성 Langfuse observation을 만들고 그 안에서 여러 AI SDK 호출을 실행해요. AI SDK observation은 활성 observation의 자식이 돼요.
import { propagateAttributes, startActiveObservation } from '@langfuse/tracing';
await startActiveObservation('holiday-traditions', async () => {
await propagateAttributes(
{
traceName: 'holiday-traditions',
userId: 'user-123',
sessionId: 'session-456',
tags: ['holiday-generator'],
},
async () => {
for (let i = 0; i < 3; i++) {
const result = await generateText({
model: openai('gpt-5.5'),
maxOutputTokens: 50,
prompt: 'Invent a new holiday and describe its traditions.',
telemetry: {
functionId: `holiday-tradition-${i}`,
},
});
console.log(result.text);
}
},
);
});
await sdk.shutdown();
결과 trace 계층 구조는 다음과 같아요:

입력/출력 추적 비활성화
기본적으로 exporter는 각 요청의 입력과 출력을 캡처해요. recordInputs와 recordOutputs 옵션을 false로 설정해 이 동작을 비활성화할 수 있어요.
const result = await generateText({
model: openai('gpt-6-astra'),
prompt: 'Write a short story about a cat.',
telemetry: {
recordInputs: false,
recordOutputs: false,
},
});
단일 호출에 대한 텔레메트리 비활성화
텔레메트리 통합이 등록되면 기본적으로 텔레메트리가 활성화돼요. 단일 AI SDK 호출에 대해 옵트아웃할 수 있어요:
const result = await generateText({
model: openai('gpt-6-astra'),
prompt: 'Write a short story about a cat.',
telemetry: {
isEnabled: false,
},
});
문제 해결
- 애플리케이션이 Node.js 22 이상인지 확인해요.
- 최신 AI SDK 패키지를 사용하고
@langfuse/vercel-ai-sdk를 설치해요; runtimeContext값이 Langfuse에 없으면 각 최상위 키를telemetry.includeRuntimeContext에 추가해요.- Next.js에서는 instrumentation 파일이 하나만 있는지 확인해요.
- Sentry를 사용한다면 다음 중 하나를 수행해야 해요:
- Sentry.init에서
skipOpenTelemetrySetup: true설정 - Sentry를 OTEL과 수동으로 설정하는 방법에 대한 Sentry 문서 따르기
- Sentry.init에서
더 알아보기
- AI SDK용 Langfuse Tracing을 설정한 후에는 다른 Langfuse 플랫폼 기능을 활용할 수 있어요:
- Prompt Management: 프롬프트를 협업적으로 관리·반복하고, 프로덕션에서 저지연으로 사용.
- Evaluations: 사용자 피드백, LLM-as-a-judge 평가자, 수동 검토 또는 커스텀 평가 파이프라인으로 개발·프로덕션에서 애플리케이션을 전반적으로 테스트.
- Experiments: 데이터셋과 평가로 프롬프트, 모델, 애플리케이션 설계를 구조적으로 반복.
- Langfuse의 AI SDK v7 통합에 대한 자세한 내용은 Langfuse Vercel AI SDK 통합 가이드를 참고하세요.
- 더 자세한 내용은 AI SDK의 텔레메트리 문서를 참고하세요.
더 알아보기 (Learn more)
- 출처 문서: Langfuse Observability