@envelop/newrelic 3.1.0 → 3.2.1
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 +3 -2
- package/index.d.ts +5 -4
- package/index.js +59 -30
- package/index.mjs +41 -29
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -44,6 +44,7 @@ const getEnveloped = envelop({
|
|
|
44
44
|
trackResolvers: true, // default `false`. When set to `true`, track resolvers as segments to monitor their performance
|
|
45
45
|
includeResolverArgs: false, // default `false`. When set to `true`, includes all the arguments passed to resolvers with their values
|
|
46
46
|
rootFieldsNaming: true, // default `false`. When set to `true` append the names of operation root fields to the transaction name
|
|
47
|
+
skipError: error => { ... return true; }, // a function that allows you to skip reporting a given error to NewRelic. By default custom `EnvelopError`s will be skipped
|
|
47
48
|
operationNameProperty: 'id', // default empty. When passed will check for the property name passed, within the document object. Will eventually use its value as operation name. Useful for custom document properties (e.g. queryId/hash)
|
|
48
49
|
}),
|
|
49
50
|
],
|
|
@@ -62,9 +63,9 @@ Below is a quick example of how you can use RegEx to set up white/black listing
|
|
|
62
63
|
|
|
63
64
|
```ts
|
|
64
65
|
useNewRelic({
|
|
65
|
-
includeExecuteVariables:
|
|
66
|
+
includeExecuteVariables: /client|application/i, // whitelist, track only variables whose name contains "client" or "application" (e.g. clientName, applicationId, xApplicationId)
|
|
66
67
|
trackResolvers: true, // track resolvers, since we also want to track resolvers' arguments
|
|
67
|
-
includeResolverArgs: /^(?!
|
|
68
|
+
includeResolverArgs: /^(?!name|email|password).*/i, // blacklist, track all arguments whose name does not match 'name', 'email' nor 'password'
|
|
68
69
|
}),
|
|
69
70
|
```
|
|
70
71
|
|
package/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Plugin } from '@envelop/core';
|
|
2
|
+
import { GraphQLError } from 'graphql';
|
|
2
3
|
export declare type UseNewRelicOptions = {
|
|
3
4
|
includeOperationDocument?: boolean;
|
|
4
5
|
includeExecuteVariables?: boolean | RegExp;
|
|
@@ -8,10 +9,10 @@ export declare type UseNewRelicOptions = {
|
|
|
8
9
|
rootFieldsNaming?: boolean;
|
|
9
10
|
operationNameProperty?: string;
|
|
10
11
|
/**
|
|
11
|
-
* Indicates whether or not to skip
|
|
12
|
-
* By default, this plugin skips all `EnvelopError` errors and does not report
|
|
12
|
+
* Indicates whether or not to skip reporting a given error to NewRelic.
|
|
13
|
+
* By default, this plugin skips all `EnvelopError` errors and does not report them to NewRelic.
|
|
13
14
|
*/
|
|
14
|
-
skipError?: (
|
|
15
|
+
skipError?: (error: GraphQLError) => boolean;
|
|
15
16
|
};
|
|
16
|
-
export declare function defaultSkipError(error:
|
|
17
|
+
export declare function defaultSkipError(error: GraphQLError): boolean;
|
|
17
18
|
export declare const useNewRelic: (rawOptions?: UseNewRelicOptions | undefined) => Plugin;
|
package/index.js
CHANGED
|
@@ -2,13 +2,28 @@
|
|
|
2
2
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
|
-
function
|
|
5
|
+
function _interopNamespace(e) {
|
|
6
|
+
if (e && e.__esModule) { return e; } else {
|
|
7
|
+
var n = {};
|
|
8
|
+
if (e) {
|
|
9
|
+
Object.keys(e).forEach(function (k) {
|
|
10
|
+
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
11
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
12
|
+
enumerable: true,
|
|
13
|
+
get: function () {
|
|
14
|
+
return e[k];
|
|
15
|
+
}
|
|
16
|
+
});
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
n['default'] = e;
|
|
20
|
+
return n;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
6
23
|
|
|
7
|
-
const newRelic = _interopDefault(require('newrelic'));
|
|
8
24
|
const core = require('@envelop/core');
|
|
9
25
|
const graphql = require('graphql');
|
|
10
26
|
|
|
11
|
-
const { shim: instrumentationApi } = newRelic;
|
|
12
27
|
var AttributeName;
|
|
13
28
|
(function (AttributeName) {
|
|
14
29
|
AttributeName["COMPONENT_NAME"] = "Envelop_NewRelic_Plugin";
|
|
@@ -35,7 +50,7 @@ const DEFAULT_OPTIONS = {
|
|
|
35
50
|
skipError: defaultSkipError,
|
|
36
51
|
};
|
|
37
52
|
function defaultSkipError(error) {
|
|
38
|
-
return error instanceof core.EnvelopError;
|
|
53
|
+
return error.originalError instanceof core.EnvelopError;
|
|
39
54
|
}
|
|
40
55
|
const useNewRelic = (rawOptions) => {
|
|
41
56
|
const options = {
|
|
@@ -44,14 +59,21 @@ const useNewRelic = (rawOptions) => {
|
|
|
44
59
|
};
|
|
45
60
|
options.isExecuteVariablesRegex = options.includeExecuteVariables instanceof RegExp;
|
|
46
61
|
options.isResolverArgsRegex = options.includeResolverArgs instanceof RegExp;
|
|
47
|
-
const
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
.getOrCreateMetric(`Supportability/ExternalModules/${AttributeName.COMPONENT_NAME}`)
|
|
51
|
-
|
|
62
|
+
const instrumentationApi$ = new Promise(function (resolve) { resolve(_interopNamespace(require('newrelic'))); })
|
|
63
|
+
.then(m => m.default || m)
|
|
64
|
+
.then(({ shim }) => {
|
|
65
|
+
shim.agent.metrics.getOrCreateMetric(`Supportability/ExternalModules/${AttributeName.COMPONENT_NAME}`).incrementCallCount();
|
|
66
|
+
return shim;
|
|
67
|
+
});
|
|
68
|
+
const logger$ = instrumentationApi$.then(({ logger }) => {
|
|
69
|
+
const childLogger = logger.child({ component: AttributeName.COMPONENT_NAME });
|
|
70
|
+
childLogger.info(`${AttributeName.COMPONENT_NAME} registered`);
|
|
71
|
+
return childLogger;
|
|
72
|
+
});
|
|
52
73
|
return {
|
|
53
|
-
onExecute({ args }) {
|
|
74
|
+
async onExecute({ args }) {
|
|
54
75
|
var _a;
|
|
76
|
+
const instrumentationApi = await instrumentationApi$;
|
|
55
77
|
const transactionNameState = instrumentationApi.agent.tracer.getTransaction().nameState;
|
|
56
78
|
const spanContext = instrumentationApi.agent.tracer.getSpanContext();
|
|
57
79
|
const delimiter = transactionNameState.delimiter;
|
|
@@ -80,7 +102,8 @@ const useNewRelic = (rawOptions) => {
|
|
|
80
102
|
}
|
|
81
103
|
const operationSegment = instrumentationApi.getActiveSegment();
|
|
82
104
|
const onResolverCalled = options.trackResolvers
|
|
83
|
-
? ({ args: resolversArgs, info }) => {
|
|
105
|
+
? async ({ args: resolversArgs, info }) => {
|
|
106
|
+
const logger = await logger$;
|
|
84
107
|
const { returnType, path, parentType } = info;
|
|
85
108
|
const formattedPath = flattenPath(path, delimiter);
|
|
86
109
|
const currentSegment = instrumentationApi.getActiveSegment();
|
|
@@ -105,14 +128,9 @@ const useNewRelic = (rawOptions) => {
|
|
|
105
128
|
resolverSegment.addAttribute(AttributeName.RESOLVER_ARGS, JSON.stringify(resolverArgsToTrack));
|
|
106
129
|
}
|
|
107
130
|
return ({ result }) => {
|
|
108
|
-
var _a;
|
|
109
131
|
if (options.includeRawResult) {
|
|
110
132
|
resolverSegment.addAttribute(AttributeName.RESOLVER_RESULT, JSON.stringify(result));
|
|
111
133
|
}
|
|
112
|
-
if (result instanceof Error && !((_a = options.skipError) === null || _a === void 0 ? void 0 : _a.call(options, result))) {
|
|
113
|
-
const transaction = instrumentationApi.tracer.getTransaction();
|
|
114
|
-
instrumentationApi.agent.errors.add(transaction, JSON.stringify(result));
|
|
115
|
-
}
|
|
116
134
|
resolverSegment.end();
|
|
117
135
|
};
|
|
118
136
|
}
|
|
@@ -120,23 +138,34 @@ const useNewRelic = (rawOptions) => {
|
|
|
120
138
|
return {
|
|
121
139
|
onResolverCalled,
|
|
122
140
|
onExecuteDone({ result }) {
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
return;
|
|
128
|
-
}
|
|
129
|
-
if (result.data && options.includeRawResult) {
|
|
130
|
-
spanContext.addCustomAttribute(AttributeName.EXECUTION_RESULT, JSON.stringify(result));
|
|
131
|
-
}
|
|
132
|
-
if (result.errors && result.errors.length > 0) {
|
|
133
|
-
const agent = instrumentationApi.agent;
|
|
134
|
-
const transaction = instrumentationApi.tracer.getTransaction();
|
|
135
|
-
for (const error of result.errors) {
|
|
136
|
-
agent.errors.add(transaction, JSON.stringify(error));
|
|
141
|
+
const sendResult = (singularResult) => {
|
|
142
|
+
var _a;
|
|
143
|
+
if (singularResult.data && options.includeRawResult) {
|
|
144
|
+
spanContext.addCustomAttribute(AttributeName.EXECUTION_RESULT, JSON.stringify(singularResult));
|
|
137
145
|
}
|
|
146
|
+
if (singularResult.errors && singularResult.errors.length > 0) {
|
|
147
|
+
const agent = instrumentationApi.agent;
|
|
148
|
+
const transaction = instrumentationApi.tracer.getTransaction();
|
|
149
|
+
for (const error of singularResult.errors) {
|
|
150
|
+
if ((_a = options.skipError) === null || _a === void 0 ? void 0 : _a.call(options, error))
|
|
151
|
+
continue;
|
|
152
|
+
agent.errors.add(transaction, JSON.stringify(error));
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
};
|
|
156
|
+
if (core.isAsyncIterable(result)) {
|
|
157
|
+
return {
|
|
158
|
+
onNext: ({ result: singularResult }) => {
|
|
159
|
+
sendResult(singularResult);
|
|
160
|
+
},
|
|
161
|
+
onEnd: () => {
|
|
162
|
+
operationSegment.end();
|
|
163
|
+
},
|
|
164
|
+
};
|
|
138
165
|
}
|
|
166
|
+
sendResult(result);
|
|
139
167
|
operationSegment.end();
|
|
168
|
+
return {};
|
|
140
169
|
},
|
|
141
170
|
};
|
|
142
171
|
},
|
package/index.mjs
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
|
-
import newRelic from 'newrelic';
|
|
2
1
|
import { EnvelopError, isAsyncIterable } from '@envelop/core';
|
|
3
2
|
import { Kind, print } from 'graphql';
|
|
4
3
|
|
|
5
|
-
const { shim: instrumentationApi } = newRelic;
|
|
6
4
|
var AttributeName;
|
|
7
5
|
(function (AttributeName) {
|
|
8
6
|
AttributeName["COMPONENT_NAME"] = "Envelop_NewRelic_Plugin";
|
|
@@ -29,7 +27,7 @@ const DEFAULT_OPTIONS = {
|
|
|
29
27
|
skipError: defaultSkipError,
|
|
30
28
|
};
|
|
31
29
|
function defaultSkipError(error) {
|
|
32
|
-
return error instanceof EnvelopError;
|
|
30
|
+
return error.originalError instanceof EnvelopError;
|
|
33
31
|
}
|
|
34
32
|
const useNewRelic = (rawOptions) => {
|
|
35
33
|
const options = {
|
|
@@ -38,14 +36,21 @@ const useNewRelic = (rawOptions) => {
|
|
|
38
36
|
};
|
|
39
37
|
options.isExecuteVariablesRegex = options.includeExecuteVariables instanceof RegExp;
|
|
40
38
|
options.isResolverArgsRegex = options.includeResolverArgs instanceof RegExp;
|
|
41
|
-
const
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
.getOrCreateMetric(`Supportability/ExternalModules/${AttributeName.COMPONENT_NAME}`)
|
|
45
|
-
|
|
39
|
+
const instrumentationApi$ = import('newrelic')
|
|
40
|
+
.then(m => m.default || m)
|
|
41
|
+
.then(({ shim }) => {
|
|
42
|
+
shim.agent.metrics.getOrCreateMetric(`Supportability/ExternalModules/${AttributeName.COMPONENT_NAME}`).incrementCallCount();
|
|
43
|
+
return shim;
|
|
44
|
+
});
|
|
45
|
+
const logger$ = instrumentationApi$.then(({ logger }) => {
|
|
46
|
+
const childLogger = logger.child({ component: AttributeName.COMPONENT_NAME });
|
|
47
|
+
childLogger.info(`${AttributeName.COMPONENT_NAME} registered`);
|
|
48
|
+
return childLogger;
|
|
49
|
+
});
|
|
46
50
|
return {
|
|
47
|
-
onExecute({ args }) {
|
|
51
|
+
async onExecute({ args }) {
|
|
48
52
|
var _a;
|
|
53
|
+
const instrumentationApi = await instrumentationApi$;
|
|
49
54
|
const transactionNameState = instrumentationApi.agent.tracer.getTransaction().nameState;
|
|
50
55
|
const spanContext = instrumentationApi.agent.tracer.getSpanContext();
|
|
51
56
|
const delimiter = transactionNameState.delimiter;
|
|
@@ -74,7 +79,8 @@ const useNewRelic = (rawOptions) => {
|
|
|
74
79
|
}
|
|
75
80
|
const operationSegment = instrumentationApi.getActiveSegment();
|
|
76
81
|
const onResolverCalled = options.trackResolvers
|
|
77
|
-
? ({ args: resolversArgs, info }) => {
|
|
82
|
+
? async ({ args: resolversArgs, info }) => {
|
|
83
|
+
const logger = await logger$;
|
|
78
84
|
const { returnType, path, parentType } = info;
|
|
79
85
|
const formattedPath = flattenPath(path, delimiter);
|
|
80
86
|
const currentSegment = instrumentationApi.getActiveSegment();
|
|
@@ -99,14 +105,9 @@ const useNewRelic = (rawOptions) => {
|
|
|
99
105
|
resolverSegment.addAttribute(AttributeName.RESOLVER_ARGS, JSON.stringify(resolverArgsToTrack));
|
|
100
106
|
}
|
|
101
107
|
return ({ result }) => {
|
|
102
|
-
var _a;
|
|
103
108
|
if (options.includeRawResult) {
|
|
104
109
|
resolverSegment.addAttribute(AttributeName.RESOLVER_RESULT, JSON.stringify(result));
|
|
105
110
|
}
|
|
106
|
-
if (result instanceof Error && !((_a = options.skipError) === null || _a === void 0 ? void 0 : _a.call(options, result))) {
|
|
107
|
-
const transaction = instrumentationApi.tracer.getTransaction();
|
|
108
|
-
instrumentationApi.agent.errors.add(transaction, JSON.stringify(result));
|
|
109
|
-
}
|
|
110
111
|
resolverSegment.end();
|
|
111
112
|
};
|
|
112
113
|
}
|
|
@@ -114,23 +115,34 @@ const useNewRelic = (rawOptions) => {
|
|
|
114
115
|
return {
|
|
115
116
|
onResolverCalled,
|
|
116
117
|
onExecuteDone({ result }) {
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
agent.errors.add(transaction, JSON.stringify(error));
|
|
118
|
+
const sendResult = (singularResult) => {
|
|
119
|
+
var _a;
|
|
120
|
+
if (singularResult.data && options.includeRawResult) {
|
|
121
|
+
spanContext.addCustomAttribute(AttributeName.EXECUTION_RESULT, JSON.stringify(singularResult));
|
|
122
|
+
}
|
|
123
|
+
if (singularResult.errors && singularResult.errors.length > 0) {
|
|
124
|
+
const agent = instrumentationApi.agent;
|
|
125
|
+
const transaction = instrumentationApi.tracer.getTransaction();
|
|
126
|
+
for (const error of singularResult.errors) {
|
|
127
|
+
if ((_a = options.skipError) === null || _a === void 0 ? void 0 : _a.call(options, error))
|
|
128
|
+
continue;
|
|
129
|
+
agent.errors.add(transaction, JSON.stringify(error));
|
|
130
|
+
}
|
|
131
131
|
}
|
|
132
|
+
};
|
|
133
|
+
if (isAsyncIterable(result)) {
|
|
134
|
+
return {
|
|
135
|
+
onNext: ({ result: singularResult }) => {
|
|
136
|
+
sendResult(singularResult);
|
|
137
|
+
},
|
|
138
|
+
onEnd: () => {
|
|
139
|
+
operationSegment.end();
|
|
140
|
+
},
|
|
141
|
+
};
|
|
132
142
|
}
|
|
143
|
+
sendResult(result);
|
|
133
144
|
operationSegment.end();
|
|
145
|
+
return {};
|
|
134
146
|
},
|
|
135
147
|
};
|
|
136
148
|
},
|