sentry-plugin.ts 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. import { SentryModule } from '@sentry/nestjs/setup';
  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 { SentryErrorHandlerStrategy } from './sentry-error-handler-strategy';
  8. import { SentryService } from './sentry.service';
  9. import { SentryPluginOptions } from './types';
  10. const SentryOptionsProvider = {
  11. provide: SENTRY_PLUGIN_OPTIONS,
  12. useFactory: () => SentryPlugin.options,
  13. };
  14. /**
  15. * @description
  16. * This plugin integrates the [Sentry](https://sentry.io) error tracking & performance monitoring
  17. * service with your Vendure server. In addition to capturing errors, it also provides built-in
  18. * support for [tracing](https://docs.sentry.io/product/sentry-basics/concepts/tracing/) as well as
  19. * enriching your Sentry events with additional context about the request.
  20. *
  21. * ## Pre-requisites
  22. *
  23. * This plugin depends on access to Sentry, which can be self-hosted or used as a cloud service.
  24. *
  25. * 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,
  26. * select the "Node.js" platform and no framework.
  27. *
  28. * Once set up, you will be given a [Data Source Name (DSN)](https://docs.sentry.io/product/sentry-basics/concepts/dsn-explainer/)
  29. * which you will need to provide to the plugin.
  30. *
  31. * ## Installation
  32. *
  33. * ```sh
  34. * npm install --save \@vendure/sentry-plugin
  35. * ```
  36. *
  37. * ## Configuration
  38. *
  39. * Setting up the Sentry plugin requires two steps:
  40. *
  41. * ### Step 1: Preload the Sentry instrument file
  42. *
  43. * The Sentry SDK must be initialized before your application starts. This is done by preloading
  44. * the instrument file when starting your Vendure server:
  45. *
  46. * ```sh
  47. * node --import \@vendure/sentry-plugin/instrument ./dist/index.js
  48. * ```
  49. *
  50. * Or if using TypeScript directly with tsx:
  51. *
  52. * ```sh
  53. * tsx --import \@vendure/sentry-plugin/instrument ./src/index.ts
  54. * ```
  55. *
  56. * ### Step 2: Add the SentryPlugin to your Vendure config
  57. *
  58. * ```ts
  59. * import { VendureConfig } from '\@vendure/core';
  60. * import { SentryPlugin } from '\@vendure/sentry-plugin';
  61. *
  62. * export const config: VendureConfig = {
  63. * // ...
  64. * plugins: [
  65. * // ...
  66. * // highlight-start
  67. * SentryPlugin.init({
  68. * // Optional configuration
  69. * includeErrorTestMutation: true,
  70. * }),
  71. * // highlight-end
  72. * ],
  73. * };
  74. *```
  75. *
  76. * ## Tracing
  77. *
  78. * 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.
  79. * To enable tracing, preload the instrument file as described in [Step 1](#step-1-preload-the-sentry-instrument-file).
  80. * This make sure that the Sentry SDK is initialized before any other code is executed.
  81. *
  82. * You can also set the `tracesSampleRate` and `profilesSampleRate` options to control the sample rate for
  83. * tracing and profiling, with the following environment variables:
  84. *
  85. * - `SENTRY_TRACES_SAMPLE_RATE`
  86. * - `SENTRY_PROFILES_SAMPLE_RATE`
  87. *
  88. * The sample rate for tracing should be between 0 and 1. The sample rate for profiling should be between 0 and 1.
  89. *
  90. * By default, both are set to `undefined`, which means that tracing and profiling are disabled.
  91. *
  92. * ## Instrumenting your own code
  93. *
  94. * You may want to add your own custom spans to your code. To do so, you can use the `Sentry` object
  95. * from the `\@sentry/node` package. For example:
  96. *
  97. * ```ts
  98. * import * as Sentry from "\@sentry/node";
  99. *
  100. * export class MyService {
  101. * async myMethod() {
  102. * Sentry.setContext('My Custom Context,{
  103. * key: 'value',
  104. * });
  105. * }
  106. * }
  107. * ```
  108. *
  109. * ## Error test mutation
  110. *
  111. * 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
  112. * which will throw an error of the type specified in the `errorType` argument. For example:
  113. *
  114. * ```graphql
  115. * mutation CreateTestError {
  116. * createTestError(errorType: DATABASE_ERROR)
  117. * }
  118. * ```
  119. *
  120. * You should then be able to see the error in your Sentry dashboard (it may take a couple of minutes to appear).
  121. *
  122. * @docsCategory core plugins/SentryPlugin
  123. */
  124. @VendurePlugin({
  125. imports: [PluginCommonModule],
  126. providers: [SentryOptionsProvider, SentryService, ErrorTestService],
  127. configuration: config => {
  128. config.systemOptions.errorHandlers.push(new SentryErrorHandlerStrategy());
  129. config.plugins.push(SentryModule.forRoot());
  130. return config;
  131. },
  132. adminApiExtensions: {
  133. schema: () => (SentryPlugin.options.includeErrorTestMutation ? testApiExtensions : undefined),
  134. resolvers: () => (SentryPlugin.options.includeErrorTestMutation ? [SentryAdminTestResolver] : []),
  135. },
  136. exports: [SentryService],
  137. compatibility: '^3.0.0',
  138. })
  139. export class SentryPlugin {
  140. static options: SentryPluginOptions = {} as any;
  141. static init(options: SentryPluginOptions) {
  142. this.options = options;
  143. return this;
  144. }
  145. }