Skip to main content
Glama
Nozomuts

Datadog MCP Server

by Nozomuts

aggregate_spans

Aggregate Datadog trace spans by attributes like service or status to analyze performance patterns and identify issues through time-series or total summaries.

Instructions

Tool for aggregating Datadog trace spans

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
filterQueryNoQuery string to search for (optional, default is '*')*
filterFromNoSearch start time (UNIX timestamp in seconds, optional, default is 15 minutes ago)
filterToNoSearch end time (UNIX timestamp in seconds, optional, default is current time)
groupByNoAttributes to group by (example: ['service', 'resource_name'])
intervalNoTime interval to group results by (optional, only used when type is timeseries)
typeNoResult type - timeseries or total (optional, default is 'timeseries')timeseries

Implementation Reference

  • Handler function for the aggregate_spans tool. Validates input using Zod schema, calls the core aggregateSpans function, formats the response with summary and Datadog link.
    export const aggregateSpansHandler = async ( parameters: z.infer<typeof aggregateSpansZodSchema> ): Promise<ToolResponse> => { const validation = aggregateSpansZodSchema.safeParse(parameters); if (!validation.success) { return createErrorResponse( `Parameter validation error: ${validation.error.message}` ); } try { // Convert to Date objects after validation const validatedParams = { ...validation.data, filterFrom: new Date(validation.data.filterFrom * 1000), filterTo: new Date(validation.data.filterTo * 1000), }; const result = await aggregateSpans(validatedParams); const formattedResult = generateSummaryText(validation.data, result); const urlText = `[View in Datadog](https://app.datadoghq.com/apm/traces?query=${encodeURIComponent( validation.data.filterQuery )}&start=${validation.data.filterFrom}&end=${ validation.data.filterTo }&viz=${ validation.data.type === "total" ? "toplist" : validation.data.type }&agg_q=${validation.data.groupBy?.join(",") || ""})`; return createSuccessResponse([formattedResult, urlText]); } catch (error: unknown) { const errorMessage = error instanceof Error ? error.message : String(error); return createErrorResponse(`Span aggregation error: ${errorMessage}`); } };
  • Zod schema defining input parameters for the aggregate_spans tool, including query filters, time range, grouping, interval, and aggregation type.
    export const aggregateSpansZodSchema = z.object({ filterQuery: z .string() .optional() .default("*") .describe("Query string to search for (optional, default is '*')"), filterFrom: z .number() .optional() .default(Date.now() / 1000 - 15 * 60) .describe( "Search start time (UNIX timestamp in seconds, optional, default is 15 minutes ago)" ), filterTo: z .number() .optional() .default(Date.now() / 1000) .describe( "Search end time (UNIX timestamp in seconds, optional, default is current time)" ), groupBy: z .array( z.enum([ "service", "resource_name", "env", "status", "operation_name", "type", "@version", "@http.status_code", "@http.client_ip", "@http.url", "@http.method", "@http.host", "@http.user_agent", "@http.path_group", "@http.route", ]) ) .optional() .describe("Attributes to group by (example: ['service', 'resource_name'])"), interval: z .string() .optional() .describe( "Time interval to group results by (optional, only used when type is timeseries)" ), type: z .enum(["timeseries", "total"]) .default("timeseries") .describe( "Result type - timeseries or total (optional, default is 'timeseries')" ), });
  • src/index.ts:32-37 (registration)
    Registers the 'aggregate_spans' tool on the MCP server using the schema and handler.
    server.tool( "aggregate_spans", "Tool for aggregating Datadog trace spans", aggregateSpansZodSchema.shape, aggregateSpansHandler );
  • Core helper function that makes the Datadog API call to aggregate spans, constructs the request body, processes the response into structured buckets.
    export const aggregateSpans = async ( params: SpanAggregationParams ): Promise<SpanAggregationResult> => { try { const configuration = createConfiguration(); const spansApi = new v2.SpansApi(configuration); const { filterFrom, filterTo, filterQuery, interval, type } = params; const requestBody: v2.SpansApiAggregateSpansRequest = { body: { data: { attributes: { compute: [ { aggregation: "count", interval: interval, type: type, }, ], filter: { from: filterFrom.toISOString(), to: filterTo.toISOString(), query: filterQuery, }, groupBy: params.groupBy?.length ? params.groupBy.map((field) => ({ facet: field, limit: 10, })) : undefined, }, type: "aggregate_request", }, }, }; const response = await spansApi.aggregateSpans(requestBody); if (!response.data || response.data.length === 0) { return { buckets: [] }; } const buckets: SpanBucket[] = response.data.map((bucket) => ({ id: bucket.id || "", by: bucket.attributes?.by || {}, compute: bucket.attributes?.compute || {}, computes: bucket.attributes?.computes || {}, })); return { buckets, elapsed: response.meta?.elapsed, requestId: response.meta?.requestId, status: response.meta?.status?.toString(), warnings: response.meta?.warnings?.map((warning) => ({ code: warning.code, detail: warning.detail, title: warning.title, })), }; } catch (error: unknown) { const errorMessage = error instanceof Error ? error.message : String(error); console.error(`Error aggregating spans: ${errorMessage}`); throw new Error(`Datadog API error: ${errorMessage}`); } };

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Nozomuts/datadog-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server