@envelop/prometheus 7.0.0-alpha-d0d0776.0 → 7.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
@@ -26,8 +26,8 @@ yarn add prom-client @envelop/prometheus
26
26
  ## Usage Example
27
27
 
28
28
  ```ts
29
- import { envelop } from '@envelop/core';
30
- import { usePrometheus } from '@envelop/prometheus';
29
+ import { envelop } from '@envelop/core'
30
+ import { usePrometheus } from '@envelop/prometheus'
31
31
 
32
32
  const getEnveloped = envelop({
33
33
  plugins: [
@@ -44,10 +44,10 @@ const getEnveloped = envelop({
44
44
  resolvers: true, // requires "execute" to be `true` as well
45
45
  resolversWhitelist: ['Mutation.*', 'Query.user'], // reports metrics als for these resolvers, leave `undefined` to report all fields
46
46
  deprecatedFields: true,
47
- registry: myRegistry, // If you are using a custom prom-client registry, please set it here
48
- }),
49
- ],
50
- });
47
+ registry: myRegistry // If you are using a custom prom-client registry, please set it here
48
+ })
49
+ ]
50
+ })
51
51
  ```
52
52
 
53
53
  > Note: Tracing resolvers using `resovlers: true` might have a performance impact on your GraphQL runtime. Please consider to test it locally first and then decide if it's needed.
