Apollo graphql,如何计算 graphql 请求的参数数量并使用摩根库写入日志

问题描述 投票:0回答:1

这是我的问题:我正在尝试计算收到的参数数量,以便将它们写入访问日志中。 我使用从express、graphql 启动的apollo 服务器作为我的API 入口点,并且使用摩根库来写入访问日志。

我尝试使用 apollo 插件从 graphql 请求中检索信息。我可以从插件中找出我有多少个参数,但我无法将此信息传递给请求上下文,以便摩根库可以检索要写入的参数数量。

我制作了一个 .js 文件,总结了我想要使用 console.log 进行调试的操作

const cors = require('cors');
const express = require('express');
const morgan = require('morgan');
const { json } = require('body-parser');
const { ApolloServer } = require('@apollo/server');
const { expressMiddleware } = require('@apollo/server/express4');

morgan.token('countID', (req) => {
  console.log('req.countID', req.countID);
  if (req.countID) return req.countID;
  return '-';
});

const logger = morgan('[:date[clf]] ":method :url HTTP/:http-version" :status ":countID"', { stream: process.stdout });

const typeDefs = `#graphql
  type Query {
    hello(id: [ID!]!): String
  }
`;

const resolvers = {
  Query: {
    hello: (parent, args, context, info) => {
      const { id } = args;
      return `id: ${id.length}`;
    },
  },
};

const countIDPlugin = {
  requestDidStart() {
    return {
      executionDidStart() {
        return {
          willResolveField({ info, contextValue: resolverContext }) {
            const args = info?.fieldNodes[0]?.arguments.filter((e) => e.name.value === 'id');
            
            const countID = args[0]?.value?.values?.length

            if (!countID) { 
              return; 
            }
            
            console.log('plugin:', countID)
            resolverContext.countID = countID;
            console.log('resolverContext.countID: ', countID)
          },
        };
      },
    };
  },
};

const server = new ApolloServer({
  typeDefs,
  resolvers,
  introspection: true,
  csrfPrevention: false,
  plugins: [
    countIDPlugin,
  ],
  context: ({ req }) => ({ req }),
});

(async () => {
  const app = express();

  app.use(logger);

  app.use(cors({
    origin: '*',
    allowedHeaders: ['Content-Type', 'x-api-key'],
    method: ['GET', 'POST'],
  }));

  await server.start();

  app.use('/graphql', cors(), json(), expressMiddleware(server, {}));

  app.listen(3000, async () => {
    console.log('Server up')
  });
})();

有了这个js文件,当我启动服务器和执行graphql请求时,就会有我的日志:

Server up
plugin: 3
resolverContext.countID:  3
req.countID undefined
[11/Mar/2024:19:47:00 +0000] "POST /graphql HTTP/1.1" 200 "-"

我不知道通过 apollo 插件来做我想做的事情是否是正确的解决方案,我仍然对其他建议持开放态度。

提前致谢

node.js express graphql apollo
1个回答
1
投票

您可以通过以下方式向中间件添加上下文表达来做到这一点:

app.use('/graphql', cors(), json(), expressMiddleware(server, {
  context: async ({ req }) => req,
}));

在您的 willResolveField 函数中,您可以执行以下操作

contextValue.res.req.countID = countID;

这是完整和简化的代码

const cors = require('cors');
const express = require('express');
const morgan = require('morgan');
const { json } = require('body-parser');
const { ApolloServer } = require('@apollo/server');
const { expressMiddleware } = require('@apollo/server/express4');

morgan.token('countID', (req) => (req?.countID || '-'));

const logger = morgan('[:date[clf]] ":method :url HTTP/:http-version" :status ":countID"', { stream: process.stdout });

const typeDefs = `#graphql
  type Query {
    hello(id: [ID!]!): String
  }
`;

const resolvers = {
  Query: {
    hello: (parent, args, context, info) => (`id: ${context.countID}`),
  },
};

const countIDPlugin = {
  requestDidStart() {
    return {
      executionDidStart() {
        return {
          willResolveField({ args, contextValue }) {
            const countID = args?.id?.length;

            if (!countID) { return; }

            contextValue.res.req.countID = countID;
            contextValue.countID = countID;
          },
        };
      },
    };
  },
};

const server = new ApolloServer({
  typeDefs,
  resolvers,
  introspection: true,
  csrfPrevention: false,
  plugins: [
    countIDPlugin,
  ],
  context: ({ req }) => ({ req }),
});

(async () => {
  const app = express();

  app.use(logger);

  app.use(cors({
    origin: '*',
    allowedHeaders: ['Content-Type', 'x-api-key'],
    method: ['GET', 'POST'],
  }));

  await server.start();

  app.use('/graphql', cors(), json(), expressMiddleware(server, {
    context: async ({ req }) => req,
  }));

  app.listen(3000, async () => {
    console.log('Server up')
  });
})();
© www.soinside.com 2019 - 2024. All rights reserved.