@artilleryio/int-core 2.24.0 → 2.25.0-37061d0

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.
@@ -4,7 +4,6 @@
4
4
 
5
5
  const async = require('async');
6
6
  const _ = require('lodash');
7
- const request = require('got');
8
7
  const tough = require('tough-cookie');
9
8
  const debug = require('debug')('http');
10
9
  const debugRequests = require('debug')('http:request');
@@ -30,6 +29,30 @@ const crypto = require('node:crypto');
30
29
 
31
30
  module.exports = HttpEngine;
32
31
 
32
+ const GOT_OPTION_NAMES = [
33
+ 'url',
34
+ 'searchParams',
35
+ 'method',
36
+ 'headers',
37
+ 'body',
38
+ 'json',
39
+ 'form',
40
+ 'allowGetBody',
41
+ 'timeout',
42
+ 'retry',
43
+ 'encoding',
44
+ 'cookieJar',
45
+ 'followRedirect',
46
+ 'maxRedirects',
47
+ 'decompress',
48
+ 'http2',
49
+ 'agent',
50
+ 'username',
51
+ 'password',
52
+ 'https',
53
+ 'throwHttpErrors'
54
+ ];
55
+
33
56
  const DEFAULT_AGENT_OPTIONS = {
34
57
  keepAlive: true,
35
58
  keepAliveMsec: 1000
@@ -126,6 +149,66 @@ function HttpEngine(script) {
126
149
  }
127
150
  }
128
151
 
152
+ HttpEngine.prototype.init = async function () {
153
+ this.request = (await import('got')).default;
154
+ };
155
+
156
+ HttpEngine.prototype._isDistributedTracingEnabled = function (config) {
157
+ const dtConfig = config.http?.distributedTracing;
158
+ if (!dtConfig) {
159
+ return false;
160
+ }
161
+
162
+ // Handle both boolean and object forms
163
+ if (typeof dtConfig === 'boolean') {
164
+ return dtConfig;
165
+ }
166
+
167
+ if (typeof dtConfig === 'object' && dtConfig.enabled !== undefined) {
168
+ return dtConfig.enabled;
169
+ }
170
+
171
+ // Default to true if distributedTracing is set but enabled is not specified
172
+ return true;
173
+ };
174
+
175
+ HttpEngine.prototype._generateTraceparent = function (config) {
176
+ // W3C Trace Context format: version-trace-id-parent-id-trace-flags
177
+ const version = '00';
178
+
179
+ // Get configuration
180
+ const dtConfig = config.http?.distributedTracing;
181
+ let sampled = true; // Default to sampled
182
+ let traceIdPrefix = 'a9'; // Default prefix
183
+
184
+ if (typeof dtConfig === 'object') {
185
+ if (dtConfig.sampled !== undefined) {
186
+ sampled = dtConfig.sampled;
187
+ }
188
+ if (dtConfig.traceIdPrefix !== undefined) {
189
+ traceIdPrefix = dtConfig.traceIdPrefix;
190
+ }
191
+ }
192
+
193
+ // Validate and normalize prefix (must be valid hex, max 8 chars)
194
+ traceIdPrefix = traceIdPrefix.toLowerCase().replace(/[^0-9a-f]/g, '').slice(0, 8);
195
+ if (traceIdPrefix.length === 0) {
196
+ traceIdPrefix = 'a9'; // Fallback to default if invalid
197
+ }
198
+
199
+ // Generate trace-id with prefix (32 hex chars total)
200
+ const remainingBytes = Math.ceil((32 - traceIdPrefix.length) / 2);
201
+ const randomPart = crypto.randomBytes(remainingBytes).toString('hex');
202
+ const traceId = (traceIdPrefix + randomPart).slice(0, 32);
203
+
204
+ // Generate 8-byte parent-id (16 hex chars)
205
+ const parentId = crypto.randomBytes(8).toString('hex');
206
+
207
+ const traceFlags = sampled ? '01' : '00';
208
+
209
+ return `${version}-${traceId}-${parentId}-${traceFlags}`;
210
+ };
211
+
129
212
  HttpEngine.prototype.createScenario = function (scenarioSpec, ee) {
130
213
  ensurePropertyIsAList(scenarioSpec, 'beforeRequest');
131
214
  ensurePropertyIsAList(scenarioSpec, 'afterResponse');
@@ -274,7 +357,7 @@ HttpEngine.prototype.step = function step(requestSpec, ee, opts) {
274
357
  const requestParams = _.extend(_.clone(params), {
275
358
  url: maybePrependBase(params.url || params.uri, config), // *NOT* templating here
276
359
  method: method,
277
- timeout: timeout * 1000,
360
+ timeout: timeout,
278
361
  uuid: crypto.randomUUID()
279
362
  });
280
363
 
@@ -683,10 +766,21 @@ HttpEngine.prototype.step = function step(requestSpec, ee, opts) {
683
766
  );
684
767
  }
685
768
 
686
- requestParams.retry = 0; // disable retries - ignored when using streams
769
+ requestParams.retry = { limit: 0 }; // disable retries - ignored when using streams
770
+ // Convert scalar seconds to Got v14 timeout object right before request
771
+ const gotOptions = _.pick(requestParams, GOT_OPTION_NAMES);
772
+ gotOptions.timeout = { response: requestParams.timeout * 1000 };
773
+
774
+ // Add W3C Trace Context headers if distributed tracing is enabled
775
+ if (self._isDistributedTracingEnabled(config)) {
776
+ const traceparent = self._generateTraceparent(config);
777
+ gotOptions.headers = gotOptions.headers || {};
778
+ gotOptions.headers.traceparent = traceparent;
779
+ }
687
780
 
688
781
  let totalDownloaded = 0;
689
- request(_.omit(requestParams, ['uuid']))
782
+ self
783
+ .request(gotOptions)
690
784
  .on('request', (req) => {
691
785
  ee.emit('trace:http:request', requestParams, requestParams.uuid);
692
786
 
@@ -937,10 +1031,16 @@ HttpEngine.prototype.compile = function compile(tasks, _scenarioSpec, ee) {
937
1031
  context = await promisify(task)(context);
938
1032
  } catch (taskErr) {
939
1033
  ee.emit('error', taskErr.code || taskErr.message);
940
- return callback(taskErr, context); // calling back for now for existing client code
1034
+ if (callback) {
1035
+ return callback(taskErr, context);
1036
+ }
1037
+ throw taskErr;
941
1038
  }
942
1039
  }
943
- return callback(null, context);
1040
+ if (callback) {
1041
+ return callback(null, context);
1042
+ }
1043
+ return context;
944
1044
  };
945
1045
  };