@@ -57,19 +57,19 @@ const getEnveloped = envelop({
57
57
  You can customize the `prom-client` `Registry` object if you are using a custom one, by passing it along with the configuration object:
58
58
 
59
59
  ```ts
60
- import { Registry } from 'prom-client';
60
+ import { Registry } from 'prom-client'
61
61
 
62
- const myRegistry = new Registry();
62
+ const myRegistry = new Registry()
63
63
 
64
64
  const getEnveloped = envelop({
65
65
  plugins: [
66
66
  // ... other plugins ...
67
67
  usePrometheus({
68
68
  // ... config ...
69
- registry: myRegistry,
70
- }),
71
- ],
72
- });
69
+ registry: myRegistry
70
+ })
71
+ ]
72
+ })
73
73
  ```
74
74
 
75
75
  > Note: if you are using custom `prom-client` instances, you need to make sure to pass your registry there as well.
@@ -83,9 +83,9 @@ If you wish to disable introspection logging, you can use `skipIntrospection: tr
83
83
  Each tracing field supports custom `prom-client` objects, and custom `labels` a metadata, you can create a custom extraction function for every `Histogram` / `Summary` / `Counter`:
84
84
 
85
85
  ```ts
86
- import { Histogram } from 'prom-client';
87
- import { envelop } from '@envelop/core';
88
- import { createHistogram, usePrometheus } from '@envelop/prometheus';
86
+ import { Histogram } from 'prom-client'
87
+ import { envelop } from '@envelop/core'
88
+ import { createHistogram, usePrometheus } from '@envelop/prometheus'
89
89
 
90
90
  const getEnveloped = envelop({
91
91
  plugins: [
@@ -97,16 +97,16 @@ const getEnveloped = envelop({
97
97
  name: 'my_custom_name',
98
98
  help: 'HELP ME',
99
99
  labelNames: ['opText'] as const,
100
- registers: [registry], // make sure to add your custom registry, if you are not using the default one
100
+ registers: [registry] // make sure to add your custom registry, if you are not using the default one
101
101
  }),
102
102
  fillLabelsFn: params => {
103
103
  // if you wish to fill your `lables` with metadata, you can use the params in order to get access to things like DocumentNode, operationName, operationType, `error` (for error metrics) and `info` (for resolvers metrics)
104
104
  return {
105
- opText: print(params.document),
106
- };
107
- },
108
- }),
109
- }),
110
- ],
111
- });
105
+ opText: print(params.document)
106
+ }
107
+ }
108
+ })
109
+ })
110
+ ]
111
+ })
112
112
  ```
package/cjs/config.js ADDED
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -1,117 +1,53 @@
1
- 'use strict';
2
-
3
- Object.defineProperty(exports, '__esModule', { value: true });
4
-
5
- const core = require('@envelop/core');
6
- const graphql = require('graphql');
7
- const promClient = require('prom-client');
8
-
9
- function shouldTraceFieldResolver(info, whitelist) {
10
- if (!whitelist) {
11
- return true;
12
- }
13
- const parentType = info.parentType.name;
14
- const fieldName = info.fieldName;
15
- const coordinate = `${parentType}.${fieldName}`;
16
- return whitelist.includes(coordinate) || whitelist.includes(`${parentType}.*`);
17
- }
18
- function getOperation(document) {
19
- return document.definitions[0];
20
- }
21
- function createInternalContext(parseResult) {
22
- if (parseResult === null) {
23
- return null;
24
- }
25
- if (parseResult instanceof Error) {
26
- return null;
27
- }
28
- const operation = getOperation(parseResult);
29
- return {
30
- document: parseResult,
31
- operationName: operation.name?.value || 'Anonymous',
32
- operationType: operation.operation,
33
- };
34
- }
35
- function createHistogram(options) {
36
- return options;
37
- }
38
- function createSummary(options) {
39
- return options;
40
- }
41
- function createCounter(options) {
42
- return options;
43
- }
44
- function getHistogramFromConfig(config, phase, name, help) {
45
- return typeof config[phase] === 'object'
46
- ? config[phase]
47
- : config[phase] === true
48
- ? createHistogram({
49
- histogram: new promClient.Histogram({
50
- name,
51
- help,
52
- labelNames: ['operationType', 'operationName'],
53
- registers: [config.registry || promClient.register],
54
- }),
55
- fillLabelsFn: params => ({
56
- operationName: params.operationName,
57
- operationType: params.operationType,
58
- }),
59
- })
60
- : undefined;
61
- }
62
- function extractDeprecatedFields(node, typeInfo) {
63
- const found = [];
64
- graphql.visit(node, graphql.visitWithTypeInfo(typeInfo, {
65
- Field: () => {
66
- const field = typeInfo.getFieldDef();
67
- if (field && (field.deprecationReason != null || field.isDeprecated)) {
68
- found.push({
69
- fieldName: field.name,
70
- typeName: typeInfo.getParentType().name || '',
71
- });
72
- }
73
- },
74
- }));
75
- return found;
76
- }
77
-
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.usePrometheus = exports.createSummary = exports.createHistogram = exports.createCounter = void 0;
78
4
  /* eslint-disable @typescript-eslint/no-non-null-asserted-optional-chain */
5
+ const core_1 = require("@envelop/core");
6
+ const graphql_1 = require("@graphql-tools/graphql");
7
+ const prom_client_1 = require("prom-client");
8
+ const utils_js_1 = require("./utils.js");
9
+ Object.defineProperty(exports, "createHistogram", { enumerable: true, get: function () { return utils_js_1.createHistogram; } });
10
+ Object.defineProperty(exports, "createCounter", { enumerable: true, get: function () { return utils_js_1.createCounter; } });
11
+ Object.defineProperty(exports, "createSummary", { enumerable: true, get: function () { return utils_js_1.createSummary; } });
79
12
  const promPluginContext = Symbol('promPluginContext');
80
13
  const promPluginExecutionStartTimeSymbol = Symbol('promPluginExecutionStartTimeSymbol');
81
14
  const usePrometheus = (config = {}) => {
82
15
  let typeInfo = null;
83
- const parseHistogram = getHistogramFromConfig(config, 'parse', 'graphql_envelop_phase_parse', 'Time spent on running GraphQL "parse" function');
84
- const validateHistogram = getHistogramFromConfig(config, 'validate', 'graphql_envelop_phase_validate', 'Time spent on running GraphQL "validate" function');
85
- const contextBuildingHistogram = getHistogramFromConfig(config, 'contextBuilding', 'graphql_envelop_phase_context', 'Time spent on building the GraphQL context');
86
- const executeHistogram = getHistogramFromConfig(config, 'execute', 'graphql_envelop_phase_execute', 'Time spent on running the GraphQL "execute" function');
16
+ const parseHistogram = (0, utils_js_1.getHistogramFromConfig)(config, 'parse', 'graphql_envelop_phase_parse', 'Time spent on running GraphQL "parse" function');
17
+ const validateHistogram = (0, utils_js_1.getHistogramFromConfig)(config, 'validate', 'graphql_envelop_phase_validate', 'Time spent on running GraphQL "validate" function');
18
+ const contextBuildingHistogram = (0, utils_js_1.getHistogramFromConfig)(config, 'contextBuilding', 'graphql_envelop_phase_context', 'Time spent on building the GraphQL context');
19
+ const executeHistogram = (0, utils_js_1.getHistogramFromConfig)(config, 'execute', 'graphql_envelop_phase_execute', 'Time spent on running the GraphQL "execute" function');
87
20
  const resolversHistogram = typeof config.resolvers === 'object'
88
21
  ? config.resolvers
89
22
  : config.resolvers === true
90
- ? createHistogram({
91
- histogram: new promClient.Histogram({
23
+ ? (0, utils_js_1.createHistogram)({
24
+ histogram: new prom_client_1.Histogram({
92
25
  name: 'graphql_envelop_execute_resolver',
93
26
  help: 'Time spent on running the GraphQL resolvers',
94
27
  labelNames: ['operationType', 'operationName', 'fieldName', 'typeName', 'returnType'],
95
- registers: [config.registry || promClient.register],
96
- }),
97
- fillLabelsFn: params => ({
98
- operationName: params.operationName,
99
- operationType: params.operationType,
100
- fieldName: params.info?.fieldName,
101
- typeName: params.info?.parentType.name,
102
- returnType: params.info?.returnType.toString(),
28
+ registers: [config.registry || prom_client_1.register],
103
29
  }),
30
+ fillLabelsFn: params => {
31
+ var _a, _b, _c;
32
+ return ({
33
+ operationName: params.operationName,
34
+ operationType: params.operationType,
35
+ fieldName: (_a = params.info) === null || _a === void 0 ? void 0 : _a.fieldName,
36
+ typeName: (_b = params.info) === null || _b === void 0 ? void 0 : _b.parentType.name,
37
+ returnType: (_c = params.info) === null || _c === void 0 ? void 0 : _c.returnType.toString(),
38
+ });
39
+ },
104
40
  })
105
41
  : undefined;
106
42
  const requestTotalHistogram = typeof config.requestTotalDuration === 'object'
107
43
  ? config.requestTotalDuration
108
44
  : config.requestTotalDuration === true
109
- ? createHistogram({
110
- histogram: new promClient.Histogram({
45
+ ? (0, utils_js_1.createHistogram)({
46
+ histogram: new prom_client_1.Histogram({
111
47
  name: 'graphql_envelop_request_duration',
112
48
  help: 'Time spent on running the GraphQL operation from parse to execute',
113
49
  labelNames: ['operationType', 'operationName'],
114
- registers: [config.registry || promClient.register],
50
+ registers: [config.registry || prom_client_1.register],
115
51
  }),
116
52
  fillLabelsFn: params => ({
117
53
  operationName: params.operationName,
@@ -122,12 +58,12 @@ const usePrometheus = (config = {}) => {
122
58
  const requestSummary = typeof config.requestSummary === 'object'
123
59
  ? config.requestSummary
124
60
  : config.requestSummary === true
125
- ? createSummary({
126
- summary: new promClient.Summary({
61
+ ? (0, utils_js_1.createSummary)({
62
+ summary: new prom_client_1.Summary({
127
63
  name: 'graphql_envelop_request_time_summary',
128
64
  help: 'Summary to measure the time to complete GraphQL operations',
129
65
  labelNames: ['operationType', 'operationName'],
130
- registers: [config.registry || promClient.register],
66
+ registers: [config.registry || prom_client_1.register],
131
67
  }),
132
68
  fillLabelsFn: params => ({
133
69
  operationName: params.operationName,
@@ -138,30 +74,33 @@ const usePrometheus = (config = {}) => {
138
74
  const errorsCounter = typeof config.errors === 'object'
139
75
  ? config.errors
140
76
  : config.errors === true
141
- ? createCounter({
142
- counter: new promClient.Counter({
77
+ ? (0, utils_js_1.createCounter)({
78
+ counter: new prom_client_1.Counter({
143
79
  name: 'graphql_envelop_error_result',
144
80
  help: 'Counts the amount of errors reported from all phases',
145
81
  labelNames: ['operationType', 'operationName', 'path', 'phase'],
146
- registers: [config.registry || promClient.register],
147
- }),
148
- fillLabelsFn: params => ({
149
- operationName: params.operationName,
150
- operationType: params.operationType,
151
- path: params.error?.path?.join('.'),
152
- phase: params.errorPhase,
82
+ registers: [config.registry || prom_client_1.register],
153
83
  }),
84
+ fillLabelsFn: params => {
85
+ var _a, _b;
86
+ return ({
87
+ operationName: params.operationName,
88
+ operationType: params.operationType,
89
+ path: (_b = (_a = params.error) === null || _a === void 0 ? void 0 : _a.path) === null || _b === void 0 ? void 0 : _b.join('.'),
90
+ phase: params.errorPhase,
91
+ });
92
+ },
154
93
  })
155
94
  : undefined;
156
95
  const reqCounter = typeof config.requestCount === 'object'
157
96
  ? config.requestCount
158
97
  : config.requestCount === true
159
- ? createCounter({
160
- counter: new promClient.Counter({
98
+ ? (0, utils_js_1.createCounter)({
99
+ counter: new prom_client_1.Counter({
161
100
  name: 'graphql_envelop_request',
162
101
  help: 'Counts the amount of GraphQL requests executed through Envelop',
163
102
  labelNames: ['operationType', 'operationName'],
164
- registers: [config.registry || promClient.register],
103
+ registers: [config.registry || prom_client_1.register],
165
104
  }),
166
105
  fillLabelsFn: params => ({
167
106
  operationName: params.operationName,
@@ -172,36 +111,39 @@ const usePrometheus = (config = {}) => {
172
111
  const deprecationCounter = typeof config.deprecatedFields === 'object'
173
112
  ? config.deprecatedFields
174
113
  : config.deprecatedFields === true
175
- ? createCounter({
176
- counter: new promClient.Counter({
114
+ ? (0, utils_js_1.createCounter)({
115
+ counter: new prom_client_1.Counter({
177
116
  name: 'graphql_envelop_deprecated_field',
178
117
  help: 'Counts the amount of deprecated fields used in selection sets',
179
118
  labelNames: ['operationType', 'operationName', 'fieldName', 'typeName'],
180
- registers: [config.registry || promClient.register],
181
- }),
182
- fillLabelsFn: params => ({
183
- operationName: params.operationName,
184
- operationType: params.operationType,
185
- fieldName: params.deprecationInfo?.fieldName,
186
- typeName: params.deprecationInfo?.typeName,
119
+ registers: [config.registry || prom_client_1.register],
187
120
  }),
121
+ fillLabelsFn: params => {
122
+ var _a, _b;
123
+ return ({
124
+ operationName: params.operationName,
125
+ operationType: params.operationType,
126
+ fieldName: (_a = params.deprecationInfo) === null || _a === void 0 ? void 0 : _a.fieldName,
127
+ typeName: (_b = params.deprecationInfo) === null || _b === void 0 ? void 0 : _b.typeName,
128
+ });
129
+ },
188
130
  })
189
131
  : undefined;
190
132
  const onParse = ({ context, extendContext, params }) => {
191
- if (config.skipIntrospection && core.isIntrospectionOperationString(params.source)) {
133
+ if (config.skipIntrospection && (0, core_1.isIntrospectionOperationString)(params.source)) {
192
134
  return;
193
135
  }
194
136
  const startTime = Date.now();
195
137
  return params => {
196
138
  const totalTime = (Date.now() - startTime) / 1000;
197
- const internalContext = createInternalContext(params.result);
139
+ const internalContext = (0, utils_js_1.createInternalContext)(params.result);
198
140
  if (internalContext) {
199
141
  extendContext({
200
142
  [promPluginContext]: internalContext,
201
143
  });
202
- parseHistogram?.histogram.observe(parseHistogram.fillLabelsFn(internalContext, context), totalTime);
144
+ parseHistogram === null || parseHistogram === void 0 ? void 0 : parseHistogram.histogram.observe(parseHistogram.fillLabelsFn(internalContext, context), totalTime);
203
145
  if (deprecationCounter && typeInfo) {
204
- const deprecatedFields = extractDeprecatedFields(internalContext.document, typeInfo);
146
+ const deprecatedFields = (0, utils_js_1.extractDeprecatedFields)(internalContext.document, typeInfo);
205
147
  if (deprecatedFields.length > 0) {
206
148
  for (const depField of deprecatedFields) {
207
149
  deprecationCounter.counter
@@ -216,11 +158,9 @@ const usePrometheus = (config = {}) => {
216
158
  }
217
159
  else {
218
160
  // means that we got a parse error, report it
219
- errorsCounter?.counter
220
- .labels({
161
+ errorsCounter === null || errorsCounter === void 0 ? void 0 : errorsCounter.counter.labels({
221
162
  phase: 'parse',
222
- })
223
- .inc();
163
+ }).inc();
224
164
  }
225
165
  };
226
166
  };
@@ -235,12 +175,10 @@ const usePrometheus = (config = {}) => {
235
175
  const labels = validateHistogram.fillLabelsFn(context[promPluginContext], context);
236
176
  validateHistogram.histogram.observe(labels, totalTime);
237
177
  if (!valid) {
238
- errorsCounter?.counter
239
- .labels({
178
+ errorsCounter === null || errorsCounter === void 0 ? void 0 : errorsCounter.counter.labels({
240
179
  ...labels,
241
180
  phase: 'validate',
242
- })
243
- .inc();
181
+ }).inc();
244
182
  }
245
183
  };
246
184
  }
@@ -263,17 +201,17 @@ const usePrometheus = (config = {}) => {
263
201
  return undefined;
264
202
  }
265
203
  const startTime = Date.now();
266
- reqCounter?.counter.labels(reqCounter.fillLabelsFn(args.contextValue[promPluginContext], args.contextValue)).inc();
204
+ reqCounter === null || reqCounter === void 0 ? void 0 : reqCounter.counter.labels(reqCounter.fillLabelsFn(args.contextValue[promPluginContext], args.contextValue)).inc();
267
205
  const result = {
268
206
  onExecuteDone: ({ result }) => {
269
207
  const totalTime = (Date.now() - startTime) / 1000;
270
208
  executeHistogram.histogram.observe(executeHistogram.fillLabelsFn(args.contextValue[promPluginContext], args.contextValue), totalTime);
271
- requestTotalHistogram?.histogram.observe(requestTotalHistogram.fillLabelsFn(args.contextValue[promPluginContext], args.contextValue), totalTime);
209
+ requestTotalHistogram === null || requestTotalHistogram === void 0 ? void 0 : requestTotalHistogram.histogram.observe(requestTotalHistogram.fillLabelsFn(args.contextValue[promPluginContext], args.contextValue), totalTime);
272
210
  if (requestSummary && args.contextValue[promPluginExecutionStartTimeSymbol]) {
273
211
  const summaryTime = (Date.now() - args.contextValue[promPluginExecutionStartTimeSymbol]) / 1000;
274
212
  requestSummary.summary.observe(requestSummary.fillLabelsFn(args.contextValue[promPluginContext], args.contextValue), summaryTime);
275
213
  }
276
- if (errorsCounter && !core.isAsyncIterable(result) && result.errors && result.errors.length > 0) {
214
+ if (errorsCounter && !(0, core_1.isAsyncIterable)(result) && result.errors && result.errors.length > 0) {
277
215
  for (const error of result.errors) {
278
216
  errorsCounter.counter
279
217
  .labels(errorsCounter.fillLabelsFn({
@@ -292,7 +230,7 @@ const usePrometheus = (config = {}) => {
292
230
  return {
293
231
  onResolverCalled: resolversHistogram
294
232
  ? ({ info, context }) => {
295
- const shouldTrace = shouldTraceFieldResolver(info, config.resolversWhitelist);
233
+ const shouldTrace = (0, utils_js_1.shouldTraceFieldResolver)(info, config.resolversWhitelist);
296
234
  if (!shouldTrace) {
297
235
  return undefined;
298
236
  }
@@ -313,7 +251,7 @@ const usePrometheus = (config = {}) => {
313
251
  });
314
252
  },
315
253
  onSchemaChange({ schema }) {
316
- typeInfo = new graphql.TypeInfo(schema);
254
+ typeInfo = new graphql_1.TypeInfo(schema);
317
255
  },
318
256
  onParse,
319
257
  onValidate,
@@ -321,8 +259,4 @@ const usePrometheus = (config = {}) => {
321
259
  onExecute,
322
260
  };
323
261
  };
324
-
325
- exports.createCounter = createCounter;
326
- exports.createHistogram = createHistogram;
327
- exports.createSummary = createSummary;
328
262
  exports.usePrometheus = usePrometheus;
@@ -0,0 +1 @@
1
+ {"type":"commonjs"}
package/cjs/utils.js ADDED
@@ -0,0 +1,81 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.extractDeprecatedFields = exports.getHistogramFromConfig = exports.createCounter = exports.createSummary = exports.createHistogram = exports.createInternalContext = exports.shouldTraceFieldResolver = void 0;
4
+ const graphql_1 = require("@graphql-tools/graphql");
5
+ const prom_client_1 = require("prom-client");
6
+ function shouldTraceFieldResolver(info, whitelist) {
7
+ if (!whitelist) {
8
+ return true;
9
+ }
10
+ const parentType = info.parentType.name;
11
+ const fieldName = info.fieldName;
12
+ const coordinate = `${parentType}.${fieldName}`;
13
+ return whitelist.includes(coordinate) || whitelist.includes(`${parentType}.*`);
14
+ }
15
+ exports.shouldTraceFieldResolver = shouldTraceFieldResolver;
16
+ function getOperation(document) {
17
+ return document.definitions[0];
18
+ }
19
+ function createInternalContext(parseResult) {
20
+ var _a;
21
+ if (parseResult === null) {
22
+ return null;
23
+ }
24
+ if (parseResult instanceof Error) {
25
+ return null;
26
+ }
27
+ const operation = getOperation(parseResult);
28
+ return {
29
+ document: parseResult,
30
+ operationName: ((_a = operation.name) === null || _a === void 0 ? void 0 : _a.value) || 'Anonymous',
31
+ operationType: operation.operation,
32
+ };
33
+ }
34
+ exports.createInternalContext = createInternalContext;
35
+ function createHistogram(options) {
36
+ return options;
37
+ }
38
+ exports.createHistogram = createHistogram;
39
+ function createSummary(options) {
40
+ return options;
41
+ }
42
+ exports.createSummary = createSummary;
43
+ function createCounter(options) {
44
+ return options;
45
+ }
46
+ exports.createCounter = createCounter;
47
+ function getHistogramFromConfig(config, phase, name, help) {
48
+ return typeof config[phase] === 'object'
49
+ ? config[phase]
50
+ : config[phase] === true
51
+ ? createHistogram({
52
+ histogram: new prom_client_1.Histogram({
53
+ name,
54
+ help,
55
+ labelNames: ['operationType', 'operationName'],
56
+ registers: [config.registry || prom_client_1.register],
57
+ }),
58
+ fillLabelsFn: params => ({
59
+ operationName: params.operationName,
60
+ operationType: params.operationType,
61
+ }),
62
+ })
63
+ : undefined;
64
+ }
65
+ exports.getHistogramFromConfig = getHistogramFromConfig;
66
+ function extractDeprecatedFields(node, typeInfo) {
67
+ const found = [];
68
+ (0, graphql_1.visit)(node, (0, graphql_1.visitWithTypeInfo)(typeInfo, {
69
+ Field: () => {
70
+ const field = typeInfo.getFieldDef();
71
+ if (field && (field.deprecationReason != null || field.isDeprecated)) {
72
+ found.push({
73
+ fieldName: field.name,
74
+ typeName: typeInfo.getParentType().name || '',
75
+ });
76
+ }
77
+ },
78
+ }));
79
+ return found;
80
+ }
81
+ exports.extractDeprecatedFields = extractDeprecatedFields;
package/esm/config.js ADDED
@@ -0,0 +1 @@
1
+ export {};
@@ -1,80 +1,12 @@
1
- import { isIntrospectionOperationString, isAsyncIterable } from '@envelop/core';
2
- import { visit, visitWithTypeInfo, TypeInfo } from 'graphql';
3
- import { Histogram, register, Summary, Counter } from 'prom-client';
4
-
5
- function shouldTraceFieldResolver(info, whitelist) {
6
- if (!whitelist) {
7
- return true;
8
- }
9
- const parentType = info.parentType.name;
10
- const fieldName = info.fieldName;
11
- const coordinate = `${parentType}.${fieldName}`;
12
- return whitelist.includes(coordinate) || whitelist.includes(`${parentType}.*`);
13
- }
14
- function getOperation(document) {
15
- return document.definitions[0];
16
- }
17
- function createInternalContext(parseResult) {
18
- if (parseResult === null) {
19
- return null;
20
- }
21
- if (parseResult instanceof Error) {
22
- return null;
23
- }
24
- const operation = getOperation(parseResult);
25
- return {
26
- document: parseResult,
27
- operationName: operation.name?.value || 'Anonymous',
28
- operationType: operation.operation,
29
- };
30
- }
31
- function createHistogram(options) {
32
- return options;
33
- }
34
- function createSummary(options) {
35
- return options;
36
- }
37
- function createCounter(options) {
38
- return options;
39
- }
40
- function getHistogramFromConfig(config, phase, name, help) {
41
- return typeof config[phase] === 'object'
42
- ? config[phase]
43
- : config[phase] === true
44
- ? createHistogram({
45
- histogram: new Histogram({
46
- name,
47
- help,
48
- labelNames: ['operationType', 'operationName'],
49
- registers: [config.registry || register],
50
- }),
51
- fillLabelsFn: params => ({
52
- operationName: params.operationName,
53
- operationType: params.operationType,
54
- }),
55
- })
56
- : undefined;
57
- }
58
- function extractDeprecatedFields(node, typeInfo) {
59
- const found = [];
60
- visit(node, visitWithTypeInfo(typeInfo, {
61
- Field: () => {
62
- const field = typeInfo.getFieldDef();
63
- if (field && (field.deprecationReason != null || field.isDeprecated)) {
64
- found.push({
65
- fieldName: field.name,
66
- typeName: typeInfo.getParentType().name || '',
67
- });
68
- }
69
- },
70
- }));
71
- return found;
72
- }
73
-
74
1
  /* eslint-disable @typescript-eslint/no-non-null-asserted-optional-chain */
2
+ import { isIntrospectionOperationString, isAsyncIterable, } from '@envelop/core';
3
+ import { TypeInfo } from '@graphql-tools/graphql';
4
+ import { Summary, Counter, Histogram, register as defaultRegistry } from 'prom-client';
5
+ import { getHistogramFromConfig, createHistogram, createCounter, shouldTraceFieldResolver, createInternalContext, extractDeprecatedFields, createSummary, } from './utils.js';
6
+ export { createCounter, createHistogram, createSummary };
75
7
  const promPluginContext = Symbol('promPluginContext');
76
8
  const promPluginExecutionStartTimeSymbol = Symbol('promPluginExecutionStartTimeSymbol');
77
- const usePrometheus = (config = {}) => {
9
+ export const usePrometheus = (config = {}) => {
78
10
  let typeInfo = null;
79
11
  const parseHistogram = getHistogramFromConfig(config, 'parse', 'graphql_envelop_phase_parse', 'Time spent on running GraphQL "parse" function');
80
12
  const validateHistogram = getHistogramFromConfig(config, 'validate', 'graphql_envelop_phase_validate', 'Time spent on running GraphQL "validate" function');
@@ -88,15 +20,18 @@ const usePrometheus = (config = {}) => {
88
20
  name: 'graphql_envelop_execute_resolver',
89
21
  help: 'Time spent on running the GraphQL resolvers',
90
22
  labelNames: ['operationType', 'operationName', 'fieldName', 'typeName', 'returnType'],
91
- registers: [config.registry || register],
92
- }),
93
- fillLabelsFn: params => ({
94
- operationName: params.operationName,
95
- operationType: params.operationType,
96
- fieldName: params.info?.fieldName,
97
- typeName: params.info?.parentType.name,
98
- returnType: params.info?.returnType.toString(),
23
+ registers: [config.registry || defaultRegistry],
99
24
  }),
25
+ fillLabelsFn: params => {
26
+ var _a, _b, _c;
27
+ return ({
28
+ operationName: params.operationName,
29
+ operationType: params.operationType,
30
+ fieldName: (_a = params.info) === null || _a === void 0 ? void 0 : _a.fieldName,
31
+ typeName: (_b = params.info) === null || _b === void 0 ? void 0 : _b.parentType.name,
32
+ returnType: (_c = params.info) === null || _c === void 0 ? void 0 : _c.returnType.toString(),
33
+ });
34
+ },
100
35
  })
101
36
  : undefined;
102
37
  const requestTotalHistogram = typeof config.requestTotalDuration === 'object'
@@ -107,7 +42,7 @@ const usePrometheus = (config = {}) => {
107
42
  name: 'graphql_envelop_request_duration',
108
43
  help: 'Time spent on running the GraphQL operation from parse to execute',
109
44
  labelNames: ['operationType', 'operationName'],
110
- registers: [config.registry || register],
45
+ registers: [config.registry || defaultRegistry],
111
46
  }),
112
47
  fillLabelsFn: params => ({
113
48
  operationName: params.operationName,
@@ -123,7 +58,7 @@ const usePrometheus = (config = {}) => {
123
58
  name: 'graphql_envelop_request_time_summary',
124
59
  help: 'Summary to measure the time to complete GraphQL operations',
125
60
  labelNames: ['operationType', 'operationName'],
126
- registers: [config.registry || register],
61
+ registers: [config.registry || defaultRegistry],
127
62
  }),
128
63
  fillLabelsFn: params => ({
129
64
  operationName: params.operationName,
@@ -139,14 +74,17 @@ const usePrometheus = (config = {}) => {
139
74
  name: 'graphql_envelop_error_result',
140
75
  help: 'Counts the amount of errors reported from all phases',
141
76
  labelNames: ['operationType', 'operationName', 'path', 'phase'],
142
- registers: [config.registry || register],
143
- }),
144
- fillLabelsFn: params => ({
145
- operationName: params.operationName,
146
- operationType: params.operationType,
147
- path: params.error?.path?.join('.'),
148
- phase: params.errorPhase,
77
+ registers: [config.registry || defaultRegistry],
149
78
  }),
79
+ fillLabelsFn: params => {
80
+ var _a, _b;
81
+ return ({
82
+ operationName: params.operationName,
83
+ operationType: params.operationType,
84
+ path: (_b = (_a = params.error) === null || _a === void 0 ? void 0 : _a.path) === null || _b === void 0 ? void 0 : _b.join('.'),
85
+ phase: params.errorPhase,
86
+ });
87
+ },
150
88
  })
151
89
  : undefined;
152
90
  const reqCounter = typeof config.requestCount === 'object'
@@ -157,7 +95,7 @@ const usePrometheus = (config = {}) => {
157
95
  name: 'graphql_envelop_request',
158
96
  help: 'Counts the amount of GraphQL requests executed through Envelop',
159
97
  labelNames: ['operationType', 'operationName'],
160
- registers: [config.registry || register],
98
+ registers: [config.registry || defaultRegistry],
161
99
  }),
162
100
  fillLabelsFn: params => ({
163
101
  operationName: params.operationName,
@@ -173,14 +111,17 @@ const usePrometheus = (config = {}) => {
173
111
  name: 'graphql_envelop_deprecated_field',
174
112
  help: 'Counts the amount of deprecated fields used in selection sets',
175
113
  labelNames: ['operationType', 'operationName', 'fieldName', 'typeName'],
176
- registers: [config.registry || register],
177
- }),
178
- fillLabelsFn: params => ({
179
- operationName: params.operationName,
180
- operationType: params.operationType,
181
- fieldName: params.deprecationInfo?.fieldName,
182
- typeName: params.deprecationInfo?.typeName,
114
+ registers: [config.registry || defaultRegistry],
183
115
  }),
116
+ fillLabelsFn: params => {
117
+ var _a, _b;
118
+ return ({
119
+ operationName: params.operationName,
120
+ operationType: params.operationType,
121
+ fieldName: (_a = params.deprecationInfo) === null || _a === void 0 ? void 0 : _a.fieldName,
122
+ typeName: (_b = params.deprecationInfo) === null || _b === void 0 ? void 0 : _b.typeName,
123
+ });
124
+ },
184
125
  })
185
126
  : undefined;
186
127
  const onParse = ({ context, extendContext, params }) => {
@@ -195,7 +136,7 @@ const usePrometheus = (config = {}) => {
195
136
  extendContext({
196
137
  [promPluginContext]: internalContext,
197
138
  });
198
- parseHistogram?.histogram.observe(parseHistogram.fillLabelsFn(internalContext, context), totalTime);
139
+ parseHistogram === null || parseHistogram === void 0 ? void 0 : parseHistogram.histogram.observe(parseHistogram.fillLabelsFn(internalContext, context), totalTime);
199
140
  if (deprecationCounter && typeInfo) {
200
141
  const deprecatedFields = extractDeprecatedFields(internalContext.document, typeInfo);
201
142
  if (deprecatedFields.length > 0) {
@@ -212,11 +153,9 @@ const usePrometheus = (config = {}) => {
212
153
  }
213
154
  else {
214
155
  // means that we got a parse error, report it
215
- errorsCounter?.counter
216
- .labels({
156
+ errorsCounter === null || errorsCounter === void 0 ? void 0 : errorsCounter.counter.labels({
217
157
  phase: 'parse',
218
- })
219
- .inc();
158
+ }).inc();
220
159
  }
221
160
  };
222
161
  };
@@ -231,12 +170,10 @@ const usePrometheus = (config = {}) => {
231
170
  const labels = validateHistogram.fillLabelsFn(context[promPluginContext], context);
232
171
  validateHistogram.histogram.observe(labels, totalTime);
233
172
  if (!valid) {
234
- errorsCounter?.counter
235
- .labels({
173
+ errorsCounter === null || errorsCounter === void 0 ? void 0 : errorsCounter.counter.labels({
236
174
  ...labels,
237
175
  phase: 'validate',
238
- })
239
- .inc();
176
+ }).inc();
240
177
  }
241
178
  };
242
179
  }
@@ -259,12 +196,12 @@ const usePrometheus = (config = {}) => {
259
196
  return undefined;
260
197
  }
261
198
  const startTime = Date.now();
262
- reqCounter?.counter.labels(reqCounter.fillLabelsFn(args.contextValue[promPluginContext], args.contextValue)).inc();
199
+ reqCounter === null || reqCounter === void 0 ? void 0 : reqCounter.counter.labels(reqCounter.fillLabelsFn(args.contextValue[promPluginContext], args.contextValue)).inc();
263
200
  const result = {
264
201
  onExecuteDone: ({ result }) => {
265
202
  const totalTime = (Date.now() - startTime) / 1000;
266
203
  executeHistogram.histogram.observe(executeHistogram.fillLabelsFn(args.contextValue[promPluginContext], args.contextValue), totalTime);
267
- requestTotalHistogram?.histogram.observe(requestTotalHistogram.fillLabelsFn(args.contextValue[promPluginContext], args.contextValue), totalTime);
204
+ requestTotalHistogram === null || requestTotalHistogram === void 0 ? void 0 : requestTotalHistogram.histogram.observe(requestTotalHistogram.fillLabelsFn(args.contextValue[promPluginContext], args.contextValue), totalTime);
268
205
  if (requestSummary && args.contextValue[promPluginExecutionStartTimeSymbol]) {
269
206
  const summaryTime = (Date.now() - args.contextValue[promPluginExecutionStartTimeSymbol]) / 1000;
270
207
  requestSummary.summary.observe(requestSummary.fillLabelsFn(args.contextValue[promPluginContext], args.contextValue), summaryTime);
@@ -317,5 +254,3 @@ const usePrometheus = (config = {}) => {
317
254
  onExecute,
318
255
  };
319
256
  };
320
-
321
- export { createCounter, createHistogram, createSummary, usePrometheus };
package/esm/utils.js ADDED
@@ -0,0 +1,71 @@
1
+ import { visit, visitWithTypeInfo, } from '@graphql-tools/graphql';
2
+ import { Histogram, register as defaultRegistry } from 'prom-client';
3
+ export function shouldTraceFieldResolver(info, whitelist) {
4
+ if (!whitelist) {
5
+ return true;
6
+ }
7
+ const parentType = info.parentType.name;
8
+ const fieldName = info.fieldName;
9
+ const coordinate = `${parentType}.${fieldName}`;
10
+ return whitelist.includes(coordinate) || whitelist.includes(`${parentType}.*`);
11
+ }
12
+ function getOperation(document) {
13
+ return document.definitions[0];
14
+ }
15
+ export function createInternalContext(parseResult) {
16
+ var _a;
17
+ if (parseResult === null) {
18
+ return null;
19
+ }
20
+ if (parseResult instanceof Error) {
21
+ return null;
22
+ }
23
+ const operation = getOperation(parseResult);
24
+ return {
25
+ document: parseResult,
26
+ operationName: ((_a = operation.name) === null || _a === void 0 ? void 0 : _a.value) || 'Anonymous',
27
+ operationType: operation.operation,
28
+ };
29
+ }
30
+ export function createHistogram(options) {
31
+ return options;
32
+ }
33
+ export function createSummary(options) {
34
+ return options;
35
+ }
36
+ export function createCounter(options) {
37
+ return options;
38
+ }
39
+ export function getHistogramFromConfig(config, phase, name, help) {
40
+ return typeof config[phase] === 'object'
41
+ ? config[phase]
42
+ : config[phase] === true
43
+ ? createHistogram({
44
+ histogram: new Histogram({
45
+ name,
46
+ help,
47
+ labelNames: ['operationType', 'operationName'],
48
+ registers: [config.registry || defaultRegistry],
49
+ }),
50
+ fillLabelsFn: params => ({
51
+ operationName: params.operationName,
52
+ operationType: params.operationType,
53
+ }),
54
+ })
55
+ : undefined;
56
+ }
57
+ export function extractDeprecatedFields(node, typeInfo) {
58
+ const found = [];
59
+ visit(node, visitWithTypeInfo(typeInfo, {
60
+ Field: () => {
61
+ const field = typeInfo.getFieldDef();
62
+ if (field && (field.deprecationReason != null || field.isDeprecated)) {
63
+ found.push({
64
+ fieldName: field.name,
65
+ typeName: typeInfo.getParentType().name || '',
66
+ });
67
+ }
68
+ },
69
+ }));
70
+ return found;
71
+ }
package/package.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "@envelop/prometheus",
3
- "version": "7.0.0-alpha-d0d0776.0",
3
+ "version": "7.0.0-alpha-ccec0fc.0",
4
4
  "sideEffects": false,
5
5
  "peerDependencies": {
6
- "@envelop/core": "3.0.0-alpha-d0d0776.0",
7
- "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0",
8
- "prom-client": "^13 || ^14.0.0"
6
+ "@envelop/core": "3.0.0-alpha-ccec0fc.0",
7
+ "prom-client": "^13 || ^14.0.0",
8
+ "@graphql-tools/graphql": "0.1.0-alpha-e7752ba5.0"
9
9
  },
10
10
  "repository": {
11
11
  "type": "git",
@@ -14,33 +14,42 @@
14
14
  },
15
15
  "author": "Dotan Simha <dotansimha@gmail.com>",
16
16
  "license": "MIT",
17
- "main": "index.js",
18
- "module": "index.mjs",
19
- "typings": "index.d.ts",
17
+ "main": "cjs/index.js",
18
+ "module": "esm/index.js",
19
+ "typings": "typings/index.d.ts",
20
20
  "typescript": {
21
- "definition": "index.d.ts"
21
+ "definition": "typings/index.d.ts"
22
22
  },
23
+ "type": "module",
23
24
  "exports": {
24
25
  ".": {
25
26
  "require": {
26
- "default": "./index.js",
27
- "types": "./index.d.ts"
27
+ "types": "./typings/index.d.ts",
28
+ "default": "./cjs/index.js"
28
29
  },
29
30
  "import": {
30
- "default": "./index.mjs",
31
- "types": "./index.d.ts"
31
+ "types": "./typings/index.d.ts",
32
+ "default": "./esm/index.js"
33
+ },
34
+ "default": {
35
+ "types": "./typings/index.d.ts",
36
+ "default": "./esm/index.js"
32
37
  }
33
38
  },
34
39
  "./*": {
35
40
  "require": {
36
- "default": "./*.js",
37
- "types": "./*.d.ts"
41
+ "types": "./typings/*.d.ts",
42
+ "default": "./cjs/*.js"
38
43
  },
39
44
  "import": {
40
- "default": "./*.mjs",
41
- "types": "./*.d.ts"
45
+ "types": "./typings/*.d.ts",
46
+ "default": "./esm/*.js"
47
+ },
48
+ "default": {
49
+ "types": "./typings/*.d.ts",
50
+ "default": "./esm/*.js"
42
51
  }
43
52
  },
44
53
  "./package.json": "./package.json"
45
54
  }
46
- }
55
+ }
@@ -1,4 +1,4 @@
1
- import { createCounter, createHistogram, createSummary } from './utils';
1
+ import { createCounter, createHistogram, createSummary } from './utils.js';
2
2
  import { Registry } from 'prom-client';
3
3
  export declare type PrometheusTracingPluginConfig = {
4
4
  requestCount?: boolean | ReturnType<typeof createCounter>;
@@ -1,6 +1,6 @@
1
1
  import { Plugin } from '@envelop/core';
2
- import { createHistogram, createCounter, FillLabelsFnParams, createSummary } from './utils';
3
- import { PrometheusTracingPluginConfig } from './config';
2
+ import { createHistogram, createCounter, FillLabelsFnParams, createSummary } from './utils.js';
3
+ import { PrometheusTracingPluginConfig } from './config.js';
4
4
  export { PrometheusTracingPluginConfig, createCounter, createHistogram, createSummary, FillLabelsFnParams };
5
5
  declare const promPluginContext: unique symbol;
6
6
  declare const promPluginExecutionStartTimeSymbol: unique symbol;
@@ -1,6 +1,6 @@
1
- import { GraphQLError, DocumentNode, OperationDefinitionNode, GraphQLResolveInfo, TypeInfo, ASTNode } from 'graphql';
1
+ import { GraphQLError, DocumentNode, OperationDefinitionNode, GraphQLResolveInfo, TypeInfo, ASTNode } from '@graphql-tools/graphql';
2
2
  import { AfterParseEventPayload } from '@envelop/core';
3
- import { PrometheusTracingPluginConfig } from './config';
3
+ import { PrometheusTracingPluginConfig } from './config.js';
4
4
  import { Counter, Histogram, Summary } from 'prom-client';
5
5
  export declare type DeprecatedFieldInfo = {
6
6
  fieldName: string;