@envelop/sentry 4.0.0-alpha-d0d0776.0 → 4.0.0-alpha-ccec0fc.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/README.md CHANGED
@@ -30,24 +30,24 @@ yarn add @sentry/node @sentry/tracing @envelop/sentry
30
30
  ## Usage Example
31
31
 
32
32
  ```ts
33
- import { envelop } from '@envelop/core';
34
- import { useSentry } from '@envelop/sentry';
33
+ import { envelop } from '@envelop/core'
34
+ import { useSentry } from '@envelop/sentry'
35
35
  // do this only once in you entry file.
36
- import "@sentry/tracing";
36
+ import '@sentry/tracing'
37
37
 
38
38
  const getEnveloped = envelop({
39
39
  plugins: [
40
40
  // ... other plugins ...
41
41
  useSentry({
42
- includeRawResult: false // set to `true` in order to include the execution result in the metadata collected
42
+ includeRawResult: false, // set to `true` in order to include the execution result in the metadata collected
43
43
  includeResolverArgs: false, // set to `true` in order to include the args passed to resolvers
44
44
  includeExecuteVariables: false, // set to `true` in order to include the operation variables values
45
- appendTags: (args) => { return { ... }} // if you wish to add custom "tags" to the Sentry transaction created per operation
46
- configureScope: (args, scope) => { return { ... }} // if you wish to modify the Sentry scope
47
- skip: (executionArgs) => { return { ... }} // if you wish to modify the skip specific operations
48
- }),
49
- ],
50
- });
45
+ appendTags: args => {}, // if you wish to add custom "tags" to the Sentry transaction created per operation
46
+ configureScope: (args, scope) => {}, // if you wish to modify the Sentry scope
47
+ skip: executionArgs => {} // if you wish to modify the skip specific operations
48
+ })
49
+ ]
50
+ })
51
51
  ```
52
52
 
53
53
  ### Configuration
