sentry-apollo-plugin.ts 1.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253
  1. /* eslint-disable @typescript-eslint/require-await */
  2. import { ApolloServerPlugin, GraphQLRequestListener, GraphQLRequestContext } from '@apollo/server';
  3. import { Transaction, setContext } from '@sentry/node';
  4. import { SENTRY_TRANSACTION_KEY } from './constants';
  5. /**
  6. * Based on https://github.com/ntegral/nestjs-sentry/issues/97#issuecomment-1252446807
  7. */
  8. export class SentryApolloPlugin implements ApolloServerPlugin {
  9. constructor(private options: { enableTracing: boolean }) {}
  10. async requestDidStart({
  11. request,
  12. contextValue,
  13. }: GraphQLRequestContext<any>): Promise<GraphQLRequestListener<any>> {
  14. const { enableTracing } = this.options;
  15. const transaction: Transaction | undefined = contextValue.req[SENTRY_TRANSACTION_KEY];
  16. if (request.operationName) {
  17. if (enableTracing) {
  18. // set the transaction Name if we have named queries
  19. transaction?.setName(request.operationName);
  20. }
  21. setContext('Graphql Request', {
  22. operation_name: request.operationName,
  23. variables: request.variables,
  24. });
  25. }
  26. return {
  27. // hook for transaction finished
  28. async willSendResponse(context) {
  29. transaction?.finish();
  30. },
  31. async executionDidStart() {
  32. return {
  33. // hook for each new resolver
  34. willResolveField({ info }) {
  35. if (enableTracing) {
  36. const span = transaction?.startChild({
  37. op: 'resolver',
  38. description: `${info.parentType.name}.${info.fieldName}`,
  39. });
  40. return () => {
  41. span?.finish();
  42. };
  43. }
  44. },
  45. };
  46. },
  47. };
  48. }
  49. }