feat(langfuse): add tool-level spans with input/output and trace-level I/O

Each MCP tool handler now sets:
- LANGFUSE_TRACE_OUTPUT_ATTR on tool spans (maps to top-level trace output)
- LANGFUSE_OBSERVATION_INPUT_ATTR and LANGFUSE_OBSERVATION_OUTPUT_ATTR
  for detailed child observation views

HTTP root span renamed to 'mcp_http_request' for consistency with stdio.
All attribute keys use constants from langfuse-transport.ts.
This commit is contained in:
2026-04-27 18:56:50 +05:30
parent 54bc20cb7f
commit d71726205d
3 changed files with 162 additions and 12 deletions
+42
View File
@@ -1,8 +1,50 @@
import { NodeTracerProvider } from "@opentelemetry/sdk-trace-node";
import { LangfuseSpanProcessor } from "@langfuse/otel";
/** Trace name used for HTTP transport in Langfuse. */
export const TRACE_NAME_HTTP = "ask262-http";
/** Trace name used for stdio transport in Langfuse. */
export const TRACE_NAME_STDIO = "ask262-stdio";
/** Langfuse attribute key for setting the trace name on a span. */
export const LANGFUSE_TRACE_NAME_ATTR = "langfuse.trace.name";
/** Langfuse attribute key for observation input. */
export const LANGFUSE_OBSERVATION_INPUT_ATTR = "langfuse.observation.input";
/** Langfuse attribute key for observation output. */
export const LANGFUSE_OBSERVATION_OUTPUT_ATTR = "langfuse.observation.output";
/** Langfuse attribute key for trace-level input. */
export const LANGFUSE_TRACE_INPUT_ATTR = "langfuse.trace.input";
/** Langfuse attribute key for trace-level output. */
export const LANGFUSE_TRACE_OUTPUT_ATTR = "langfuse.trace.output";
let provider: NodeTracerProvider | null = null;
/**
* Extract MCP tool call information from a JSON-RPC request body.
* Used to populate trace-level input in Langfuse.
*/
export function extractMcpToolInfo(
body: unknown,
): { method?: string; tool?: string; input?: unknown } {
if (typeof body !== "object" || body === null) return {};
const b = body as Record<string, unknown>;
const rpcMethod = b.method as string | undefined;
if (rpcMethod === "tools/call") {
const params = b.params as Record<string, unknown> | undefined;
return {
method: rpcMethod,
tool: params?.name as string | undefined,
input: params?.arguments,
};
}
return { method: rpcMethod };
}
/**
* Initialize Langfuse OTel span processor.
* Called once at server startup before any spans are created.