sentry-apollo-plugin.ts 2.0 KB

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