sentry-plugin.ts 4.9 KB

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