我很惊讶我找不到执行以下操作的库或示例:
我想要一个对服务器的每个请求的简单服务器日志,其中将说明请求的查询或突变,以及完成请求所需的时间
我知道有插件和扩展框架。但我不确定保持两个回调之间的状态的最佳实践是什么:
requestDidStart
和willSendResponse
会吐出的东西:
path="createAccountMutation" service=20ms
额外的功劳是显示有效负载的大小
path="createAccountMutation" service=20ms bytes=355
很想看到打字稿中的解决方案
注意:我找到了apollo-log——但它不执行请求持续时间
谢谢!
requestDidStart
每个请求调用一次,并返回请求生命周期挂钩的映射,因此您可以初始化挂钩之间保留的任何状态。
const LogPlugin = {
requestDidStart(requestContext) {
const start = Date.now()
let op
return {
didResolveOperation (context) {
op = context.operationName
},
willSendResponse (context) {
const stop = Date.now()
const elapsed = stop - start
const size = JSON.stringify(context.response).length * 2
console.log(
`Operation ${op} completed in ${elapsed} ms and returned ${size} bytes`
)
}
}
},
}
这是 Typescript 中的
import {
ApolloServerPlugin,
} from 'apollo-server-plugin-base';
import { GraphQLRequestContext } from 'apollo-server-types';
import { GraphQLRequestListener } from 'apollo-server-plugin-base/src/index'
// https://stackoverflow.com/questions/59988906/how-do-i-write-a-apollo-server-plugin-to-log-the-request-and-its-duration
export const LogPlugin: ApolloServerPlugin = {
requestDidStart<TContext>(_: GraphQLRequestContext<TContext>): GraphQLRequestListener<TContext> {
const start = Date.now()
let op: string
return {
didResolveOperation (context) {
op = context.operationName
},
willSendResponse (context) {
const stop = Date.now()
const elapsed = stop - start
const size = JSON.stringify(context.response).length * 2
console.log(
`operataion=${op} duration=${elapsed}ms bytes=${size}`
)
}
}
},
}
所有功劳归丹尼尔·里尔登
我扩展了丹尼尔·里尔登和乔纳森的答案,使其对我有用。
ApolloServerPlugin
类型需要异步调用。也许这是因为我使用的是 ApolloClient v.3?此外,操作变量必须输入为 null
,因为它被初始化为 null。
无论如何,这是我所做的一个工作示例。我还擅自重命名了插件、操作变量、添加了错误记录器并使用
performance.now()
而不是 Date.now()
。
另请注意,
MyApolloContext
是您自己定义的上下文(至少在使用apollo-server-express
时)
import { MyModels } from './models'
import {
ApolloServerPlugin,
} from 'apollo-server-plugin-base';
import { GraphQLRequestContext } from 'apollo-server-types';
import { GraphQLRequestListener } from 'apollo-server-plugin-base/src/index'
import { performance } from 'perf_hooks'
export interface MyApolloContext {
models: MyModels
}
export const myDebugLoggerPlugin: ApolloServerPlugin = {
async requestDidStart<MyApolloContext >(
requestContext: GraphQLRequestContext<MyApolloContext >,
): Promise<GraphQLRequestListener<MyApolloContext >> {
const start = performance.now()
let operation: string | null
return {
// Apollo server lifetime methods that you can use. https://www.apollographql.com/docs/apollo-server/integrations/plugins/#responding-to-request-lifecycle-events
async didResolveOperation(context) {
operation = context.operationName
},
async willSendResponse(context) {
const elapsed = Math.round(performance.now() - start)
const size = JSON.stringify(context.response).length * 2
console.log(
`ApolloServer log: operataion=${operation} duration=${elapsed}ms bytes=${size}`,
)
},
async didEncounterErrors(context) {
console.log('Did encounter error: ', context)
},
}
},
async serverWillStart(_context) {},
}
@Emanuel,如果您不将await与async didResolveOperation(context)、async willSendResponse(context)和async didEncounterErrors(context)一起使用,它将使这些函数的执行并发,这可能会导致异常行为,因此可能不会发生超时正如预期的那样。