@@ -61,6 +61,7 @@ const getEnveloped = envelop({
61
61
  - `appendTags` - See example above. Allow you to manipulate the tags reports on the Sentry transaction.
62
62
  - `configureScope` - See example above. Allow you to manipulate the tags reports on the Sentry transaction.
63
63
  - `transactionName` (default: operation name) - Produces a name of Transaction (only when "renameTransaction" or "startTransaction" are enabled) and description of created Span.
64
+ - `traceparentData` (default: `{}`) - Adds tracing data to be sent to Sentry - this includes traceId, parentId and more.
64
65
  - `operationName` - Produces a "op" (operation) of created Span.
65
66
  - `skip` (default: none) - Produces a "op" (operation) of created Span.
66
67
  - `skipError` (default: ignored `EnvelopError`) - Indicates whether or not to skip Sentry exception reporting for a given error. By default, this plugin skips all `EnvelopError` errors and does not report it to Sentry.
@@ -1,38 +1,19 @@
1
- 'use strict';
2
-
3
- Object.defineProperty(exports, '__esModule', { value: true });
4
-
5
- const core = require('@envelop/core');
6
- const Sentry = require('@sentry/node');
7
- const graphql = require('graphql');
8
-
9
- function _interopNamespace(e) {
10
- if (e && e.__esModule) return e;
11
- const n = Object.create(null);
12
- if (e) {
13
- for (const k in e) {
14
- if (k !== 'default') {
15
- const d = Object.getOwnPropertyDescriptor(e, k);
16
- Object.defineProperty(n, k, d.get ? d : {
17
- enumerable: true,
18
- get: function () { return e[k]; }
19
- });
20
- }
21
- }
22
- }
23
- n["default"] = e;
24
- return Object.freeze(n);
25
- }
26
-
27
- const Sentry__namespace = /*#__PURE__*/_interopNamespace(Sentry);
28
-
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useSentry = exports.defaultSkipError = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const core_1 = require("@envelop/core");
6
+ const Sentry = tslib_1.__importStar(require("@sentry/node"));
7
+ const graphql_1 = require("@graphql-tools/graphql");
29
8
  function defaultSkipError(error) {
30
- return error instanceof core.EnvelopError;
9
+ return error instanceof core_1.EnvelopError;
31
10
  }
11
+ exports.defaultSkipError = defaultSkipError;
32
12
  const sentryTracingSymbol = Symbol('sentryTracing');
33
13
  const useSentry = (options = {}) => {
34
14
  function pick(key, defaultValue) {
35
- return options[key] ?? defaultValue;
15
+ var _a;
16
+ return (_a = options[key]) !== null && _a !== void 0 ? _a : defaultValue;
36
17
  }
37
18
  const startTransaction = pick('startTransaction', true);
38
19
  const trackResolvers = pick('trackResolvers', true);
@@ -43,11 +24,12 @@ const useSentry = (options = {}) => {
43
24
  const skipOperation = pick('skip', () => false);
44
25
  const skipError = pick('skipError', defaultSkipError);
45
26
  function addEventId(err, eventId) {
27
+ var _a;
46
28
  if (options.eventIdKey === null) {
47
29
  return err;
48
30
  }
49
- const eventIdKey = options.eventIdKey ?? 'sentryEventId';
50
- return new graphql.GraphQLError(err.message, err.nodes, err.source, err.positions, err.path, undefined, {
31
+ const eventIdKey = (_a = options.eventIdKey) !== null && _a !== void 0 ? _a : 'sentryEventId';
32
+ return new graphql_1.GraphQLError(err.message, err.nodes, err.source, err.positions, err.path, undefined, {
51
33
  ...err.extensions,
52
34
  [eventIdKey]: eventId,
53
35
  });
@@ -76,10 +58,10 @@ const useSentry = (options = {}) => {
76
58
  }
77
59
  if (result instanceof Error && !skipError(result)) {
78
60
  // Map index values in list to $index for better grouping of events.
79
- const errorPath = graphql.responsePathAsArray(info.path)
61
+ const errorPath = (0, graphql_1.responsePathAsArray)(info.path)
80
62
  .map(v => (typeof v === 'number' ? '$index' : v))
81
63
  .join(' > ');
82
- Sentry__namespace.captureException(result, {
64
+ Sentry.captureException(result, {
83
65
  fingerprint: ['graphql', errorPath, opName, operationType],
84
66
  });
85
67
  }
@@ -92,33 +74,43 @@ const useSentry = (options = {}) => {
92
74
  return {
93
75
  onResolverCalled,
94
76
  onExecute({ args, extendContext }) {
77
+ var _a;
95
78
  if (skipOperation(args)) {
96
79
  return;
97
80
  }
98
- const rootOperation = args.document.definitions.find(o => o.kind === graphql.Kind.OPERATION_DEFINITION);
81
+ const rootOperation = args.document.definitions.find(o => o.kind === graphql_1.Kind.OPERATION_DEFINITION);
99
82
  const operationType = rootOperation.operation;
100
- const document = graphql.print(args.document);
101
- const opName = args.operationName || rootOperation.name?.value || 'Anonymous Operation';
83
+ const document = (0, graphql_1.print)(args.document);
84
+ const opName = args.operationName || ((_a = rootOperation.name) === null || _a === void 0 ? void 0 : _a.value) || 'Anonymous Operation';
102
85
  const addedTags = (options.appendTags && options.appendTags(args)) || {};
86
+ const traceparentData = (options.traceparentData && options.traceparentData(args)) || {};
103
87
  const transactionName = options.transactionName ? options.transactionName(args) : opName;
104
88
  const op = options.operationName ? options.operationName(args) : 'execute';
105
89
  const tags = {
106
90
  operationName: opName,
107
91
  operation: operationType,
108
- ...(addedTags || {}),
92
+ ...addedTags,
109
93
  };
110
94
  let rootSpan;
111
95
  if (startTransaction) {
112
- rootSpan = Sentry__namespace.startTransaction({
96
+ rootSpan = Sentry.startTransaction({
113
97
  name: transactionName,
114
98
  op,
115
99
  tags,
100
+ ...traceparentData,
116
101
  });
102
+ if (!rootSpan) {
103
+ const error = [
104
+ `Could not create the root Sentry transaction for the GraphQL operation "${transactionName}".`,
105
+ `It's very likely that this is because you have not included the Sentry tracing SDK in your app's runtime before handling the request.`,
106
+ ];
107
+ throw new Error(error.join('\n'));
108
+ }
117
109
  }
118
110
  else {
119
- const scope = Sentry__namespace.getCurrentHub().getScope();
120
- const parentSpan = scope?.getSpan();
121
- const span = parentSpan?.startChild({
111
+ const scope = Sentry.getCurrentHub().getScope();
112
+ const parentSpan = scope === null || scope === void 0 ? void 0 : scope.getSpan();
113
+ const span = parentSpan === null || parentSpan === void 0 ? void 0 : parentSpan.startChild({
122
114
  description: transactionName,
123
115
  op,
124
116
  tags,
@@ -138,7 +130,7 @@ const useSentry = (options = {}) => {
138
130
  }
139
131
  rootSpan.setData('document', document);
140
132
  if (options.configureScope) {
141
- Sentry__namespace.configureScope(scope => options.configureScope(args, scope));
133
+ Sentry.configureScope(scope => options.configureScope(args, scope));
142
134
  }
143
135
  if (onResolverCalled) {
144
136
  const sentryContext = {
@@ -155,7 +147,8 @@ const useSentry = (options = {}) => {
155
147
  rootSpan.setData('result', result);
156
148
  }
157
149
  if (result.errors && result.errors.length > 0) {
158
- Sentry__namespace.withScope(scope => {
150
+ Sentry.withScope(scope => {
151
+ var _a;
159
152
  scope.setTransactionName(opName);
160
153
  scope.setTag('operation', operationType);
161
154
  scope.setTag('operationName', opName);
@@ -167,8 +160,9 @@ const useSentry = (options = {}) => {
167
160
  if (includeExecuteVariables) {
168
161
  scope.setExtra('variables', args.variableValues);
169
162
  }
170
- const errors = result.errors?.map(err => {
171
- const errorPath = (err.path ?? []).join(' > ');
163
+ const errors = (_a = result.errors) === null || _a === void 0 ? void 0 : _a.map(err => {
164
+ var _a, _b;
165
+ const errorPath = ((_a = err.path) !== null && _a !== void 0 ? _a : []).join(' > ');
172
166
  if (errorPath) {
173
167
  scope.addBreadcrumb({
174
168
  category: 'execution-path',
@@ -177,8 +171,10 @@ const useSentry = (options = {}) => {
177
171
  });
178
172
  }
179
173
  // Map index values in list to $index for better grouping of events.
180
- const errorPathWithIndex = (err.path ?? []).map(v => (typeof v === 'number' ? '$index' : v)).join(' > ');
181
- const eventId = Sentry__namespace.captureException(err, {
174
+ const errorPathWithIndex = ((_b = err.path) !== null && _b !== void 0 ? _b : [])
175
+ .map(v => (typeof v === 'number' ? '$index' : v))
176
+ .join(' > ');
177
+ const eventId = Sentry.captureException(err, {
182
178
  fingerprint: ['graphql', errorPathWithIndex, opName, operationType],
183
179
  contexts: {
184
180
  GraphQL: {
@@ -198,12 +194,10 @@ const useSentry = (options = {}) => {
198
194
  }
199
195
  rootSpan.finish();
200
196
  };
201
- return core.handleStreamOrSingleExecutionResult(payload, handleResult);
197
+ return (0, core_1.handleStreamOrSingleExecutionResult)(payload, handleResult);
202
198
  },
203
199
  };
204
200
  },
205
201
  };
206
202
  };
207
-
208
- exports.defaultSkipError = defaultSkipError;
209
203
  exports.useSentry = useSentry;
@@ -0,0 +1 @@
1
+ {"type":"commonjs"}
@@ -1,14 +1,14 @@
1
- import { EnvelopError, handleStreamOrSingleExecutionResult } from '@envelop/core';
1
+ import { EnvelopError, handleStreamOrSingleExecutionResult, } from '@envelop/core';
2
2
  import * as Sentry from '@sentry/node';
3
- import { responsePathAsArray, Kind, print, GraphQLError } from 'graphql';
4
-
5
- function defaultSkipError(error) {
3
+ import { GraphQLError, Kind, print, responsePathAsArray, } from '@graphql-tools/graphql';
4
+ export function defaultSkipError(error) {
6
5
  return error instanceof EnvelopError;
7
6
  }
8
7
  const sentryTracingSymbol = Symbol('sentryTracing');
9
- const useSentry = (options = {}) => {
8
+ export const useSentry = (options = {}) => {
10
9
  function pick(key, defaultValue) {
11
- return options[key] ?? defaultValue;
10
+ var _a;
11
+ return (_a = options[key]) !== null && _a !== void 0 ? _a : defaultValue;
12
12
  }
13
13
  const startTransaction = pick('startTransaction', true);
14
14
  const trackResolvers = pick('trackResolvers', true);
@@ -19,10 +19,11 @@ const useSentry = (options = {}) => {
19
19
  const skipOperation = pick('skip', () => false);
20
20
  const skipError = pick('skipError', defaultSkipError);
21
21
  function addEventId(err, eventId) {
22
+ var _a;
22
23
  if (options.eventIdKey === null) {
23
24
  return err;
24
25
  }
25
- const eventIdKey = options.eventIdKey ?? 'sentryEventId';
26
+ const eventIdKey = (_a = options.eventIdKey) !== null && _a !== void 0 ? _a : 'sentryEventId';
26
27
  return new GraphQLError(err.message, err.nodes, err.source, err.positions, err.path, undefined, {
27
28
  ...err.extensions,
28
29
  [eventIdKey]: eventId,
@@ -68,20 +69,22 @@ const useSentry = (options = {}) => {
68
69
  return {
69
70
  onResolverCalled,
70
71
  onExecute({ args, extendContext }) {
72
+ var _a;
71
73
  if (skipOperation(args)) {
72
74
  return;
73
75
  }
74
76
  const rootOperation = args.document.definitions.find(o => o.kind === Kind.OPERATION_DEFINITION);
75
77
  const operationType = rootOperation.operation;
76
78
  const document = print(args.document);
77
- const opName = args.operationName || rootOperation.name?.value || 'Anonymous Operation';
79
+ const opName = args.operationName || ((_a = rootOperation.name) === null || _a === void 0 ? void 0 : _a.value) || 'Anonymous Operation';
78
80
  const addedTags = (options.appendTags && options.appendTags(args)) || {};
81
+ const traceparentData = (options.traceparentData && options.traceparentData(args)) || {};
79
82
  const transactionName = options.transactionName ? options.transactionName(args) : opName;
80
83
  const op = options.operationName ? options.operationName(args) : 'execute';
81
84
  const tags = {
82
85
  operationName: opName,
83
86
  operation: operationType,
84
- ...(addedTags || {}),
87
+ ...addedTags,
85
88
  };
86
89
  let rootSpan;
87
90
  if (startTransaction) {
@@ -89,12 +92,20 @@ const useSentry = (options = {}) => {
89
92
  name: transactionName,
90
93
  op,
91
94
  tags,
95
+ ...traceparentData,
92
96
  });
97
+ if (!rootSpan) {
98
+ const error = [
99
+ `Could not create the root Sentry transaction for the GraphQL operation "${transactionName}".`,
100
+ `It's very likely that this is because you have not included the Sentry tracing SDK in your app's runtime before handling the request.`,
101
+ ];
102
+ throw new Error(error.join('\n'));
103
+ }
93
104
  }
94
105
  else {
95
106
  const scope = Sentry.getCurrentHub().getScope();
96
- const parentSpan = scope?.getSpan();
97
- const span = parentSpan?.startChild({
107
+ const parentSpan = scope === null || scope === void 0 ? void 0 : scope.getSpan();
108
+ const span = parentSpan === null || parentSpan === void 0 ? void 0 : parentSpan.startChild({
98
109
  description: transactionName,
99
110
  op,
100
111
  tags,
@@ -132,6 +143,7 @@ const useSentry = (options = {}) => {
132
143
  }
133
144
  if (result.errors && result.errors.length > 0) {
134
145
  Sentry.withScope(scope => {
146
+ var _a;
135
147
  scope.setTransactionName(opName);
136
148
  scope.setTag('operation', operationType);
137
149
  scope.setTag('operationName', opName);
@@ -143,8 +155,9 @@ const useSentry = (options = {}) => {
143
155
  if (includeExecuteVariables) {
144
156
  scope.setExtra('variables', args.variableValues);
145
157
  }
146
- const errors = result.errors?.map(err => {
147
- const errorPath = (err.path ?? []).join(' > ');
158
+ const errors = (_a = result.errors) === null || _a === void 0 ? void 0 : _a.map(err => {
159
+ var _a, _b;
160
+ const errorPath = ((_a = err.path) !== null && _a !== void 0 ? _a : []).join(' > ');
148
161
  if (errorPath) {
149
162
  scope.addBreadcrumb({
150
163
  category: 'execution-path',
@@ -153,7 +166,9 @@ const useSentry = (options = {}) => {
153
166
  });
154
167
  }
155
168
  // Map index values in list to $index for better grouping of events.
156
- const errorPathWithIndex = (err.path ?? []).map(v => (typeof v === 'number' ? '$index' : v)).join(' > ');
169
+ const errorPathWithIndex = ((_b = err.path) !== null && _b !== void 0 ? _b : [])
170
+ .map(v => (typeof v === 'number' ? '$index' : v))
171
+ .join(' > ');
157
172
  const eventId = Sentry.captureException(err, {
158
173
  fingerprint: ['graphql', errorPathWithIndex, opName, operationType],
159
174
  contexts: {
@@ -180,5 +195,3 @@ const useSentry = (options = {}) => {
180
195
  },
181
196
  };
182
197
  };
183
-
184
- export { defaultSkipError, useSentry };
package/package.json CHANGED
@@ -1,12 +1,13 @@
1
1
  {
2
2
  "name": "@envelop/sentry",
3
- "version": "4.0.0-alpha-d0d0776.0",
3
+ "version": "4.0.0-alpha-ccec0fc.0",
4
4
  "sideEffects": false,
5
5
  "peerDependencies": {
6
- "@envelop/core": "3.0.0-alpha-d0d0776.0",
6
+ "@envelop/core": "3.0.0-alpha-ccec0fc.0",
7
7
  "@sentry/node": "^6 || ^7",
8
- "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0"
8
+ "@graphql-tools/graphql": "0.1.0-alpha-e7752ba5.0"
9
9
  },
10
+ "dependencies": {},
10
11
  "repository": {
11
12
  "type": "git",
12
13
  "url": "https://github.com/n1ru4l/envelop.git",
@@ -14,33 +15,42 @@
14
15
  },
15
16
  "author": "Dotan Simha <dotansimha@gmail.com>",
16
17
  "license": "MIT",
17
- "main": "index.js",
18
- "module": "index.mjs",
19
- "typings": "index.d.ts",
18
+ "main": "cjs/index.js",
19
+ "module": "esm/index.js",
20
+ "typings": "typings/index.d.ts",
20
21
  "typescript": {
21
- "definition": "index.d.ts"
22
+ "definition": "typings/index.d.ts"
22
23
  },
24
+ "type": "module",
23
25
  "exports": {
24
26
  ".": {
25
27
  "require": {
26
- "default": "./index.js",
27
- "types": "./index.d.ts"
28
+ "types": "./typings/index.d.ts",
29
+ "default": "./cjs/index.js"
28
30
  },
29
31
  "import": {
30
- "default": "./index.mjs",
31
- "types": "./index.d.ts"
32
+ "types": "./typings/index.d.ts",
33
+ "default": "./esm/index.js"
34
+ },
35
+ "default": {
36
+ "types": "./typings/index.d.ts",
37
+ "default": "./esm/index.js"
32
38
  }
33
39
  },
34
40
  "./*": {
35
41
  "require": {
36
- "default": "./*.js",
37
- "types": "./*.d.ts"
42
+ "types": "./typings/*.d.ts",
43
+ "default": "./cjs/*.js"
38
44
  },
39
45
  "import": {
40
- "default": "./*.mjs",
41
- "types": "./*.d.ts"
46
+ "types": "./typings/*.d.ts",
47
+ "default": "./esm/*.js"
48
+ },
49
+ "default": {
50
+ "types": "./typings/*.d.ts",
51
+ "default": "./esm/*.js"
42
52
  }
43
53
  },
44
54
  "./package.json": "./package.json"
45
55
  }
46
- }
56
+ }
@@ -1,6 +1,7 @@
1
1
  import { Plugin } from '@envelop/core';
2
2
  import * as Sentry from '@sentry/node';
3
- import { ExecutionArgs } from 'graphql';
3
+ import type { TraceparentData } from '@sentry/types';
4
+ import { ExecutionArgs } from '@graphql-tools/graphql';
4
5
  export declare type SentryPluginOptions = {
5
6
  /**
6
7
  * Starts a new transaction for every GraphQL Operation.
@@ -53,6 +54,12 @@ export declare type SentryPluginOptions = {
53
54
  * @default operation's name or "Anonymous Operation" when missing)
54
55
  */
55
56
  transactionName?: (args: ExecutionArgs) => string;
57
+ /**
58
+ * Produces tracing data for Transaction
59
+ *
60
+ * @default is empty
61
+ */
62
+ traceparentData?: (args: ExecutionArgs) => TraceparentData | undefined;
56
63
  /**
57
64
  * Produces a "op" (operation) of created Span.
58
65
  *