get_spans_by_ids
Retrieve complete span details including payloads using span IDs from earlier queries, enabling in-depth analysis of specific requests or traces.
Instructions
Fetch specific span recordings by their IDs.
Use this tool when you have span IDs from a previous query and need the full details including payloads.
This is useful for:
Getting full details for spans found via query_spans
Examining specific requests in detail
Comparing multiple specific spans
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| observableServiceId | No | Service ID to query (required if multiple services available) | |
| ids | Yes | Span recording IDs to fetch | |
| fields | No | Specific fields to return | |
| includePayloads | No | Include inputValue/outputValue | |
| maxPayloadLength | No | Truncate payload strings |
Implementation Reference
- src/tools/getSpansByIds.ts:51-103 (handler)The main handler function handleGetSpansByIds that processes the tool request: parses input, calls the API client, formats results into markdown text with span details, and returns them as text content.
export async function handleGetSpansByIds( client: TuskDriftApiClient, args: Record<string, unknown> ): Promise<{ content: Array<{ type: "text"; text: string }> }> { const input = parseGetSpansByIdsInput(args); const result = await client.getSpansByIds(input); if (result.spans.length === 0) { return { content: [ { type: "text", text: `No spans found for the provided IDs.`, }, ], }; } const spansText = result.spans .map((span, i) => { const lines = [ `## Span ${i + 1}: ${span.name}`, `- **ID:** ${span.id}`, `- **Trace ID:** ${span.traceId}`, `- **Span ID:** ${span.spanId}`, `- **Package:** ${span.packageName}`, `- **Duration:** ${span.duration.toFixed(2)}ms`, `- **Status:** ${span.status.code === 0 ? "OK" : span.status.code === 1 ? "UNSET" : "ERROR"}`, `- **Timestamp:** ${span.timestamp}`, `- **Root Span:** ${span.isRootSpan ? "Yes" : "No"}`, ]; if (span.inputValue) { lines.push(`\n**Input:**\n\`\`\`json\n${JSON.stringify(span.inputValue, null, 2)}\n\`\`\``); } if (span.outputValue) { lines.push(`\n**Output:**\n\`\`\`json\n${JSON.stringify(span.outputValue, null, 2)}\n\`\`\``); } return lines.join("\n"); }) .join("\n\n---\n\n"); return { content: [ { type: "text", text: `Found ${result.spans.length} spans:\n\n${spansText}`, }, ], }; } - src/tools/getSpansByIds.ts:6-49 (schema)Tool definition object with name 'get_spans_by_ids', description, and inputSchema defining the Zod validation schema for parameters (observableServiceId, ids, fields, includePayloads, maxPayloadLength).
export const getSpansByIdsTool: Tool = { name: "get_spans_by_ids", description: `Fetch specific span recordings by their IDs. Use this tool when you have span IDs from a previous query and need the full details including payloads. This is useful for: - Getting full details for spans found via query_spans - Examining specific requests in detail - Comparing multiple specific spans`, inputSchema: { type: "object", properties: { observableServiceId: { type: "string", description: "Service ID to query. Required if multiple services are available.", }, ids: { type: "array", items: { type: "string" }, description: "Span recording IDs to fetch (max 20)", }, fields: { type: "array", items: { type: "string", enum: [...selectableSpanFieldCodec.names], }, description: "Optional list of fields to return", }, includePayloads: { type: "boolean", description: "Include full inputValue/outputValue", default: true, }, maxPayloadLength: { type: "number", description: "Truncate payload strings to this length", default: 500, }, }, required: ["ids"], }, }; - src/types.ts:276-282 (schema)Zod schema getSpansByIdsInputSchema defining validation for the tool's input parameters.
export const getSpansByIdsInputSchema = z.object({ observableServiceId: z.string().optional().describe("Service ID to query (required if multiple services available)"), ids: z.array(z.string()).min(1).max(20).describe("Span recording IDs to fetch"), fields: z.array(enumNameSchema(selectableSpanFieldCodec)).optional().describe("Specific fields to return"), includePayloads: z.boolean().default(true).describe("Include inputValue/outputValue"), maxPayloadLength: z.number().min(0).default(500).describe("Truncate payload strings"), }); - src/types.ts:415-424 (helper)parseGetSpansByIdsInput function that parses raw args through the Zod schema and creates a SharedGetSpansByIdsRequest protobuf message.
export function parseGetSpansByIdsInput(args: Record<string, unknown>): GetSpansByIdsInput { const input: GetSpansByIdsArgs = getSpansByIdsInputSchema.parse(args); return SharedGetSpansByIdsRequest.create({ observableServiceId: input.observableServiceId ?? "", ids: input.ids, fields: (input.fields ?? []).map((field) => selectableSpanFieldCodec.byName[field]), includePayloads: input.includePayloads, maxPayloadLength: input.maxPayloadLength, }); } - src/server.ts:466-543 (registration)Server-side registration of the tool via server.registerTool(...) with the name 'get_spans_by_ids', input schema, and an async handler with access control check and error handling.
// ============================================ // Tool: get_spans_by_ids // ============================================ server.registerTool( "get_spans_by_ids", { description: `Fetch specific span recordings by their IDs. Use this tool when you have span IDs from a previous query and need the full details including payloads. This is useful for: - Getting full details for spans found via query_spans - Examining specific requests in detail - Comparing multiple specific spans`, inputSchema: getSpansByIdsInputSchema.shape, }, async (args) => { const input = parseGetSpansByIdsInput(args); if (input.observableServiceId && !(await checkAccess(input.observableServiceId))) { return { content: [{ type: "text" as const, text: "Error: Access denied to observable service" }], isError: true, }; } try { const result = await provider.getSpansByIds(input); if (result.spans.length === 0) { return { content: [{ type: "text" as const, text: "No spans found for the provided IDs." }], }; } const spansText = result.spans .map((span, i) => { const lines = [ `## Span ${i + 1}: ${span.name}`, `- **ID:** ${span.id}`, `- **Trace ID:** ${span.traceId}`, `- **Span ID:** ${span.spanId}`, `- **Package:** ${span.packageName}`, `- **Duration:** ${span.duration?.toFixed(2) ?? "N/A"}ms`, `- **Status:** ${span.status?.code === 0 ? "OK" : span.status?.code === 1 ? "UNSET" : "ERROR"}`, `- **Timestamp:** ${span.timestamp}`, `- **Root Span:** ${span.isRootSpan ? "Yes" : "No"}`, ]; if (span.inputValue) { lines.push( `\n**Input:**\n\`\`\`json\n${JSON.stringify(span.inputValue, null, 2)}\n\`\`\`` ); } if (span.outputValue) { lines.push( `\n**Output:**\n\`\`\`json\n${JSON.stringify(span.outputValue, null, 2)}\n\`\`\`` ); } return lines.join("\n"); }) .join("\n\n---\n\n"); return { content: [ { type: "text" as const, text: `Found ${result.spans.length} spans:\n\n${spansText}` }, ], }; } catch (error) { return { content: [{ type: "text" as const, text: `Error executing get_spans_by_ids: ${error}` }], isError: true, }; } } );