@mimik/request-retry 2.0.12 → 2.1.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.
Files changed (3) hide show
  1. package/README.md +4 -0
  2. package/index.js +25 -4
  3. package/package.json +5 -5
package/README.md CHANGED
@@ -29,6 +29,10 @@ The following properties are added to the `options` object under the `retry` pro
29
29
  - *responseName*: name to associate with the response. The default is `response`or is the value is not a string or and empty string it is set to `response`,
30
30
  - timeout `{int}`: in seconds the timeout to be set for the request and retries. If the timeout is reached, a TimeoutError will be generated. The default is `50 seconds`. If the value is less than `10 seconds` the value is set to `10 seconds`, and if the value is more than `120 seconds` the value is set to `120 seconds`,
31
31
  - retryStrategy `{function}`: function describing the retry strategy. The parameters are (`nbRetry`, `err`, `options`, `correlationId`). Must return a `boolean`, if not the function strategy is ignored.
32
+ The following properties are added to the `options` object under the 'metrics' property:
33
+ - HTTPRequestDuration `function`: prom-client function to measure the delay of the request,
34
+ - url: optional url to be added for labelling the metric. If not present the url of the request will be used.
35
+
32
36
  The `default` retryStategy is:
33
37
 
34
38
  ``` javascript
package/index.js CHANGED
@@ -49,6 +49,10 @@ Promise.config({ cancellation: true });
49
49
  * - *responseName*: name to associate with the response. The default is `response`or is the value is not a string or and empty string it is set to `response`,
50
50
  * - timeout `{int}`: in seconds the timeout to be set for the request and retries. If the timeout is reached, a TimeoutError will be generated. The default is `50 seconds`. If the value is less than `10 seconds` the value is set to `10 seconds`, and if the value is more than `120 seconds` the value is set to `120 seconds`,
51
51
  * - retryStrategy `{function}`: function describing the retry strategy. The parameters are (`nbRetry`, `err`, `options`, `correlationId`). Must return a `boolean`, if not the function strategy is ignored.
52
+ * The following properties are added to the `options` object under the 'metrics' property:
53
+ * - HTTPRequestDuration `function`: prom-client function to measure the delay of the request,
54
+ * - url: optional url to be added for labelling the metric. If not present the url of the request will be used.
55
+ *
52
56
  * The `default` retryStategy is:
53
57
  *
54
58
  *``` javascript
@@ -68,7 +72,10 @@ Promise.config({ cancellation: true });
68
72
  * - `qs` is used to assign to `params`
69
73
  */
70
74
  const rpRetry = (origOptions) => {
75
+ const startHrTime = process.hrtime();
71
76
  const options = origOptions;
77
+ const { metrics } = options;
78
+ const enteredUrl = options.uri || options.url;
72
79
  const correlationId = (options.headers && options.headers['x-correlation-id']) ? options.headers['x-correlation-id'] : getCorrelationId();
73
80
  const errors = [];
74
81
  const delayPromises = [];
@@ -77,13 +84,25 @@ const rpRetry = (origOptions) => {
77
84
  const logLevelLength = Object.keys(logLevel).length;
78
85
  let nbRetries = 0;
79
86
  let mainTimeout;
87
+ const measure = (statusCode) => {
88
+ if (metrics && metrics.HTTPRequestDuration) {
89
+ const elapsedHrTime = process.hrtime(startHrTime);
90
+ const elapsedTimeInMs = elapsedHrTime[0] * 1000 + elapsedHrTime[1] / 1e6;
91
+
92
+ metrics.HTTPRequestDuration
93
+ .labels('rpRetry', options.method, metrics.url || enteredUrl, enteredUrl.includes('?'), statusCode)
94
+ .observe(elapsedTimeInMs);
95
+ }
96
+ };
80
97
 
81
98
  if (!options.headers) options.headers = { 'user-agent': setUserAgent() };
82
99
  else if (!options.headers['user-agent']) options.headers['user-agent'] = setUserAgent();
100
+ const optionsInfo = { ...options };
101
+ delete optionsInfo.metrics;
83
102
 
84
103
  const retryProcess = (nbRetry) => rp(options)
85
104
  .then((response) => {
86
- const info = { options, nbRetries, errors };
105
+ const info = { options: optionsInfo, nbRetries, errors };
87
106
 
88
107
  if (logLevel.response) {
89
108
  info[logLevel.responseName] = setResponse(response, logLevel.responseDetails);
@@ -136,7 +155,7 @@ const rpRetry = (origOptions) => {
136
155
  error = getRichError(
137
156
  'System',
138
157
  'request error response',
139
- { options },
158
+ { options: optionsInfo },
140
159
  error,
141
160
  logLevel.error || ((logLevelLength === 0) ? DEFAULT_LOGLEVEL_ERROR : undefined),
142
161
  correlationId,
@@ -145,17 +164,19 @@ const rpRetry = (origOptions) => {
145
164
  }, criteria.timeout * 1000);
146
165
  });
147
166
 
148
- if (logLevel.request) logger[logLevel.request]('making a request', { options, criteria }, correlationId);
149
- else if (logLevelLength === 0) logger[DEFAULT_LOGLEVEL_REQUEST]('making a request', { options, criteria }, correlationId);
167
+ if (logLevel.request) logger[logLevel.request]('making a request', { options: optionsInfo, criteria }, correlationId);
168
+ else if (logLevelLength === 0) logger[DEFAULT_LOGLEVEL_REQUEST]('making a request', { options: optionsInfo, criteria }, correlationId);
150
169
  return Promise.race([retryPromise, mainTimeoutPromise])
151
170
  .then((result) => {
152
171
  mainTimeoutPromise.cancel('main timeout');
153
172
  clearTimeout(mainTimeout);
173
+ measure(200);
154
174
  return result;
155
175
  })
156
176
  .catch((err) => {
157
177
  mainTimeoutPromise.cancel(`main timeout error: ${err.message}`);
158
178
  clearTimeout(mainTimeout);
179
+ measure(err.statusCode || 500);
159
180
  throw err;
160
181
  });
161
182
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mimik/request-retry",
3
- "version": "2.0.12",
3
+ "version": "2.1.0",
4
4
  "description": "Request retry wrapping axios",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -31,7 +31,7 @@
31
31
  "dependencies": {
32
32
  "@mimik/request-helper": "^1.7.7",
33
33
  "@mimik/response-helper": "^2.6.2",
34
- "@mimik/sumologic-winston-logger": "^1.6.11",
34
+ "@mimik/sumologic-winston-logger": "^1.6.13",
35
35
  "axios": "1.2.1",
36
36
  "bluebird": "3.7.2",
37
37
  "lodash": "4.17.21"
@@ -42,7 +42,7 @@
42
42
  "acorn": "8.8.1",
43
43
  "body-parser": "1.20.1",
44
44
  "chai": "4.3.7",
45
- "eslint": "8.28.0",
45
+ "eslint": "8.30.0",
46
46
  "eslint-config-airbnb": "19.0.4",
47
47
  "eslint-plugin-import": "2.26.0",
48
48
  "eslint-plugin-jsx-a11y": "6.6.1",
@@ -51,10 +51,10 @@
51
51
  "express": "4.18.2",
52
52
  "husky": "8.0.2",
53
53
  "jsdoc-to-markdown": "8.0.0",
54
- "mocha": "10.1.0",
54
+ "mocha": "10.2.0",
55
55
  "mochawesome": "7.1.3",
56
56
  "nyc": "15.1.0",
57
- "sinon": "15.0.0",
57
+ "sinon": "15.0.1",
58
58
  "verror": "1.10.1"
59
59
  }
60
60
  }