946
1046
 
@@ -23,6 +23,10 @@ function SocketIoEngine(script) {
23
23
  this.httpDelegate = new EngineHttp(script);
24
24
  }
25
25
 
26
+ SocketIoEngine.prototype.init = async function () {
27
+ await this.httpDelegate.init();
28
+ };
29
+
26
30
  SocketIoEngine.prototype.createScenario = function (scenarioSpec, ee) {
27
31
  // Adds scenario overridden configuration into the static config
28
32
  this.socketioOpts = { ...this.socketioOpts, ...scenarioSpec.socketio };
package/lib/runner.js CHANGED
@@ -163,6 +163,16 @@ async function runner(script, payload, options, callback) {
163
163
  warnings
164
164
  );
165
165
 
166
+ for (const e of runnerEngines) {
167
+ if (
168
+ e &&
169
+ typeof e.init === 'function' &&
170
+ e.init.constructor.name === 'AsyncFunction'
171
+ ) {
172
+ await e.init();
173
+ }
174
+ }
175
+
166
176
  const promise = new Promise((resolve, _reject) => {
167
177
  ee.run = (contextVars) => {
168
178
  const runState = {
@@ -506,12 +516,23 @@ function $randomString(length = 10) {
506
516
  return s;
507
517
  }
508
518
 
509
- function handleScriptHook(hook, script, hookEvents, contextVars = {}) {
519
+ async function handleScriptHook(hook, script, hookEvents, contextVars = {}) {
510
520
  if (!script[hook]) {
511
521
  return {};
512
522
  }
513
523
 
514
524
  const { loadedEngines: engines } = loadEngines(script, hookEvents);
525
+
526
+ for (const e of engines) {
527
+ if (
528
+ e &&
529
+ typeof e.init === 'function' &&
530
+ e.init.constructor.name === 'AsyncFunction'
531
+ ) {
532
+ await e.init();
533
+ }
534
+ }
535
+
515
536
  const ee = new EventEmitter();
516
537
 
517
538
  return new Promise((resolve, reject) => {
package/package.json CHANGED
@@ -1,16 +1,16 @@
1
1
  {
2
2
  "name": "@artilleryio/int-core",
3
- "version": "2.24.0",
3
+ "version": "2.25.0-37061d0",
4
4
  "main": "./index.js",
5
5
  "license": "MPL-2.0",
6
6
  "dependencies": {
7
- "@artilleryio/int-commons": "2.20.0",
7
+ "@artilleryio/int-commons": "2.21.0-37061d0",
8
8
  "@artilleryio/sketches-js": "^2.1.1",
9
9
  "agentkeepalive": "^4.6.0",
10
10
  "arrivals": "^2.1.2",
11
11
  "async": "^2.6.4",
12
12
  "chalk": "^2.4.2",
13
- "cheerio": "^1.1.2",
13
+ "cheerio": "^1.2.0",
14
14
  "cookie-parser": "^1.4.7",
15
15
  "csv-parse": "^4.16.3",
16
16
  "debug": "^4.4.3",
@@ -22,10 +22,10 @@
22
22
  "fast-deep-equal": "^3.1.3",
23
23
  "filtrex": "^0.5.4",
24
24
  "form-data": "^4.0.5",
25
- "got": "^11.8.5",
25
+ "got": "^14.6.6",
26
26
  "hpagent": "^0.1.1",
27
27
  "https-proxy-agent": "^5.0.0",
28
- "lodash": "^4.17.21",
28
+ "lodash": "^4.18.0",
29
29
  "ms": "^2.1.3",
30
30
  "protobufjs": "^7.5.4",
31
31
  "socket.io-client": "^4.8.3",