sentry-plugin.ts 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. import { MiddlewareConsumer, NestModule } from '@nestjs/common';
  2. import { APP_FILTER } from '@nestjs/core';
  3. import { PluginCommonModule, VendurePlugin } from '@vendure/core';
  4. import { SentryAdminTestResolver } from './api/admin-test.resolver';
  5. import { testApiExtensions } from './api/api-extensions';
  6. import { ErrorTestService } from './api/error-test.service';
  7. import { SENTRY_PLUGIN_OPTIONS } from './constants';
  8. import { SentryApolloPlugin } from './sentry-apollo-plugin';
  9. import { SentryContextMiddleware } from './sentry-context.middleware';
  10. import { SentryExceptionsFilter } from './sentry.filter';
  11. import { SentryService } from './sentry.service';
  12. import { SentryPluginOptions } from './types';
  13. const SentryOptionsProvider = {
  14. provide: SENTRY_PLUGIN_OPTIONS,
  15. useFactory: () => SentryPlugin.options,
  16. };
  17. /**
  18. * @description
  19. * This plugin integrates the [Sentry](https://sentry.io) error tracking & performance monitoring
  20. * service with your Vendure server. In addition to capturing errors, it also provides built-in
  21. * support for [tracing](https://docs.sentry.io/product/sentry-basics/concepts/tracing/) as well as
  22. * enriching your Sentry events with additional context about the request.
  23. *
  24. * ## Pre-requisites
  25. *
  26. * This plugin depends on access to Sentry, which can be self-hosted or used as a cloud service.
  27. *
  28. * If using the hosted SaaS option, you must have a Sentry account and a project set up ([sign up here](https://sentry.io/signup/)). When setting up your project,
  29. * select the "Node.js" platform and no framework.
  30. *
  31. * Once set up, you will be given a [Data Source Name (DSN)](https://docs.sentry.io/product/sentry-basics/concepts/dsn-explainer/)
  32. * which you will need to provide to the plugin.
  33. *
  34. * ## Installation
  35. *
  36. * Install this plugin as well as the `@sentry/node` package:
  37. *
  38. * ```sh
  39. * npm install --save \@vendure/sentry-plugin \@sentry/node
  40. * ```
  41. *
  42. * ## Configuration
  43. *
  44. * Before using the plugin, you must configure it with the DSN provided by Sentry:
  45. *
  46. * ```ts
  47. * import { VendureConfig } from '\@vendure/core';
  48. * import { SentryPlugin } from '\@vendure/sentry-plugin';
  49. *
  50. * export const config: VendureConfig = {
  51. * // ...
  52. * plugins: [
  53. * // ...
  54. * // highlight-start
  55. * SentryPlugin.init({
  56. * dsn: process.env.SENTRY_DSN,
  57. * // Optional configuration
  58. * includeErrorTestMutation: true,
  59. * enableTracing: true,
  60. * // you can also pass in any of the options from \@sentry/node
  61. * // for instance:
  62. * tracesSampleRate: 1.0,
  63. * }),
  64. * // highlight-end
  65. * ],
  66. * };
  67. *```
  68. *
  69. * ## Tracing
  70. *
  71. * This plugin includes built-in support for [tracing](https://docs.sentry.io/product/sentry-basics/concepts/tracing/), which allows you to see the performance of your
  72. * GraphQL resolvers in the Sentry dashboard. To enable tracing, set the `enableTracing` option to `true` as shown above.
  73. *
  74. * ## Instrumenting your own code
  75. *
  76. * You may want to add your own custom spans to your code. To do so, you can use the `Sentry` object
  77. * just as you would in any Node application. For example:
  78. *
  79. * ```ts
  80. * import * as Sentry from "\@sentry/node";
  81. *
  82. * export class MyService {
  83. * async myMethod() {
  84. * Sentry.setContext('My Custom Context,{
  85. * key: 'value',
  86. * });
  87. * }
  88. * }
  89. * ```
  90. *
  91. * ## Error test mutation
  92. *
  93. * To test whether your Sentry configuration is working correctly, you can set the `includeErrorTestMutation` option to `true`. This will add a mutation to the Admin API
  94. * which will throw an error of the type specified in the `errorType` argument. For example:
  95. *
  96. * ```graphql
  97. * mutation CreateTestError {
  98. * createTestError(errorType: DATABASE_ERROR)
  99. * }
  100. * ```
  101. *
  102. * You should then be able to see the error in your Sentry dashboard (it may take a couple of minutes to appear).
  103. *
  104. * @docsCategory core plugins/SentryPlugin
  105. */
  106. @VendurePlugin({
  107. imports: [PluginCommonModule],
  108. providers: [
  109. SentryOptionsProvider,
  110. SentryService,
  111. ErrorTestService,
  112. {
  113. provide: APP_FILTER,
  114. useClass: SentryExceptionsFilter,
  115. },
  116. ],
  117. configuration: config => {
  118. config.apiOptions.apolloServerPlugins.push(
  119. new SentryApolloPlugin({
  120. enableTracing: !!SentryPlugin.options.enableTracing,
  121. }),
  122. );
  123. return config;
  124. },
  125. adminApiExtensions: {
  126. schema: () => (SentryPlugin.options.includeErrorTestMutation ? testApiExtensions : undefined),
  127. resolvers: () => (SentryPlugin.options.includeErrorTestMutation ? [SentryAdminTestResolver] : []),
  128. },
  129. exports: [SentryService],
  130. compatibility: '^2.0.0',
  131. })
  132. export class SentryPlugin implements NestModule {
  133. static options: SentryPluginOptions = {} as any;
  134. configure(consumer: MiddlewareConsumer): any {
  135. consumer.apply(SentryContextMiddleware).forRoutes('*');
  136. }
  137. static init(options: SentryPluginOptions) {
  138. this.options = options;
  139. return this;
  140. }
  141. }