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}`);
      }
    };
Install Server

Other Tools

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