Files
claude-code/src/services/langfuse/client.ts
2026-05-05 19:36:38 +08:00

87 lines
2.6 KiB
TypeScript

import { BasicTracerProvider } from '@opentelemetry/sdk-trace-base'
import { LangfuseSpanProcessor } from '@langfuse/otel'
import type { MaskFunction } from '@langfuse/otel'
import { setLangfuseTracerProvider } from '@langfuse/tracing'
import { sanitizeGlobal } from './sanitize.js'
import { logForDebugging } from 'src/utils/debug.js'
declare const MACRO: { VERSION: string }
let processor: LangfuseSpanProcessor | null = null
let provider: BasicTracerProvider | null = null
export function isLangfuseEnabled(): boolean {
return !!(process.env.LANGFUSE_PUBLIC_KEY && process.env.LANGFUSE_SECRET_KEY)
}
export function getLangfuseProcessor(): LangfuseSpanProcessor | null {
return processor
}
export function initLangfuse(): boolean {
if (processor !== null) return true
if (!isLangfuseEnabled()) {
logForDebugging('[langfuse] No keys configured, running in no-op mode')
return false
}
try {
const maskFn: MaskFunction = ({ data }) => sanitizeGlobal(data)
processor = new LangfuseSpanProcessor({
publicKey: process.env.LANGFUSE_PUBLIC_KEY,
secretKey: process.env.LANGFUSE_SECRET_KEY,
baseUrl: process.env.LANGFUSE_BASE_URL ?? 'https://cloud.langfuse.com',
flushAt: parseInt(process.env.LANGFUSE_FLUSH_AT ?? '20', 10),
flushInterval: parseInt(process.env.LANGFUSE_FLUSH_INTERVAL ?? '10', 10),
mask: maskFn,
environment: process.env.LANGFUSE_TRACING_ENVIRONMENT ?? 'development',
release: MACRO.VERSION,
exportMode:
(process.env.LANGFUSE_EXPORT_MODE as
| 'batched'
| 'immediate'
| undefined) ?? 'batched',
timeout: parseInt(process.env.LANGFUSE_TIMEOUT ?? '5', 10),
})
provider = new BasicTracerProvider({
spanProcessors: [processor],
})
setLangfuseTracerProvider(provider)
logForDebugging('[langfuse] Initialized with LangfuseSpanProcessor')
return true
} catch (e) {
logForDebugging(`[langfuse] Init failed: ${e}`, { level: 'error' })
processor = null
provider = null
return false
}
}
export async function flushLangfuse(): Promise<void> {
try {
if (processor) {
await processor.forceFlush()
}
} catch (e) {
logForDebugging(`[langfuse] Flush error: ${e}`, { level: 'error' })
}
}
export async function shutdownLangfuse(): Promise<void> {
try {
if (processor) {
await processor.forceFlush()
await processor.shutdown()
}
processor = null
provider = null
logForDebugging('[langfuse] Shutdown complete')
} catch (e) {
logForDebugging(`[langfuse] Shutdown error: ${e}`, { level: 'error' })
}
}