@deenruv/sentry-plugin 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +23 -0
- package/README.md +67 -0
- package/lib/index.d.ts +4 -0
- package/lib/index.js +21 -0
- package/lib/index.js.map +1 -0
- package/lib/src/api/admin-test.resolver.d.ts +10 -0
- package/lib/src/api/admin-test.resolver.js +57 -0
- package/lib/src/api/admin-test.resolver.js.map +1 -0
- package/lib/src/api/error-test.service.d.ts +6 -0
- package/lib/src/api/error-test.service.js +28 -0
- package/lib/src/api/error-test.service.js.map +1 -0
- package/lib/src/constants.d.ts +3 -0
- package/lib/src/constants.js +7 -0
- package/lib/src/constants.js.map +1 -0
- package/lib/src/sentry-apollo-plugin.d.ts +11 -0
- package/lib/src/sentry-apollo-plugin.js +51 -0
- package/lib/src/sentry-apollo-plugin.js.map +1 -0
- package/lib/src/sentry-context.middleware.d.ts +10 -0
- package/lib/src/sentry-context.middleware.js +41 -0
- package/lib/src/sentry-context.middleware.js.map +1 -0
- package/lib/src/sentry-error-handler-strategy.d.ts +12 -0
- package/lib/src/sentry-error-handler-strategy.js +42 -0
- package/lib/src/sentry-error-handler-strategy.js.map +1 -0
- package/lib/src/sentry-plugin.d.ts +7 -0
- package/lib/src/sentry-plugin.js +161 -0
- package/lib/src/sentry-plugin.js.map +1 -0
- package/lib/src/sentry.service.d.ts +13 -0
- package/lib/src/sentry.service.js +73 -0
- package/lib/src/sentry.service.js.map +1 -0
- package/lib/src/types.d.ts +23 -0
- package/lib/src/types.js +4 -0
- package/lib/src/types.js.map +1 -0
- package/package.json +41 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# License 1
|
|
2
|
+
|
|
3
|
+
The MIT License
|
|
4
|
+
|
|
5
|
+
Copyright (c) 2025-present Aexol
|
|
6
|
+
|
|
7
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
8
|
+
|
|
9
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
10
|
+
|
|
11
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
12
|
+
|
|
13
|
+
# License 2
|
|
14
|
+
|
|
15
|
+
The MIT License
|
|
16
|
+
|
|
17
|
+
Copyright (c) 2018-2025 Michael Bromley
|
|
18
|
+
|
|
19
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
20
|
+
|
|
21
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
22
|
+
|
|
23
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# @deenruv/sentry-plugin
|
|
2
|
+
|
|
3
|
+
Integrates your Deenruv server with [Sentry](https://sentry.io/) for error tracking, performance monitoring, and distributed tracing.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pnpm add @deenruv/sentry-plugin @sentry/node
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Configuration
|
|
12
|
+
|
|
13
|
+
```typescript
|
|
14
|
+
import { SentryPlugin } from '@deenruv/sentry-plugin';
|
|
15
|
+
|
|
16
|
+
const config = {
|
|
17
|
+
plugins: [
|
|
18
|
+
SentryPlugin.init({
|
|
19
|
+
dsn: process.env.SENTRY_DSN,
|
|
20
|
+
enableTracing: true,
|
|
21
|
+
includeErrorTestMutation: !isProduction,
|
|
22
|
+
// Any additional @sentry/node options are also supported:
|
|
23
|
+
tracesSampleRate: 1.0,
|
|
24
|
+
}),
|
|
25
|
+
],
|
|
26
|
+
};
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
**Options:**
|
|
30
|
+
|
|
31
|
+
| Option | Type | Default | Description |
|
|
32
|
+
|--------|------|---------|-------------|
|
|
33
|
+
| `dsn` | `string` | *required* | Sentry [Data Source Name](https://docs.sentry.io/product/sentry-basics/concepts/dsn-explainer/) |
|
|
34
|
+
| `enableTracing` | `boolean` | `false` | Enables performance tracing for GraphQL resolvers |
|
|
35
|
+
| `includeErrorTestMutation` | `boolean` | `false` | Adds a `createTestError` mutation to the Admin API for testing |
|
|
36
|
+
|
|
37
|
+
All additional `@sentry/node` `NodeOptions` are passed through (e.g. `tracesSampleRate`, `environment`, etc.).
|
|
38
|
+
|
|
39
|
+
## Features
|
|
40
|
+
|
|
41
|
+
- Automatic error capture via Apollo Server plugin and error handler strategy
|
|
42
|
+
- Request context enrichment via middleware (attaches user/session info to Sentry events)
|
|
43
|
+
- Built-in support for distributed tracing across GraphQL resolvers
|
|
44
|
+
- Optional `createTestError` Admin API mutation for verifying Sentry integration
|
|
45
|
+
- Compatible with Sentry's full Node.js SDK for custom instrumentation
|
|
46
|
+
|
|
47
|
+
## Admin UI
|
|
48
|
+
|
|
49
|
+
Server-only plugin. No Admin UI extensions.
|
|
50
|
+
|
|
51
|
+
## API Extensions
|
|
52
|
+
|
|
53
|
+
When `includeErrorTestMutation` is enabled, the Admin API is extended with:
|
|
54
|
+
|
|
55
|
+
```graphql
|
|
56
|
+
enum TestErrorType {
|
|
57
|
+
UNCAUGHT_ERROR
|
|
58
|
+
THROWN_ERROR
|
|
59
|
+
CAPTURED_ERROR
|
|
60
|
+
CAPTURED_MESSAGE
|
|
61
|
+
DATABASE_ERROR
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
extend type Mutation {
|
|
65
|
+
createTestError(errorType: TestErrorType!): Boolean
|
|
66
|
+
}
|
|
67
|
+
```
|
package/lib/index.d.ts
ADDED
package/lib/index.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./src/sentry-plugin"), exports);
|
|
18
|
+
__exportStar(require("./src/sentry.service"), exports);
|
|
19
|
+
__exportStar(require("./src/types"), exports);
|
|
20
|
+
__exportStar(require("./src/constants"), exports);
|
|
21
|
+
//# sourceMappingURL=index.js.map
|
package/lib/index.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,sDAAoC;AACpC,uDAAqC;AACrC,8CAA4B;AAC5B,kDAAgC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { SentryService } from "../sentry.service";
|
|
2
|
+
import { ErrorTestService } from "./error-test.service";
|
|
3
|
+
export declare class SentryAdminTestResolver {
|
|
4
|
+
private sentryService;
|
|
5
|
+
private errorTestService;
|
|
6
|
+
constructor(sentryService: SentryService, errorTestService: ErrorTestService);
|
|
7
|
+
createTestError(args: {
|
|
8
|
+
errorType: string;
|
|
9
|
+
}): Promise<number | true | undefined>;
|
|
10
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
12
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.SentryAdminTestResolver = void 0;
|
|
16
|
+
const graphql_1 = require("@nestjs/graphql");
|
|
17
|
+
const core_1 = require("@deenruv/core");
|
|
18
|
+
const sentry_service_1 = require("../sentry.service");
|
|
19
|
+
const error_test_service_1 = require("./error-test.service");
|
|
20
|
+
let SentryAdminTestResolver = class SentryAdminTestResolver {
|
|
21
|
+
constructor(sentryService, errorTestService) {
|
|
22
|
+
this.sentryService = sentryService;
|
|
23
|
+
this.errorTestService = errorTestService;
|
|
24
|
+
}
|
|
25
|
+
async createTestError(args) {
|
|
26
|
+
switch (args.errorType) {
|
|
27
|
+
case "UNCAUGHT_ERROR":
|
|
28
|
+
return a / 10;
|
|
29
|
+
case "THROWN_ERROR":
|
|
30
|
+
throw new core_1.UserInputError("SentryPlugin Test Error");
|
|
31
|
+
case "CAPTURED_ERROR":
|
|
32
|
+
this.sentryService.captureException(new Error("SentryPlugin Direct error"));
|
|
33
|
+
return true;
|
|
34
|
+
case "CAPTURED_MESSAGE":
|
|
35
|
+
this.sentryService.captureMessage("Captured message");
|
|
36
|
+
return true;
|
|
37
|
+
case "DATABASE_ERROR":
|
|
38
|
+
await this.errorTestService.createDatabaseError();
|
|
39
|
+
return true;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
exports.SentryAdminTestResolver = SentryAdminTestResolver;
|
|
44
|
+
__decorate([
|
|
45
|
+
(0, core_1.Allow)(core_1.Permission.SuperAdmin),
|
|
46
|
+
(0, graphql_1.Mutation)(),
|
|
47
|
+
__param(0, (0, graphql_1.Args)()),
|
|
48
|
+
__metadata("design:type", Function),
|
|
49
|
+
__metadata("design:paramtypes", [Object]),
|
|
50
|
+
__metadata("design:returntype", Promise)
|
|
51
|
+
], SentryAdminTestResolver.prototype, "createTestError", null);
|
|
52
|
+
exports.SentryAdminTestResolver = SentryAdminTestResolver = __decorate([
|
|
53
|
+
(0, graphql_1.Resolver)(),
|
|
54
|
+
__metadata("design:paramtypes", [sentry_service_1.SentryService,
|
|
55
|
+
error_test_service_1.ErrorTestService])
|
|
56
|
+
], SentryAdminTestResolver);
|
|
57
|
+
//# sourceMappingURL=admin-test.resolver.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"admin-test.resolver.js","sourceRoot":"","sources":["../../../src/api/admin-test.resolver.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,6CAA2D;AAC3D,wCAAkE;AAElE,sDAAkD;AAClD,6DAAwD;AAKjD,IAAM,uBAAuB,GAA7B,MAAM,uBAAuB;IAClC,YACU,aAA4B,EAC5B,gBAAkC;QADlC,kBAAa,GAAb,aAAa,CAAe;QAC5B,qBAAgB,GAAhB,gBAAgB,CAAkB;IACzC,CAAC;IAIE,AAAN,KAAK,CAAC,eAAe,CAAS,IAA2B;QACvD,QAAQ,IAAI,CAAC,SAAS,EAAE,CAAC;YACvB,KAAK,gBAAgB;gBACnB,OAAO,CAAC,GAAG,EAAE,CAAC;YAChB,KAAK,cAAc;gBACjB,MAAM,IAAI,qBAAc,CAAC,yBAAyB,CAAC,CAAC;YACtD,KAAK,gBAAgB;gBACnB,IAAI,CAAC,aAAa,CAAC,gBAAgB,CACjC,IAAI,KAAK,CAAC,2BAA2B,CAAC,CACvC,CAAC;gBACF,OAAO,IAAI,CAAC;YACd,KAAK,kBAAkB;gBACrB,IAAI,CAAC,aAAa,CAAC,cAAc,CAAC,kBAAkB,CAAC,CAAC;gBACtD,OAAO,IAAI,CAAC;YACd,KAAK,gBAAgB;gBACnB,MAAM,IAAI,CAAC,gBAAgB,CAAC,mBAAmB,EAAE,CAAC;gBAClD,OAAO,IAAI,CAAC;QAChB,CAAC;IACH,CAAC;CACF,CAAA;AA3BY,0DAAuB;AAQ5B;IAFL,IAAA,YAAK,EAAC,iBAAU,CAAC,UAAU,CAAC;IAC5B,IAAA,kBAAQ,GAAE;IACY,WAAA,IAAA,cAAI,GAAE,CAAA;;;;8DAkB5B;kCA1BU,uBAAuB;IADnC,IAAA,kBAAQ,GAAE;qCAGgB,8BAAa;QACV,qCAAgB;GAHjC,uBAAuB,CA2BnC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.ErrorTestService = void 0;
|
|
13
|
+
const common_1 = require("@nestjs/common");
|
|
14
|
+
const core_1 = require("@deenruv/core");
|
|
15
|
+
let ErrorTestService = class ErrorTestService {
|
|
16
|
+
constructor(connection) {
|
|
17
|
+
this.connection = connection;
|
|
18
|
+
}
|
|
19
|
+
createDatabaseError() {
|
|
20
|
+
return this.connection.rawConnection.query("SELECT * FROM non_existent_table");
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
exports.ErrorTestService = ErrorTestService;
|
|
24
|
+
exports.ErrorTestService = ErrorTestService = __decorate([
|
|
25
|
+
(0, common_1.Injectable)(),
|
|
26
|
+
__metadata("design:paramtypes", [core_1.TransactionalConnection])
|
|
27
|
+
], ErrorTestService);
|
|
28
|
+
//# sourceMappingURL=error-test.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error-test.service.js","sourceRoot":"","sources":["../../../src/api/error-test.service.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,2CAA4C;AAC5C,wCAAwD;AAGjD,IAAM,gBAAgB,GAAtB,MAAM,gBAAgB;IAC3B,YAAoB,UAAmC;QAAnC,eAAU,GAAV,UAAU,CAAyB;IAAG,CAAC;IAE3D,mBAAmB;QACjB,OAAO,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC,KAAK,CACxC,kCAAkC,CACnC,CAAC;IACJ,CAAC;CACF,CAAA;AARY,4CAAgB;2BAAhB,gBAAgB;IAD5B,IAAA,mBAAU,GAAE;qCAEqB,8BAAuB;GAD5C,gBAAgB,CAQ5B"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.loggerCtx = exports.SENTRY_TRANSACTION_KEY = exports.SENTRY_PLUGIN_OPTIONS = void 0;
|
|
4
|
+
exports.SENTRY_PLUGIN_OPTIONS = "SENTRY_PLUGIN_OPTIONS";
|
|
5
|
+
exports.SENTRY_TRANSACTION_KEY = "SENTRY_PLUGIN_TRANSACTION";
|
|
6
|
+
exports.loggerCtx = "SentryPlugin";
|
|
7
|
+
//# sourceMappingURL=constants.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/constants.ts"],"names":[],"mappings":";;;AAAa,QAAA,qBAAqB,GAAG,uBAAuB,CAAC;AAChD,QAAA,sBAAsB,GAAG,2BAA2B,CAAC;AACrD,QAAA,SAAS,GAAG,cAAc,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { ApolloServerPlugin, GraphQLRequestListener, GraphQLRequestContext } from "@apollo/server";
|
|
2
|
+
/**
|
|
3
|
+
* Based on https://github.com/ntegral/nestjs-sentry/issues/97#issuecomment-1252446807
|
|
4
|
+
*/
|
|
5
|
+
export declare class SentryApolloPlugin implements ApolloServerPlugin {
|
|
6
|
+
private options;
|
|
7
|
+
constructor(options: {
|
|
8
|
+
enableTracing: boolean;
|
|
9
|
+
});
|
|
10
|
+
requestDidStart({ request, contextValue, }: GraphQLRequestContext<any>): Promise<GraphQLRequestListener<any>>;
|
|
11
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SentryApolloPlugin = void 0;
|
|
4
|
+
const node_1 = require("@sentry/node");
|
|
5
|
+
const constants_1 = require("./constants");
|
|
6
|
+
/**
|
|
7
|
+
* Based on https://github.com/ntegral/nestjs-sentry/issues/97#issuecomment-1252446807
|
|
8
|
+
*/
|
|
9
|
+
class SentryApolloPlugin {
|
|
10
|
+
constructor(options) {
|
|
11
|
+
this.options = options;
|
|
12
|
+
}
|
|
13
|
+
async requestDidStart({ request, contextValue, }) {
|
|
14
|
+
const { enableTracing } = this.options;
|
|
15
|
+
const transaction = contextValue.req[constants_1.SENTRY_TRANSACTION_KEY];
|
|
16
|
+
if (request.operationName) {
|
|
17
|
+
if (enableTracing) {
|
|
18
|
+
// set the transaction Name if we have named queries
|
|
19
|
+
transaction === null || transaction === void 0 ? void 0 : transaction.setName(request.operationName);
|
|
20
|
+
}
|
|
21
|
+
(0, node_1.setContext)("Graphql Request", {
|
|
22
|
+
operation_name: request.operationName,
|
|
23
|
+
variables: request.variables,
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
return {
|
|
27
|
+
// hook for transaction finished
|
|
28
|
+
async willSendResponse(context) {
|
|
29
|
+
transaction === null || transaction === void 0 ? void 0 : transaction.finish();
|
|
30
|
+
},
|
|
31
|
+
async executionDidStart() {
|
|
32
|
+
return {
|
|
33
|
+
// hook for each new resolver
|
|
34
|
+
willResolveField({ info }) {
|
|
35
|
+
if (enableTracing) {
|
|
36
|
+
const span = transaction === null || transaction === void 0 ? void 0 : transaction.startChild({
|
|
37
|
+
op: "resolver",
|
|
38
|
+
description: `${info.parentType.name}.${info.fieldName}`,
|
|
39
|
+
});
|
|
40
|
+
return () => {
|
|
41
|
+
span === null || span === void 0 ? void 0 : span.finish();
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
};
|
|
46
|
+
},
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
exports.SentryApolloPlugin = SentryApolloPlugin;
|
|
51
|
+
//# sourceMappingURL=sentry-apollo-plugin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sentry-apollo-plugin.js","sourceRoot":"","sources":["../../src/sentry-apollo-plugin.ts"],"names":[],"mappings":";;;AAMA,uCAAuD;AAEvD,2CAAqD;AAErD;;GAEG;AACH,MAAa,kBAAkB;IAC7B,YAAoB,OAAmC;QAAnC,YAAO,GAAP,OAAO,CAA4B;IAAG,CAAC;IAE3D,KAAK,CAAC,eAAe,CAAC,EACpB,OAAO,EACP,YAAY,GACe;QAC3B,MAAM,EAAE,aAAa,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC;QACvC,MAAM,WAAW,GACf,YAAY,CAAC,GAAG,CAAC,kCAAsB,CAAC,CAAC;QAC3C,IAAI,OAAO,CAAC,aAAa,EAAE,CAAC;YAC1B,IAAI,aAAa,EAAE,CAAC;gBAClB,oDAAoD;gBACpD,WAAW,aAAX,WAAW,uBAAX,WAAW,CAAE,OAAO,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC;YAC9C,CAAC;YACD,IAAA,iBAAU,EAAC,iBAAiB,EAAE;gBAC5B,cAAc,EAAE,OAAO,CAAC,aAAa;gBACrC,SAAS,EAAE,OAAO,CAAC,SAAS;aAC7B,CAAC,CAAC;QACL,CAAC;QAED,OAAO;YACL,gCAAgC;YAChC,KAAK,CAAC,gBAAgB,CAAC,OAAO;gBAC5B,WAAW,aAAX,WAAW,uBAAX,WAAW,CAAE,MAAM,EAAE,CAAC;YACxB,CAAC;YACD,KAAK,CAAC,iBAAiB;gBACrB,OAAO;oBACL,6BAA6B;oBAC7B,gBAAgB,CAAC,EAAE,IAAI,EAAE;wBACvB,IAAI,aAAa,EAAE,CAAC;4BAClB,MAAM,IAAI,GAAG,WAAW,aAAX,WAAW,uBAAX,WAAW,CAAE,UAAU,CAAC;gCACnC,EAAE,EAAE,UAAU;gCACd,WAAW,EAAE,GAAG,IAAI,CAAC,UAAU,CAAC,IAAI,IAAI,IAAI,CAAC,SAAS,EAAE;6BACzD,CAAC,CAAC;4BACH,OAAO,GAAG,EAAE;gCACV,IAAI,aAAJ,IAAI,uBAAJ,IAAI,CAAE,MAAM,EAAE,CAAC;4BACjB,CAAC,CAAC;wBACJ,CAAC;oBACH,CAAC;iBACF,CAAC;YACJ,CAAC;SACF,CAAC;IACJ,CAAC;CACF;AA5CD,gDA4CC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { NestMiddleware } from "@nestjs/common";
|
|
2
|
+
import { Request, Response, NextFunction } from "express";
|
|
3
|
+
import { SentryService } from "./sentry.service";
|
|
4
|
+
import { SentryPluginOptions } from "./types";
|
|
5
|
+
export declare class SentryContextMiddleware implements NestMiddleware {
|
|
6
|
+
private options;
|
|
7
|
+
private sentryService;
|
|
8
|
+
constructor(options: SentryPluginOptions, sentryService: SentryService);
|
|
9
|
+
use(req: Request, res: Response, next: NextFunction): void;
|
|
10
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
12
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.SentryContextMiddleware = void 0;
|
|
16
|
+
const common_1 = require("@nestjs/common");
|
|
17
|
+
const constants_1 = require("./constants");
|
|
18
|
+
const sentry_service_1 = require("./sentry.service");
|
|
19
|
+
let SentryContextMiddleware = class SentryContextMiddleware {
|
|
20
|
+
constructor(options, sentryService) {
|
|
21
|
+
this.options = options;
|
|
22
|
+
this.sentryService = sentryService;
|
|
23
|
+
}
|
|
24
|
+
use(req, res, next) {
|
|
25
|
+
if (this.options.enableTracing) {
|
|
26
|
+
const transaction = this.sentryService.startTransaction({
|
|
27
|
+
op: "resolver",
|
|
28
|
+
name: `GraphQLTransaction`,
|
|
29
|
+
});
|
|
30
|
+
req[constants_1.SENTRY_TRANSACTION_KEY] = transaction;
|
|
31
|
+
}
|
|
32
|
+
next();
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
exports.SentryContextMiddleware = SentryContextMiddleware;
|
|
36
|
+
exports.SentryContextMiddleware = SentryContextMiddleware = __decorate([
|
|
37
|
+
(0, common_1.Injectable)(),
|
|
38
|
+
__param(0, (0, common_1.Inject)(constants_1.SENTRY_PLUGIN_OPTIONS)),
|
|
39
|
+
__metadata("design:paramtypes", [Object, sentry_service_1.SentryService])
|
|
40
|
+
], SentryContextMiddleware);
|
|
41
|
+
//# sourceMappingURL=sentry-context.middleware.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sentry-context.middleware.js","sourceRoot":"","sources":["../../src/sentry-context.middleware.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,2CAAoE;AAGpE,2CAA4E;AAC5E,qDAAiD;AAI1C,IAAM,uBAAuB,GAA7B,MAAM,uBAAuB;IAClC,YACyC,OAA4B,EAC3D,aAA4B;QADG,YAAO,GAAP,OAAO,CAAqB;QAC3D,kBAAa,GAAb,aAAa,CAAe;IACnC,CAAC;IAEJ,GAAG,CAAC,GAAY,EAAE,GAAa,EAAE,IAAkB;QACjD,IAAI,IAAI,CAAC,OAAO,CAAC,aAAa,EAAE,CAAC;YAC/B,MAAM,WAAW,GAAG,IAAI,CAAC,aAAa,CAAC,gBAAgB,CAAC;gBACtD,EAAE,EAAE,UAAU;gBACd,IAAI,EAAE,oBAAoB;aAC3B,CAAC,CAAC;YACH,GAAG,CAAC,kCAAsB,CAAC,GAAG,WAAW,CAAC;QAC5C,CAAC;QACD,IAAI,EAAE,CAAC;IACT,CAAC;CACF,CAAA;AAhBY,0DAAuB;kCAAvB,uBAAuB;IADnC,IAAA,mBAAU,GAAE;IAGR,WAAA,IAAA,eAAM,EAAC,iCAAqB,CAAC,CAAA;6CACP,8BAAa;GAH3B,uBAAuB,CAgBnC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { ArgumentsHost } from "@nestjs/common";
|
|
2
|
+
import { ErrorHandlerStrategy, Injector, Job } from "@deenruv/core";
|
|
3
|
+
export declare class SentryErrorHandlerStrategy implements ErrorHandlerStrategy {
|
|
4
|
+
private sentryService;
|
|
5
|
+
init(injector: Injector): void;
|
|
6
|
+
handleServerError(exception: Error, { host }: {
|
|
7
|
+
host: ArgumentsHost;
|
|
8
|
+
}): void;
|
|
9
|
+
handleWorkerError(exception: Error, { job }: {
|
|
10
|
+
job: Job;
|
|
11
|
+
}): void;
|
|
12
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SentryErrorHandlerStrategy = void 0;
|
|
4
|
+
const graphql_1 = require("@nestjs/graphql");
|
|
5
|
+
const node_1 = require("@sentry/node");
|
|
6
|
+
const core_1 = require("@deenruv/core");
|
|
7
|
+
const sentry_service_1 = require("./sentry.service");
|
|
8
|
+
class SentryErrorHandlerStrategy {
|
|
9
|
+
init(injector) {
|
|
10
|
+
this.sentryService = injector.get(sentry_service_1.SentryService);
|
|
11
|
+
}
|
|
12
|
+
handleServerError(exception, { host }) {
|
|
13
|
+
// We only care about errors which have at least a Warn log level
|
|
14
|
+
const shouldLogError = exception instanceof core_1.I18nError
|
|
15
|
+
? exception.logLevel <= core_1.LogLevel.Warn
|
|
16
|
+
: true;
|
|
17
|
+
if (shouldLogError) {
|
|
18
|
+
if ((host === null || host === void 0 ? void 0 : host.getType()) === "graphql") {
|
|
19
|
+
const gqlContext = graphql_1.GqlExecutionContext.create(host);
|
|
20
|
+
const info = gqlContext.getInfo();
|
|
21
|
+
(0, node_1.setContext)("GraphQL Error Context", {
|
|
22
|
+
fieldName: info.fieldName,
|
|
23
|
+
path: info.path,
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
const variables = exception.variables;
|
|
27
|
+
if (variables) {
|
|
28
|
+
(0, node_1.setContext)("GraphQL Error Variables", variables);
|
|
29
|
+
}
|
|
30
|
+
this.sentryService.captureException(exception);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
handleWorkerError(exception, { job }) {
|
|
34
|
+
(0, node_1.setContext)("Worker Context", {
|
|
35
|
+
queueName: job.queueName,
|
|
36
|
+
jobId: job.id,
|
|
37
|
+
});
|
|
38
|
+
this.sentryService.captureException(exception);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
exports.SentryErrorHandlerStrategy = SentryErrorHandlerStrategy;
|
|
42
|
+
//# sourceMappingURL=sentry-error-handler-strategy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sentry-error-handler-strategy.js","sourceRoot":"","sources":["../../src/sentry-error-handler-strategy.ts"],"names":[],"mappings":";;;AACA,6CAAsE;AACtE,uCAA0C;AAC1C,wCAMuB;AAEvB,qDAAiD;AAEjD,MAAa,0BAA0B;IAGrC,IAAI,CAAC,QAAkB;QACrB,IAAI,CAAC,aAAa,GAAG,QAAQ,CAAC,GAAG,CAAC,8BAAa,CAAC,CAAC;IACnD,CAAC;IAED,iBAAiB,CAAC,SAAgB,EAAE,EAAE,IAAI,EAA2B;QACnE,iEAAiE;QACjE,MAAM,cAAc,GAClB,SAAS,YAAY,gBAAS;YAC5B,CAAC,CAAC,SAAS,CAAC,QAAQ,IAAI,eAAQ,CAAC,IAAI;YACrC,CAAC,CAAC,IAAI,CAAC;QACX,IAAI,cAAc,EAAE,CAAC;YACnB,IAAI,CAAA,IAAI,aAAJ,IAAI,uBAAJ,IAAI,CAAE,OAAO,EAAkB,MAAK,SAAS,EAAE,CAAC;gBAClD,MAAM,UAAU,GAAG,6BAAmB,CAAC,MAAM,CAAC,IAAwB,CAAC,CAAC;gBACxE,MAAM,IAAI,GAAG,UAAU,CAAC,OAAO,EAAE,CAAC;gBAClC,IAAA,iBAAU,EAAC,uBAAuB,EAAE;oBAClC,SAAS,EAAE,IAAI,CAAC,SAAS;oBACzB,IAAI,EAAE,IAAI,CAAC,IAAI;iBAChB,CAAC,CAAC;YACL,CAAC;YACD,MAAM,SAAS,GAAI,SAAiB,CAAC,SAAS,CAAC;YAC/C,IAAI,SAAS,EAAE,CAAC;gBACd,IAAA,iBAAU,EAAC,yBAAyB,EAAE,SAAS,CAAC,CAAC;YACnD,CAAC;YACD,IAAI,CAAC,aAAa,CAAC,gBAAgB,CAAC,SAAS,CAAC,CAAC;QACjD,CAAC;IACH,CAAC;IAED,iBAAiB,CAAC,SAAgB,EAAE,EAAE,GAAG,EAAgB;QACvD,IAAA,iBAAU,EAAC,gBAAgB,EAAE;YAC3B,SAAS,EAAE,GAAG,CAAC,SAAS;YACxB,KAAK,EAAE,GAAG,CAAC,EAAE;SACd,CAAC,CAAC;QACH,IAAI,CAAC,aAAa,CAAC,gBAAgB,CAAC,SAAS,CAAC,CAAC;IACjD,CAAC;CACF;AArCD,gEAqCC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { MiddlewareConsumer, NestModule } from "@nestjs/common";
|
|
2
|
+
import { SentryPluginOptions } from "./types";
|
|
3
|
+
export declare class SentryPlugin implements NestModule {
|
|
4
|
+
static options: SentryPluginOptions;
|
|
5
|
+
configure(consumer: MiddlewareConsumer): any;
|
|
6
|
+
static init(options: SentryPluginOptions): typeof SentryPlugin;
|
|
7
|
+
}
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
9
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.SentryPlugin = void 0;
|
|
13
|
+
const core_1 = require("@deenruv/core");
|
|
14
|
+
const graphql_tag_1 = __importDefault(require("graphql-tag"));
|
|
15
|
+
const admin_test_resolver_1 = require("./api/admin-test.resolver");
|
|
16
|
+
const error_test_service_1 = require("./api/error-test.service");
|
|
17
|
+
const constants_1 = require("./constants");
|
|
18
|
+
const sentry_apollo_plugin_1 = require("./sentry-apollo-plugin");
|
|
19
|
+
const sentry_context_middleware_1 = require("./sentry-context.middleware");
|
|
20
|
+
const sentry_error_handler_strategy_1 = require("./sentry-error-handler-strategy");
|
|
21
|
+
const sentry_service_1 = require("./sentry.service");
|
|
22
|
+
const SentryOptionsProvider = {
|
|
23
|
+
provide: constants_1.SENTRY_PLUGIN_OPTIONS,
|
|
24
|
+
useFactory: () => SentryPlugin.options,
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* @description
|
|
28
|
+
* This plugin integrates the [Sentry](https://sentry.io) error tracking & performance monitoring
|
|
29
|
+
* service with your Deenruv server. In addition to capturing errors, it also provides built-in
|
|
30
|
+
* support for [tracing](https://docs.sentry.io/product/sentry-basics/concepts/tracing/) as well as
|
|
31
|
+
* enriching your Sentry events with additional context about the request.
|
|
32
|
+
*
|
|
33
|
+
* ## Pre-requisites
|
|
34
|
+
*
|
|
35
|
+
* This plugin depends on access to Sentry, which can be self-hosted or used as a cloud service.
|
|
36
|
+
*
|
|
37
|
+
* 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,
|
|
38
|
+
* select the "Node.js" platform and no framework.
|
|
39
|
+
*
|
|
40
|
+
* Once set up, you will be given a [Data Source Name (DSN)](https://docs.sentry.io/product/sentry-basics/concepts/dsn-explainer/)
|
|
41
|
+
* which you will need to provide to the plugin.
|
|
42
|
+
*
|
|
43
|
+
* ## Installation
|
|
44
|
+
*
|
|
45
|
+
* Install this plugin as well as the `@sentry/node` package:
|
|
46
|
+
*
|
|
47
|
+
* ```sh
|
|
48
|
+
* npm install --save \@deenruv/sentry-plugin \@sentry/node
|
|
49
|
+
* ```
|
|
50
|
+
*
|
|
51
|
+
* ## Configuration
|
|
52
|
+
*
|
|
53
|
+
* Before using the plugin, you must configure it with the DSN provided by Sentry:
|
|
54
|
+
*
|
|
55
|
+
* ```ts
|
|
56
|
+
* import { Deenruv } from '\@deenruv/core';
|
|
57
|
+
* import { SentryPlugin } from '\@deenruv/sentry-plugin';
|
|
58
|
+
*
|
|
59
|
+
* export const config: Deenruv = {
|
|
60
|
+
* // ...
|
|
61
|
+
* plugins: [
|
|
62
|
+
* // ...
|
|
63
|
+
* // highlight-start
|
|
64
|
+
* SentryPlugin.init({
|
|
65
|
+
* dsn: process.env.SENTRY_DSN,
|
|
66
|
+
* // Optional configuration
|
|
67
|
+
* includeErrorTestMutation: true,
|
|
68
|
+
* enableTracing: true,
|
|
69
|
+
* // you can also pass in any of the options from \@sentry/node
|
|
70
|
+
* // for instance:
|
|
71
|
+
* tracesSampleRate: 1.0,
|
|
72
|
+
* }),
|
|
73
|
+
* // highlight-end
|
|
74
|
+
* ],
|
|
75
|
+
* };
|
|
76
|
+
*```
|
|
77
|
+
*
|
|
78
|
+
* ## Tracing
|
|
79
|
+
*
|
|
80
|
+
* 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
|
|
81
|
+
* GraphQL resolvers in the Sentry dashboard. To enable tracing, set the `enableTracing` option to `true` as shown above.
|
|
82
|
+
*
|
|
83
|
+
* ## Instrumenting your own code
|
|
84
|
+
*
|
|
85
|
+
* You may want to add your own custom spans to your code. To do so, you can use the `Sentry` object
|
|
86
|
+
* just as you would in any Node application. For example:
|
|
87
|
+
*
|
|
88
|
+
* ```ts
|
|
89
|
+
* import * as Sentry from "\@sentry/node";
|
|
90
|
+
*
|
|
91
|
+
* export class MyService {
|
|
92
|
+
* async myMethod() {
|
|
93
|
+
* Sentry.setContext('My Custom Context,{
|
|
94
|
+
* key: 'value',
|
|
95
|
+
* });
|
|
96
|
+
* }
|
|
97
|
+
* }
|
|
98
|
+
* ```
|
|
99
|
+
*
|
|
100
|
+
* ## Error test mutation
|
|
101
|
+
*
|
|
102
|
+
* 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
|
|
103
|
+
* which will throw an error of the type specified in the `errorType` argument. For example:
|
|
104
|
+
*
|
|
105
|
+
* ```graphql
|
|
106
|
+
* mutation CreateTestError {
|
|
107
|
+
* createTestError(errorType: DATABASE_ERROR)
|
|
108
|
+
* }
|
|
109
|
+
* ```
|
|
110
|
+
*
|
|
111
|
+
* You should then be able to see the error in your Sentry dashboard (it may take a couple of minutes to appear).
|
|
112
|
+
*
|
|
113
|
+
* @docsCategory core plugins/SentryPlugin
|
|
114
|
+
*/
|
|
115
|
+
const testApiExtensions = (0, graphql_tag_1.default) `
|
|
116
|
+
enum TestErrorType {
|
|
117
|
+
UNCAUGHT_ERROR
|
|
118
|
+
THROWN_ERROR
|
|
119
|
+
CAPTURED_ERROR
|
|
120
|
+
CAPTURED_MESSAGE
|
|
121
|
+
DATABASE_ERROR
|
|
122
|
+
}
|
|
123
|
+
extend type Mutation {
|
|
124
|
+
createTestError(errorType: TestErrorType!): Boolean
|
|
125
|
+
}
|
|
126
|
+
`;
|
|
127
|
+
let SentryPlugin = class SentryPlugin {
|
|
128
|
+
configure(consumer) {
|
|
129
|
+
consumer.apply(sentry_context_middleware_1.SentryContextMiddleware).forRoutes("*");
|
|
130
|
+
}
|
|
131
|
+
static init(options) {
|
|
132
|
+
this.options = options;
|
|
133
|
+
return this;
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
exports.SentryPlugin = SentryPlugin;
|
|
137
|
+
SentryPlugin.options = {};
|
|
138
|
+
exports.SentryPlugin = SentryPlugin = __decorate([
|
|
139
|
+
(0, core_1.DeenruvPlugin)({
|
|
140
|
+
imports: [core_1.PluginCommonModule],
|
|
141
|
+
providers: [SentryOptionsProvider, sentry_service_1.SentryService, error_test_service_1.ErrorTestService],
|
|
142
|
+
configuration: (config) => {
|
|
143
|
+
config.apiOptions.apolloServerPlugins.push(new sentry_apollo_plugin_1.SentryApolloPlugin({
|
|
144
|
+
enableTracing: !!SentryPlugin.options.enableTracing,
|
|
145
|
+
}));
|
|
146
|
+
config.systemOptions.errorHandlers.push(new sentry_error_handler_strategy_1.SentryErrorHandlerStrategy());
|
|
147
|
+
return config;
|
|
148
|
+
},
|
|
149
|
+
adminApiExtensions: {
|
|
150
|
+
schema: () => SentryPlugin.options.includeErrorTestMutation
|
|
151
|
+
? testApiExtensions
|
|
152
|
+
: undefined,
|
|
153
|
+
resolvers: () => SentryPlugin.options.includeErrorTestMutation
|
|
154
|
+
? [admin_test_resolver_1.SentryAdminTestResolver]
|
|
155
|
+
: [],
|
|
156
|
+
},
|
|
157
|
+
exports: [sentry_service_1.SentryService],
|
|
158
|
+
compatibility: "^0.0.0",
|
|
159
|
+
})
|
|
160
|
+
], SentryPlugin);
|
|
161
|
+
//# sourceMappingURL=sentry-plugin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sentry-plugin.js","sourceRoot":"","sources":["../../src/sentry-plugin.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,wCAAkE;AAElE,8DAA8B;AAE9B,mEAAoE;AACpE,iEAA4D;AAC5D,2CAAoD;AACpD,iEAA4D;AAC5D,2EAAsE;AACtE,mFAA6E;AAC7E,qDAAiD;AAGjD,MAAM,qBAAqB,GAAG;IAC5B,OAAO,EAAE,iCAAqB;IAC9B,UAAU,EAAE,GAAG,EAAE,CAAC,YAAY,CAAC,OAAO;CACvC,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwFG;AACH,MAAM,iBAAiB,GAAG,IAAA,qBAAG,EAAA;;;;;;;;;;;CAW5B,CAAC;AA0BK,IAAM,YAAY,GAAlB,MAAM,YAAY;IAGvB,SAAS,CAAC,QAA4B;QACpC,QAAQ,CAAC,KAAK,CAAC,mDAAuB,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;IACzD,CAAC;IAED,MAAM,CAAC,IAAI,CAAC,OAA4B;QACtC,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,OAAO,IAAI,CAAC;IACd,CAAC;;AAVU,oCAAY;AAChB,oBAAO,GAAwB,EAAS,AAAjC,CAAkC;uBADrC,YAAY;IAzBxB,IAAA,oBAAa,EAAC;QACb,OAAO,EAAE,CAAC,yBAAkB,CAAC;QAC7B,SAAS,EAAE,CAAC,qBAAqB,EAAE,8BAAa,EAAE,qCAAgB,CAAC;QACnE,aAAa,EAAE,CAAC,MAAM,EAAE,EAAE;YACxB,MAAM,CAAC,UAAU,CAAC,mBAAmB,CAAC,IAAI,CACxC,IAAI,yCAAkB,CAAC;gBACrB,aAAa,EAAE,CAAC,CAAC,YAAY,CAAC,OAAO,CAAC,aAAa;aACpD,CAAC,CACH,CAAC;YACF,MAAM,CAAC,aAAa,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,0DAA0B,EAAE,CAAC,CAAC;YAC1E,OAAO,MAAM,CAAC;QAChB,CAAC;QACD,kBAAkB,EAAE;YAClB,MAAM,EAAE,GAAG,EAAE,CACX,YAAY,CAAC,OAAO,CAAC,wBAAwB;gBAC3C,CAAC,CAAC,iBAAiB;gBACnB,CAAC,CAAC,SAAS;YACf,SAAS,EAAE,GAAG,EAAE,CACd,YAAY,CAAC,OAAO,CAAC,wBAAwB;gBAC3C,CAAC,CAAC,CAAC,6CAAuB,CAAC;gBAC3B,CAAC,CAAC,EAAE;SACT;QACD,OAAO,EAAE,CAAC,8BAAa,CAAC;QACxB,aAAa,EAAE,QAAQ;KACxB,CAAC;GACW,YAAY,CAWxB"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { OnApplicationBootstrap, OnApplicationShutdown } from "@nestjs/common";
|
|
2
|
+
import * as Sentry from "@sentry/node";
|
|
3
|
+
import { CaptureContext, TransactionContext } from "@sentry/types";
|
|
4
|
+
import { SentryPluginOptions } from "./types";
|
|
5
|
+
export declare class SentryService implements OnApplicationBootstrap, OnApplicationShutdown {
|
|
6
|
+
private options;
|
|
7
|
+
constructor(options: SentryPluginOptions);
|
|
8
|
+
onApplicationBootstrap(): any;
|
|
9
|
+
onApplicationShutdown(): Promise<boolean>;
|
|
10
|
+
captureException(exception: Error): void;
|
|
11
|
+
captureMessage(message: string, captureContext?: CaptureContext): void;
|
|
12
|
+
startTransaction(context: TransactionContext): Sentry.Transaction;
|
|
13
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
19
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
20
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
21
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
22
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
23
|
+
};
|
|
24
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
25
|
+
if (mod && mod.__esModule) return mod;
|
|
26
|
+
var result = {};
|
|
27
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
28
|
+
__setModuleDefault(result, mod);
|
|
29
|
+
return result;
|
|
30
|
+
};
|
|
31
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
32
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
33
|
+
};
|
|
34
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
35
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
36
|
+
};
|
|
37
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
38
|
+
exports.SentryService = void 0;
|
|
39
|
+
const common_1 = require("@nestjs/common");
|
|
40
|
+
const Sentry = __importStar(require("@sentry/node"));
|
|
41
|
+
const constants_1 = require("./constants");
|
|
42
|
+
let SentryService = class SentryService {
|
|
43
|
+
constructor(options) {
|
|
44
|
+
this.options = options;
|
|
45
|
+
}
|
|
46
|
+
onApplicationBootstrap() {
|
|
47
|
+
var _a, _b;
|
|
48
|
+
const integrations = (_a = this.options.integrations) !== null && _a !== void 0 ? _a : [
|
|
49
|
+
new Sentry.Integrations.Http({ tracing: true }),
|
|
50
|
+
...Sentry.autoDiscoverNodePerformanceMonitoringIntegrations(),
|
|
51
|
+
];
|
|
52
|
+
Sentry.init(Object.assign(Object.assign({}, this.options), { tracesSampleRate: (_b = this.options.tracesSampleRate) !== null && _b !== void 0 ? _b : 1.0, integrations, dsn: this.options.dsn }));
|
|
53
|
+
}
|
|
54
|
+
onApplicationShutdown() {
|
|
55
|
+
return Sentry.close();
|
|
56
|
+
}
|
|
57
|
+
captureException(exception) {
|
|
58
|
+
Sentry.captureException(exception);
|
|
59
|
+
}
|
|
60
|
+
captureMessage(message, captureContext) {
|
|
61
|
+
Sentry.captureMessage(message, captureContext);
|
|
62
|
+
}
|
|
63
|
+
startTransaction(context) {
|
|
64
|
+
return Sentry.startTransaction(context);
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
exports.SentryService = SentryService;
|
|
68
|
+
exports.SentryService = SentryService = __decorate([
|
|
69
|
+
(0, common_1.Injectable)(),
|
|
70
|
+
__param(0, (0, common_1.Inject)(constants_1.SENTRY_PLUGIN_OPTIONS)),
|
|
71
|
+
__metadata("design:paramtypes", [Object])
|
|
72
|
+
], SentryService);
|
|
73
|
+
//# sourceMappingURL=sentry.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sentry.service.js","sourceRoot":"","sources":["../../src/sentry.service.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,2CAKwB;AACxB,qDAAuC;AAGvC,2CAAoD;AAI7C,IAAM,aAAa,GAAnB,MAAM,aAAa;IAGxB,YACyC,OAA4B;QAA5B,YAAO,GAAP,OAAO,CAAqB;IAClE,CAAC;IAEJ,sBAAsB;;QACpB,MAAM,YAAY,GAAG,MAAA,IAAI,CAAC,OAAO,CAAC,YAAY,mCAAI;YAChD,IAAI,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;YAC/C,GAAG,MAAM,CAAC,iDAAiD,EAAE;SAC9D,CAAC;QACF,MAAM,CAAC,IAAI,iCACN,IAAI,CAAC,OAAO,KACf,gBAAgB,EAAE,MAAA,IAAI,CAAC,OAAO,CAAC,gBAAgB,mCAAI,GAAG,EACtD,YAAY,EACZ,GAAG,EAAE,IAAI,CAAC,OAAO,CAAC,GAAG,IACrB,CAAC;IACL,CAAC;IAED,qBAAqB;QACnB,OAAO,MAAM,CAAC,KAAK,EAAE,CAAC;IACxB,CAAC;IAED,gBAAgB,CAAC,SAAgB;QAC/B,MAAM,CAAC,gBAAgB,CAAC,SAAS,CAAC,CAAC;IACrC,CAAC;IAED,cAAc,CAAC,OAAe,EAAE,cAA+B;QAC7D,MAAM,CAAC,cAAc,CAAC,OAAO,EAAE,cAAc,CAAC,CAAC;IACjD,CAAC;IAED,gBAAgB,CAAC,OAA2B;QAC1C,OAAO,MAAM,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC;IAC1C,CAAC;CACF,CAAA;AAnCY,sCAAa;wBAAb,aAAa;IADzB,IAAA,mBAAU,GAAE;IAKR,WAAA,IAAA,eAAM,EAAC,iCAAqB,CAAC,CAAA;;GAJrB,aAAa,CAmCzB"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { Transaction } from "@sentry/node";
|
|
2
|
+
import { NodeOptions } from "@sentry/node/types/types";
|
|
3
|
+
import { SENTRY_TRANSACTION_KEY } from "./constants";
|
|
4
|
+
/**
|
|
5
|
+
* @description
|
|
6
|
+
* Configuration options for the {@link SentryPlugin}.
|
|
7
|
+
*
|
|
8
|
+
* @docsCategory core plugins/SentryPlugin
|
|
9
|
+
*/
|
|
10
|
+
export interface SentryPluginOptions extends NodeOptions {
|
|
11
|
+
/**
|
|
12
|
+
* @description
|
|
13
|
+
* The [Data Source Name](https://docs.sentry.io/product/sentry-basics/concepts/dsn-explainer/) for your Sentry instance.
|
|
14
|
+
*/
|
|
15
|
+
dsn: string;
|
|
16
|
+
enableTracing?: boolean;
|
|
17
|
+
includeErrorTestMutation?: boolean;
|
|
18
|
+
}
|
|
19
|
+
declare module "express" {
|
|
20
|
+
interface Request {
|
|
21
|
+
[SENTRY_TRANSACTION_KEY]: Transaction | undefined;
|
|
22
|
+
}
|
|
23
|
+
}
|
package/lib/src/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":";;AAGA,2CAAqD"}
|
package/package.json
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@deenruv/sentry-plugin",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"license": "MIT",
|
|
5
|
+
"main": "lib/index.js",
|
|
6
|
+
"types": "lib/index.d.ts",
|
|
7
|
+
"files": [
|
|
8
|
+
"lib/**/*"
|
|
9
|
+
],
|
|
10
|
+
"homepage": "https://deenruv.com/",
|
|
11
|
+
"publishConfig": {
|
|
12
|
+
"access": "public"
|
|
13
|
+
},
|
|
14
|
+
"peerDependencies": {
|
|
15
|
+
"@sentry/node": "7.106.1",
|
|
16
|
+
"@deenruv/core": "^0.1.0",
|
|
17
|
+
"graphql": "~16.9.0",
|
|
18
|
+
"graphql-tag": "^2.12.6"
|
|
19
|
+
},
|
|
20
|
+
"devDependencies": {
|
|
21
|
+
"@sentry/node": "7.106.1",
|
|
22
|
+
"@sentry/types": "7.106.1",
|
|
23
|
+
"@types/express": "^4.17.21",
|
|
24
|
+
"rimraf": "^5.0.5",
|
|
25
|
+
"@deenruv/core": "^1.0.0"
|
|
26
|
+
},
|
|
27
|
+
"dependencies": {
|
|
28
|
+
"@apollo/server": "^4.10.4",
|
|
29
|
+
"@nestjs/common": "^10.3.10",
|
|
30
|
+
"@nestjs/core": "^10.3.10",
|
|
31
|
+
"@nestjs/graphql": "^12.2.0",
|
|
32
|
+
"express": "^4.21.0",
|
|
33
|
+
"@deenruv/common": "^1.0.0"
|
|
34
|
+
},
|
|
35
|
+
"scripts": {
|
|
36
|
+
"watch": "tsc -p ./tsconfig.build.json --watch",
|
|
37
|
+
"build": "rimraf lib && tsc -p ./tsconfig.build.json",
|
|
38
|
+
"lint": "eslint .",
|
|
39
|
+
"lint:fix": "eslint --fix ."
|
|
40
|
+
}
|
|
41
|
+
}
|