You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

apollo-server-express如何在Apollo自省Playground中启用链路追踪

Apollo Server Express 链路追踪实现方案

问题根因说明

  • 你遇到的Playground耗时显示错误,核心原因是Apollo官方定义的tracing扩展中duration字段要求单位为纳秒,你当前代码传的是毫秒值,所以展示数值会异常
  • 你留空的resolvers数组是Playground展示单字段耗时的依赖字段,需要填充对应解析器的执行数据才能展示完整链路信息

推荐开发环境轻量追踪方案

开发阶段不需要手动实现完整链路插件,直接使用官方内置的追踪插件即可,配置成本极低:

  1. 安装依赖:
npm install apollo-server-plugin-tracing
  1. 在ApolloServer配置中引入插件即可:
import { ApolloServerPluginTracing } from 'apollo-server-plugin-tracing';

const server = new ApolloServer({
  // 其余配置省略
  plugins: [
    // 开发环境启用,生产环境可注释关闭
    process.env.NODE_ENV === 'development' && ApolloServerPluginTracing(),
    // 你原来的Sentry插件可以保留,两者不冲突
    sentryPlugin
  ].filter(Boolean)
})

启用后Playground会自动展示全链路耗时、每个Resolver的执行时间,完全满足轻量调试需求。

现有自定义插件修复方案

如果你需要保留自定义实现逻辑,可以按以下方式修改原有代码:

/**
 * 修复后的链路追踪+Sentry集成插件
 * */
import {
  ApolloServerPlugin,
  GraphQLFieldResolverParams,
  GraphQLRequestContextWillSendResponse,
  GraphQLRequestListener,
} from 'apollo-server-plugin-base';

import {Context} from '../models';

const sentryPlugin: ApolloServerPlugin<Context> = {
  async requestDidStart({
    request,
    context,
  }): Promise<GraphQLRequestListener<Context>> {
    const startTime = Date.now();
    // 存储所有resolver的执行数据
    const resolverTraces = [];
    if (request.operationName)
      context.sentryTransaction.setName(request.operationName!);

    return {
      async executionDidStart() {
        return {
          willResolveField(
            reqContext: GraphQLFieldResolverParams<any, Context>
          ) {
            const resolverStartTime = Date.now();
            // hook for each new resolver
            const span = reqContext.context.sentryTransaction.startChild({
              op: 'resolver',
              description: `${reqContext.info.parentType.name}.${reqContext.info.fieldName}`,
            });
            
            return () => {
              // resolver执行结束后记录数据
              const resolverEndTime = Date.now();
              resolverTraces.push({
                path: reqContext.info.path,
                parentType: reqContext.info.parentType.name,
                fieldName: reqContext.info.fieldName,
                returnType: reqContext.info.returnType.toString(),
                startOffset: (resolverStartTime - startTime) * 1000000, // 转纳秒
                duration: (resolverEndTime - resolverStartTime) * 1000000, // 转纳秒
              })
              span.finish();
            };
          },
        };
      },
      async willSendResponse(
        requestContext: GraphQLRequestContextWillSendResponse<Context>
      ) {
        const endTime = Date.now();
        requestContext.response.extensions = {
          ...requestContext.response.extensions,
          tracing: {
            version: 1,
            startTime: new Date(startTime).toISOString(),
            endTime: new Date(endTime).toISOString(),
            duration: (endTime - startTime) * 1000000, // 毫秒转纳秒,修复显示错误
            execution: {
              resolvers: resolverTraces, // 填充收集到的resolver执行数据
            },
          },
        };

        requestContext.context.sentryTransaction.finish();
      },
    };
  },
};

export default sentryPlugin;

修复后自定义插件也可以正常在Playground显示完整的链路追踪数据。

内容的提问来源于stack exchange,提问作者Ahmed HAMEED

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 21:45:03