feat(langfuse): add opt-in Langfuse observability integration

Add Langfuse as an OTel trace transport for MCP request lifecycle tracking.

Changes:
- New src/lib/langfuse-transport.ts: initializes LangfuseSpanProcessor when
  ASK262_LANGFUSE_ENABLED=true with valid credentials
- src/lib/tracing.ts: add metadata to TraceContext, propagate it to child spans,
  use startActiveSpan for proper OTel context, add setupTracing() entry point,
  add getSessionMetadata() for version/transport metadata
- src/lib/logger.ts: include TraceContext.metadata in JSON log mixin
- src/mcp-server-{http,stdio}.ts: call setupTracing() at startup, pass
  version/transport metadata through withSpan/withSpanContext
- src/lib/fireworks-embeddings.ts: wrap API calls in withSpan() with gen_ai
  attributes for Langfuse generation/cost tracking
- .env.example: add LANGFUSE_* configuration variables
- AGENTS.md: document Langfuse integration
- package.json: add @langfuse/tracing, @langfuse/otel, @opentelemetry/sdk-node
This commit is contained in:
2026-04-27 18:31:19 +05:30
parent 40b439307e
commit 627b80008e
9 changed files with 466 additions and 97 deletions
+32
View File
@@ -0,0 +1,32 @@
import { NodeTracerProvider } from "@opentelemetry/sdk-trace-node";
import { LangfuseSpanProcessor } from "@langfuse/otel";
let provider: NodeTracerProvider | null = null;
/**
* Initialize Langfuse OTel span processor.
* Called once at server startup before any spans are created.
*/
export function initializeLangfuseTransport(): void {
if (process.env.ASK262_LANGFUSE_ENABLED !== "true") return;
const publicKey = process.env.LANGFUSE_PUBLIC_KEY;
const secretKey = process.env.LANGFUSE_SECRET_KEY;
if (!publicKey || !secretKey) {
console.error(
"[LANGFUSE] Missing LANGFUSE_PUBLIC_KEY or LANGFUSE_SECRET_KEY, skipping",
);
return;
}
provider = new NodeTracerProvider({
spanProcessors: [
new LangfuseSpanProcessor({
// Export all spans, not just LLM-relevant ones
shouldExportSpan: () => true,
}),
],
});
provider.register();
}