Просмотр исходного кода

feat(sentry-plugin): Migrate to @sentry/nestjs module (#3744)

BREAKING CHANGE: We have updated the underlying library used in our `@vendure/sentry-plugin` package, bringing it up to the latest version. This also impacts the way that the sentry plugin is configured - see the release notes for details.
David Höck 3 месяцев назад
Родитель
Сommit
0a60889fd0

+ 35 - 23
docs/docs/reference/core-plugins/sentry-plugin/index.md

@@ -11,7 +11,7 @@ import MemberDescription from '@site/src/components/MemberDescription';
 
 ## SentryPlugin
 
-<GenerationInfo sourceFile="packages/sentry-plugin/src/sentry-plugin.ts" sourceLine="108" packageName="@vendure/sentry-plugin" />
+<GenerationInfo sourceFile="packages/sentry-plugin/src/sentry-plugin.ts" sourceLine="127" packageName="@vendure/sentry-plugin" />
 
 This plugin integrates the [Sentry](https://sentry.io) error tracking & performance monitoring
 service with your Vendure server. In addition to capturing errors, it also provides built-in
@@ -30,15 +30,30 @@ which you will need to provide to the plugin.
 
 ## Installation
 
-Install this plugin as well as the `@sentry/node` package:
-
 ```sh
-npm install --save @vendure/sentry-plugin @sentry/node
+npm install --save @vendure/sentry-plugin
 ```
 
 ## Configuration
 
-Before using the plugin, you must configure it with the DSN provided by Sentry:
+Setting up the Sentry plugin requires two steps:
+
+### Step 1: Preload the Sentry instrument file
+
+The Sentry SDK must be initialized before your application starts. This is done by preloading
+the instrument file when starting your Vendure server:
+
+```sh
+node --import @vendure/sentry-plugin/instrument ./dist/index.js
+```
+
+Or if using TypeScript directly with tsx:
+
+```sh
+tsx --import @vendure/sentry-plugin/instrument ./src/index.ts
+```
+
+### Step 2: Add the SentryPlugin to your Vendure config
 
 ```ts
 import { VendureConfig } from '@vendure/core';
@@ -50,13 +65,8 @@ export const config: VendureConfig = {
         // ...
         // highlight-start
         SentryPlugin.init({
-            dsn: process.env.SENTRY_DSN,
             // Optional configuration
             includeErrorTestMutation: true,
-            enableTracing: true,
-            // you can also pass in any of the options from @sentry/node
-            // for instance:
-            tracesSampleRate: 1.0,
         }),
         // highlight-end
     ],
@@ -65,13 +75,24 @@ export const config: VendureConfig = {
 
 ## Tracing
 
-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
-GraphQL resolvers in the Sentry dashboard. To enable tracing, set the `enableTracing` option to `true` as shown above.
+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.
+To enable tracing, preload the instrument file as described in [Step 1](#step-1-preload-the-sentry-instrument-file).
+This make sure that the Sentry SDK is initialized before any other code is executed.
+
+You can also set the `tracesSampleRate` and `profilesSampleRate` options to control the sample rate for
+tracing and profiling, with the following environment variables:
+
+- `SENTRY_TRACES_SAMPLE_RATE`
+- `SENTRY_PROFILES_SAMPLE_RATE`
+
+The sample rate for tracing should be between 0 and 1. The sample rate for profiling should be between 0 and 1.
+
+By default, both are set to `undefined`, which means that tracing and profiling are disabled.
 
 ## Instrumenting your own code
 
 You may want to add your own custom spans to your code. To do so, you can use the `Sentry` object
-just as you would in any Node application. For example:
+from the `@sentry/node` package. For example:
 
 ```ts
 import * as Sentry from "@sentry/node";
@@ -99,15 +120,11 @@ mutation CreateTestError {
 You should then be able to see the error in your Sentry dashboard (it may take a couple of minutes to appear).
 
 ```ts title="Signature"
-class SentryPlugin implements NestModule {
+class SentryPlugin {
     static options: SentryPluginOptions = {} as any;
-    configure(consumer: MiddlewareConsumer) => any;
     init(options: SentryPluginOptions) => ;
 }
 ```
-* Implements: <code>NestModule</code>
-
-
 
 <div className="members-wrapper">
 
@@ -116,11 +133,6 @@ class SentryPlugin implements NestModule {
 <MemberInfo kind="property" type={`<a href='/reference/core-plugins/sentry-plugin/sentry-plugin-options#sentrypluginoptions'>SentryPluginOptions</a>`}   />
 
 
-### configure
-
-<MemberInfo kind="method" type={`(consumer: MiddlewareConsumer) => any`}   />
-
-
 ### init
 
 <MemberInfo kind="method" type={`(options: <a href='/reference/core-plugins/sentry-plugin/sentry-plugin-options#sentrypluginoptions'>SentryPluginOptions</a>) => `}   />

+ 4 - 19
docs/docs/reference/core-plugins/sentry-plugin/sentry-plugin-options.md

@@ -11,38 +11,23 @@ import MemberDescription from '@site/src/components/MemberDescription';
 
 ## SentryPluginOptions
 
-<GenerationInfo sourceFile="packages/sentry-plugin/src/types.ts" sourceLine="12" packageName="@vendure/sentry-plugin" />
+<GenerationInfo sourceFile="packages/sentry-plugin/src/types.ts" sourceLine="7" packageName="@vendure/sentry-plugin" />
 
 Configuration options for the <a href='/reference/core-plugins/sentry-plugin/#sentryplugin'>SentryPlugin</a>.
 
 ```ts title="Signature"
-interface SentryPluginOptions extends NodeOptions {
-    dsn: string;
-    enableTracing?: boolean;
+interface SentryPluginOptions {
     includeErrorTestMutation?: boolean;
 }
 ```
-* Extends: <code>NodeOptions</code>
-
-
 
 <div className="members-wrapper">
 
-### dsn
-
-<MemberInfo kind="property" type={`string`}   />
-
-The [Data Source Name](https://docs.sentry.io/product/sentry-basics/concepts/dsn-explainer/) for your Sentry instance.
-### enableTracing
-
-<MemberInfo kind="property" type={`boolean`}   />
-
-
 ### includeErrorTestMutation
 
-<MemberInfo kind="property" type={`boolean`}   />
-
+<MemberInfo kind="property" type={`boolean`} default={`false`}   />
 
+Whether to include the error test mutation in the admin API.
 
 
 </div>

+ 51 - 0
docs/docs/reference/core-plugins/sentry-plugin/sentry-service.md

@@ -0,0 +1,51 @@
+---
+title: "SentryService"
+isDefaultIndex: false
+generated: true
+---
+<!-- This file was generated from the Vendure source. Do not modify. Instead, re-run the "docs:build" script -->
+import MemberInfo from '@site/src/components/MemberInfo';
+import GenerationInfo from '@site/src/components/GenerationInfo';
+import MemberDescription from '@site/src/components/MemberDescription';
+
+
+## SentryService
+
+<GenerationInfo sourceFile="packages/sentry-plugin/src/sentry.service.ts" sourceLine="13" packageName="@vendure/sentry-plugin" />
+
+Service for capturing errors and messages to Sentry.
+
+```ts title="Signature"
+class SentryService {
+    constructor(options: SentryPluginOptions)
+    captureException(exception: Error) => ;
+    captureMessage(message: string, captureContext?: CaptureContext) => ;
+    startSpan(context: StartSpanOptions) => ;
+}
+```
+
+<div className="members-wrapper">
+
+### constructor
+
+<MemberInfo kind="method" type={`(options: <a href='/reference/core-plugins/sentry-plugin/sentry-plugin-options#sentrypluginoptions'>SentryPluginOptions</a>) => SentryService`}   />
+
+
+### captureException
+
+<MemberInfo kind="method" type={`(exception: Error) => `}   />
+
+
+### captureMessage
+
+<MemberInfo kind="method" type={`(message: string, captureContext?: CaptureContext) => `}   />
+
+Captures a message
+### startSpan
+
+<MemberInfo kind="method" type={`(context: StartSpanOptions) => `}   />
+
+Starts new span
+
+
+</div>

+ 6 - 7
packages/core/e2e/stock-control.e2e-spec.ts

@@ -14,22 +14,22 @@ import path from 'path';
 import { afterAll, beforeAll, describe, expect, it } from 'vitest';
 
 import { initialData } from '../../../e2e-common/e2e-initial-data';
-import { testConfig, TEST_SETUP_TIMEOUT_MS } from '../../../e2e-common/test-config';
+import { TEST_SETUP_TIMEOUT_MS, testConfig } from '../../../e2e-common/test-config';
 
 import { testSuccessfulPaymentMethod, twoStagePaymentMethod } from './fixtures/test-payment-methods';
 import { VARIANT_WITH_STOCK_FRAGMENT } from './graphql/fragments';
+import * as Codegen from './graphql/generated-e2e-admin-types';
 import {
-    CreateAddressInput,
     ErrorCode as AdminErrorCode,
+    CreateAddressInput,
     FulfillmentFragment,
     GlobalFlag,
     StockMovementType,
     UpdateProductVariantInput,
     VariantWithStockFragment,
 } from './graphql/generated-e2e-admin-types';
-import * as Codegen from './graphql/generated-e2e-admin-types';
-import { ErrorCode, PaymentInput } from './graphql/generated-e2e-shop-types';
 import * as CodegenShop from './graphql/generated-e2e-shop-types';
+import { ErrorCode, PaymentInput } from './graphql/generated-e2e-shop-types';
 import {
     CANCEL_ORDER,
     CREATE_FULFILLMENT,
@@ -1243,9 +1243,8 @@ describe('Stock control', () => {
 
                 expect(add2.errorCode).toBe(ErrorCode.INSUFFICIENT_STOCK_ERROR);
 
-                const { activeOrder } = await shopClient.query<CodegenShop.GetActiveOrderQuery>(
-                    GET_ACTIVE_ORDER,
-                );
+                const { activeOrder } =
+                    await shopClient.query<CodegenShop.GetActiveOrderQuery>(GET_ACTIVE_ORDER);
                 expect(activeOrder!.lines.length).toBe(0);
             });
 

+ 4 - 2
packages/dashboard/src/lib/graphql/api.ts

@@ -4,8 +4,10 @@ import { DocumentNode, print } from 'graphql';
 import { uiConfig } from 'virtual:vendure-ui-config';
 
 const API_URL =
-    (uiConfig.api.host !== "auto" ? uiConfig.api.host : `${window.location.protocol}//${window.location.hostname}`) +
-    `:${(uiConfig.api.port !== 'auto' ? uiConfig.api.port : window.location.port)}` +
+    (uiConfig.api.host !== 'auto'
+        ? uiConfig.api.host
+        : `${window.location.protocol}//${window.location.hostname}`) +
+    `:${uiConfig.api.port !== 'auto' ? uiConfig.api.port : window.location.port}` +
     `/${uiConfig.api.adminApiPath}`;
 
 export const SELECTED_CHANNEL_TOKEN_KEY = 'vendure-selected-channel-token';

+ 32 - 0
packages/dev-server/dev-config.ts

@@ -15,6 +15,7 @@ import {
 import { DashboardPlugin } from '@vendure/dashboard/plugin';
 import { defaultEmailHandlers, EmailPlugin, FileBasedTemplateLoader } from '@vendure/email-plugin';
 import { GraphiqlPlugin } from '@vendure/graphiql-plugin';
+import { SentryPlugin } from '@vendure/sentry-plugin';
 import { TelemetryPlugin } from '@vendure/telemetry-plugin';
 import 'dotenv/config';
 import path from 'path';
@@ -113,6 +114,37 @@ export const devConfig: VendureConfig = {
             },
         }),
         ...(IS_INSTRUMENTED ? [TelemetryPlugin.init({})] : []),
+        ...(process.env.ENABLE_SENTRY === 'true' && process.env.SENTRY_DSN
+            ? [
+                  SentryPlugin.init({
+                      includeErrorTestMutation: true,
+                  }),
+              ]
+            : []),
+        // AdminUiPlugin.init({
+        //     route: 'admin',
+        //     port: 5001,
+        //     adminUiConfig: {},
+        //     // Un-comment to compile a custom admin ui
+        //     // app: compileUiExtensions({
+        //     //     outputPath: path.join(__dirname, './custom-admin-ui'),
+        //     //     extensions: [
+        //     //         {
+        //     //             id: 'ui-extensions-library',
+        //     //             extensionPath: path.join(__dirname, 'example-plugins/ui-extensions-library/ui'),
+        //     //             routes: [{ route: 'ui-library', filePath: 'routes.ts' }],
+        //     //             providers: ['providers.ts'],
+        //     //         },
+        //     //         {
+        //     //             globalStyles: path.join(
+        //     //                 __dirname,
+        //     //                 'test-plugins/with-ui-extension/ui/custom-theme.scss',
+        //     //             ),
+        //     //         },
+        //     //     ],
+        //     //     devMode: true,
+        //     // }),
+        // }),
         AdminUiPlugin.init({
             route: 'admin',
             port: 5001,

+ 1 - 0
packages/dev-server/package.json

@@ -8,6 +8,7 @@
         "populate": "node -r ts-node/register -r dotenv/config populate-dev-server.ts",
         "dev:server": "node -r ts-node/register -r dotenv/config -r tsconfig-paths/register index.ts",
         "dev:server:instrumented": "IS_INSTRUMENTED=true node -r ts-node/register -r dotenv/config -r tsconfig-paths/register -r ./instrumentation.ts index.ts",
+        "dev:server:sentry": "node -r ts-node/register -r dotenv/config -r tsconfig-paths/register -r @vendure/sentry-plugin/instrument index.ts",
         "dev:worker": "node -r ts-node/register -r dotenv/config -r tsconfig-paths/register index-worker.ts",
         "dev:worker:instrumented": "IS_INSTRUMENTED=true node -r ts-node/register -r dotenv/config -r tsconfig-paths/register -r ./instrumentation.ts index-worker.ts",
         "dev": "concurrently npm:dev:server npm:dev:worker",

+ 1 - 1
packages/sentry-plugin/index.ts

@@ -1,4 +1,4 @@
+export * from './src/constants';
 export * from './src/sentry-plugin';
 export * from './src/sentry.service';
 export * from './src/types';
-export * from './src/constants';

+ 33 - 0
packages/sentry-plugin/instrument.ts

@@ -0,0 +1,33 @@
+import * as Sentry from '@sentry/nestjs';
+import { nodeProfilingIntegration } from '@sentry/profiling-node';
+
+const SENTRY_DSN = process.env.SENTRY_DSN;
+const SENTRY_TRACES_SAMPLE_RATE = process.env.SENTRY_TRACES_SAMPLE_RATE
+    ? Number(process.env.SENTRY_TRACES_SAMPLE_RATE)
+    : undefined;
+const SENTRY_PROFILES_SAMPLE_RATE = process.env.SENTRY_PROFILES_SAMPLE_RATE
+    ? Number(process.env.SENTRY_PROFILES_SAMPLE_RATE)
+    : undefined;
+
+if (!SENTRY_DSN) {
+    throw new Error('SENTRY_DSN is not set');
+}
+
+Sentry.init({
+    dsn: SENTRY_DSN,
+    integrations: [nodeProfilingIntegration()],
+    /**
+     * @description
+     * The sample rate for tracing. Value should be between 0 and 1.
+     * By default, tracing is disabled.
+     * @default undefined
+     */
+    tracesSampleRate: SENTRY_TRACES_SAMPLE_RATE,
+    /**
+     * @description
+     * The sample rate for profiling. Value should be between 0 and 1.
+     * By default, profiling is disabled.
+     * @default undefined
+     */
+    profilesSampleRate: SENTRY_PROFILES_SAMPLE_RATE,
+});

+ 17 - 7
packages/sentry-plugin/package.json

@@ -2,11 +2,21 @@
     "name": "@vendure/sentry-plugin",
     "version": "3.4.2",
     "license": "GPL-3.0-or-later",
-    "main": "lib/index.js",
-    "types": "lib/index.d.ts",
+    "main": "dist/index.js",
+    "types": "dist/index.d.ts",
     "files": [
-        "lib/**/*"
+        "dist/**/*"
     ],
+    "exports": {
+        ".": {
+            "types": "./dist/index.d.ts",
+            "default": "./dist/index.js"
+        },
+        "./instrument": {
+            "types": "./dist/instrument.d.ts",
+            "default": "./dist/instrument.js"
+        }
+    },
     "repository": {
         "type": "git",
         "url": "https://github.com/vendure-ecommerce/vendure"
@@ -21,12 +31,12 @@
     "publishConfig": {
         "access": "public"
     },
-    "peerDependencies": {
-        "@sentry/node": "^7.106.1"
-    },
     "devDependencies": {
-        "@sentry/node": "^7.106.1",
         "@vendure/common": "3.4.2",
         "@vendure/core": "3.4.2"
+    },
+    "dependencies": {
+        "@sentry/nestjs": "^10.2.0",
+        "@sentry/profiling-node": "^10.2.0"
     }
 }

+ 5 - 1
packages/sentry-plugin/src/api/admin-test.resolver.ts

@@ -2,13 +2,17 @@ import { Args, Mutation, Resolver } from '@nestjs/graphql';
 import { Allow, Permission, UserInputError } from '@vendure/core';
 
 import { SentryService } from '../sentry.service';
+
 import { ErrorTestService } from './error-test.service';
 
 declare const a: number;
 
 @Resolver()
 export class SentryAdminTestResolver {
-    constructor(private sentryService: SentryService, private errorTestService: ErrorTestService) {}
+    constructor(
+        private sentryService: SentryService,
+        private errorTestService: ErrorTestService,
+    ) {}
 
     @Allow(Permission.SuperAdmin)
     @Mutation()

+ 0 - 53
packages/sentry-plugin/src/sentry-apollo-plugin.ts

@@ -1,53 +0,0 @@
-/* eslint-disable @typescript-eslint/require-await */
-import { ApolloServerPlugin, GraphQLRequestListener, GraphQLRequestContext } from '@apollo/server';
-import { Transaction, setContext } from '@sentry/node';
-
-import { SENTRY_TRANSACTION_KEY } from './constants';
-
-/**
- * Based on https://github.com/ntegral/nestjs-sentry/issues/97#issuecomment-1252446807
- */
-export class SentryApolloPlugin implements ApolloServerPlugin {
-    constructor(private options: { enableTracing: boolean }) {}
-
-    async requestDidStart({
-        request,
-        contextValue,
-    }: GraphQLRequestContext<any>): Promise<GraphQLRequestListener<any>> {
-        const { enableTracing } = this.options;
-        const transaction: Transaction | undefined = contextValue.req[SENTRY_TRANSACTION_KEY];
-        if (request.operationName) {
-            if (enableTracing) {
-                // set the transaction Name if we have named queries
-                transaction?.setName(request.operationName);
-            }
-            setContext('Graphql Request', {
-                operation_name: request.operationName,
-                variables: request.variables,
-            });
-        }
-
-        return {
-            // hook for transaction finished
-            async willSendResponse(context) {
-                transaction?.finish();
-            },
-            async executionDidStart() {
-                return {
-                    // hook for each new resolver
-                    willResolveField({ info }) {
-                        if (enableTracing) {
-                            const span = transaction?.startChild({
-                                op: 'resolver',
-                                description: `${info.parentType.name}.${info.fieldName}`,
-                            });
-                            return () => {
-                                span?.finish();
-                            };
-                        }
-                    },
-                };
-            },
-        };
-    }
-}

+ 0 - 25
packages/sentry-plugin/src/sentry-context.middleware.ts

@@ -1,25 +0,0 @@
-import { Inject, Injectable, NestMiddleware } from '@nestjs/common';
-import { Request, Response, NextFunction } from 'express';
-
-import { SENTRY_PLUGIN_OPTIONS, SENTRY_TRANSACTION_KEY } from './constants';
-import { SentryService } from './sentry.service';
-import { SentryPluginOptions } from './types';
-
-@Injectable()
-export class SentryContextMiddleware implements NestMiddleware {
-    constructor(
-        @Inject(SENTRY_PLUGIN_OPTIONS) private options: SentryPluginOptions,
-        private sentryService: SentryService,
-    ) {}
-
-    use(req: Request, res: Response, next: NextFunction) {
-        if (this.options.enableTracing) {
-            const transaction = this.sentryService.startTransaction({
-                op: 'resolver',
-                name: `GraphQLTransaction`,
-            });
-            req[SENTRY_TRANSACTION_KEY] = transaction;
-        }
-        next();
-    }
-}

+ 36 - 25
packages/sentry-plugin/src/sentry-plugin.ts

@@ -1,12 +1,10 @@
-import { MiddlewareConsumer, NestModule } from '@nestjs/common';
+import { SentryModule } from '@sentry/nestjs/setup';
 import { PluginCommonModule, VendurePlugin } from '@vendure/core';
 
 import { SentryAdminTestResolver } from './api/admin-test.resolver';
 import { testApiExtensions } from './api/api-extensions';
 import { ErrorTestService } from './api/error-test.service';
 import { SENTRY_PLUGIN_OPTIONS } from './constants';
-import { SentryApolloPlugin } from './sentry-apollo-plugin';
-import { SentryContextMiddleware } from './sentry-context.middleware';
 import { SentryErrorHandlerStrategy } from './sentry-error-handler-strategy';
 import { SentryService } from './sentry.service';
 import { SentryPluginOptions } from './types';
@@ -35,15 +33,30 @@ const SentryOptionsProvider = {
  *
  * ## Installation
  *
- * Install this plugin as well as the `@sentry/node` package:
- *
  * ```sh
- * npm install --save \@vendure/sentry-plugin \@sentry/node
+ * npm install --save \@vendure/sentry-plugin
  * ```
  *
  * ## Configuration
  *
- * Before using the plugin, you must configure it with the DSN provided by Sentry:
+ * Setting up the Sentry plugin requires two steps:
+ *
+ * ### Step 1: Preload the Sentry instrument file
+ *
+ * The Sentry SDK must be initialized before your application starts. This is done by preloading
+ * the instrument file when starting your Vendure server:
+ *
+ * ```sh
+ * node --import \@vendure/sentry-plugin/instrument ./dist/index.js
+ * ```
+ *
+ * Or if using TypeScript directly with tsx:
+ *
+ * ```sh
+ * tsx --import \@vendure/sentry-plugin/instrument ./src/index.ts
+ * ```
+ *
+ * ### Step 2: Add the SentryPlugin to your Vendure config
  *
  * ```ts
  * import { VendureConfig } from '\@vendure/core';
@@ -55,13 +68,8 @@ const SentryOptionsProvider = {
  *         // ...
  *         // highlight-start
  *         SentryPlugin.init({
- *             dsn: process.env.SENTRY_DSN,
  *             // Optional configuration
  *             includeErrorTestMutation: true,
- *             enableTracing: true,
- *             // you can also pass in any of the options from \@sentry/node
- *             // for instance:
- *             tracesSampleRate: 1.0,
  *         }),
  *         // highlight-end
  *     ],
@@ -70,13 +78,24 @@ const SentryOptionsProvider = {
  *
  * ## Tracing
  *
- * 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
- * GraphQL resolvers in the Sentry dashboard. To enable tracing, set the `enableTracing` option to `true` as shown above.
+ * 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.
+ * To enable tracing, preload the instrument file as described in [Step 1](#step-1-preload-the-sentry-instrument-file).
+ * This make sure that the Sentry SDK is initialized before any other code is executed.
+ *
+ * You can also set the `tracesSampleRate` and `profilesSampleRate` options to control the sample rate for
+ * tracing and profiling, with the following environment variables:
+ *
+ * - `SENTRY_TRACES_SAMPLE_RATE`
+ * - `SENTRY_PROFILES_SAMPLE_RATE`
+ *
+ * The sample rate for tracing should be between 0 and 1. The sample rate for profiling should be between 0 and 1.
+ *
+ * By default, both are set to `undefined`, which means that tracing and profiling are disabled.
  *
  * ## Instrumenting your own code
  *
  * You may want to add your own custom spans to your code. To do so, you can use the `Sentry` object
- * just as you would in any Node application. For example:
+ * from the `\@sentry/node` package. For example:
  *
  * ```ts
  * import * as Sentry from "\@sentry/node";
@@ -109,12 +128,8 @@ const SentryOptionsProvider = {
     imports: [PluginCommonModule],
     providers: [SentryOptionsProvider, SentryService, ErrorTestService],
     configuration: config => {
-        config.apiOptions.apolloServerPlugins.push(
-            new SentryApolloPlugin({
-                enableTracing: !!SentryPlugin.options.enableTracing,
-            }),
-        );
         config.systemOptions.errorHandlers.push(new SentryErrorHandlerStrategy());
+        config.plugins.push(SentryModule.forRoot());
         return config;
     },
     adminApiExtensions: {
@@ -124,13 +139,9 @@ const SentryOptionsProvider = {
     exports: [SentryService],
     compatibility: '^3.0.0',
 })
-export class SentryPlugin implements NestModule {
+export class SentryPlugin {
     static options: SentryPluginOptions = {} as any;
 
-    configure(consumer: MiddlewareConsumer): any {
-        consumer.apply(SentryContextMiddleware).forRoutes('*');
-    }
-
     static init(options: SentryPluginOptions) {
         this.options = options;
         return this;

+ 20 - 22
packages/sentry-plugin/src/sentry.service.ts

@@ -1,40 +1,38 @@
-import { Inject, Injectable, OnApplicationBootstrap, OnApplicationShutdown } from '@nestjs/common';
+import { Inject, Injectable } from '@nestjs/common';
+import { CaptureContext, StartSpanOptions } from '@sentry/core';
 import * as Sentry from '@sentry/node';
-import { CaptureContext, TransactionContext } from '@sentry/types';
 
 import { SENTRY_PLUGIN_OPTIONS } from './constants';
 import { SentryPluginOptions } from './types';
 
+/**
+ * @description
+ * Service for capturing errors and messages to Sentry.
+ * @docsCategory core plugins/SentryPlugin
+ */
 @Injectable()
-export class SentryService implements OnApplicationBootstrap, OnApplicationShutdown {
+export class SentryService {
     constructor(@Inject(SENTRY_PLUGIN_OPTIONS) private options: SentryPluginOptions) {}
 
-    onApplicationBootstrap(): any {
-        const integrations = this.options.integrations ?? [
-            new Sentry.Integrations.Http({ tracing: true }),
-            ...Sentry.autoDiscoverNodePerformanceMonitoringIntegrations(),
-        ];
-        Sentry.init({
-            ...this.options,
-            tracesSampleRate: this.options.tracesSampleRate ?? 1.0,
-            integrations,
-            dsn: this.options.dsn,
-        });
-    }
-
-    onApplicationShutdown() {
-        return Sentry.close();
-    }
-
     captureException(exception: Error) {
         Sentry.captureException(exception);
     }
 
+    /**
+     * @description
+     * Captures a message
+     * @param message - The message to capture
+     * @param captureContext - The capture context
+     */
     captureMessage(message: string, captureContext?: CaptureContext) {
         Sentry.captureMessage(message, captureContext);
     }
 
-    startTransaction(context: TransactionContext) {
-        return Sentry.startTransaction(context);
+    /**
+     * @description
+     * Starts new span
+     */
+    startSpan(context: StartSpanOptions) {
+        return Sentry.startSpanManual(context, span => span);
     }
 }

+ 3 - 15
packages/sentry-plugin/src/types.ts

@@ -1,26 +1,14 @@
-import { Transaction } from '@sentry/node';
-import { NodeOptions } from '@sentry/node/types/types';
-
-import { SENTRY_TRANSACTION_KEY } from './constants';
-
 /**
  * @description
  * Configuration options for the {@link SentryPlugin}.
  *
  * @docsCategory core plugins/SentryPlugin
  */
-export interface SentryPluginOptions extends NodeOptions {
+export interface SentryPluginOptions {
     /**
      * @description
-     * The [Data Source Name](https://docs.sentry.io/product/sentry-basics/concepts/dsn-explainer/) for your Sentry instance.
+     * Whether to include the error test mutation in the admin API.
+     * @default false
      */
-    dsn: string;
-    enableTracing?: boolean;
     includeErrorTestMutation?: boolean;
 }
-
-declare module 'express' {
-    interface Request {
-        [SENTRY_TRANSACTION_KEY]: Transaction | undefined;
-    }
-}

+ 5 - 7
packages/sentry-plugin/tsconfig.build.json

@@ -1,9 +1,7 @@
 {
-  "extends": "./tsconfig.json",
-  "compilerOptions": {
-    "outDir": "./lib"
-  },
-  "files": [
-    "./index.ts"
-  ]
+    "extends": "./tsconfig.json",
+    "compilerOptions": {
+        "outDir": "./dist"
+    },
+    "files": ["./index.ts", "./instrument.ts"]
 }