@forgehive/task 0.2.2 → 0.2.4
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/dist/index.d.ts +12 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +66 -13
- package/dist/index.js.map +1 -1
- package/dist/test/add-listener-with-boundaries.test.js +78 -7
- package/dist/test/add-listener-with-boundaries.test.js.map +1 -1
- package/dist/test/add-listener.test.js +36 -0
- package/dist/test/add-listener.test.js.map +1 -1
- package/dist/test/boundary-modes.test.js +45 -5
- package/dist/test/boundary-modes.test.js.map +1 -1
- package/dist/test/execution-record-boundaries.test.js +12 -2
- package/dist/test/execution-record-boundaries.test.js.map +1 -1
- package/dist/test/integration-enhanced-records.test.d.ts +2 -0
- package/dist/test/integration-enhanced-records.test.d.ts.map +1 -0
- package/dist/test/integration-enhanced-records.test.js +467 -0
- package/dist/test/integration-enhanced-records.test.js.map +1 -0
- package/dist/test/listen-execution-records.test.d.ts +2 -0
- package/dist/test/listen-execution-records.test.d.ts.map +1 -0
- package/dist/test/listen-execution-records.test.js +223 -0
- package/dist/test/listen-execution-records.test.js.map +1 -0
- package/dist/test/metrics-collection.test.d.ts +2 -0
- package/dist/test/metrics-collection.test.d.ts.map +1 -0
- package/dist/test/metrics-collection.test.js +409 -0
- package/dist/test/metrics-collection.test.js.map +1 -0
- package/dist/test/performance-edge-cases.test.d.ts +2 -0
- package/dist/test/performance-edge-cases.test.d.ts.map +1 -0
- package/dist/test/performance-edge-cases.test.js +502 -0
- package/dist/test/performance-edge-cases.test.js.map +1 -0
- package/dist/test/run-boundary.test.js +27 -3
- package/dist/test/run-boundary.test.js.map +1 -1
- package/dist/test/safe-replay-complex-boundary.test.js +110 -9
- package/dist/test/safe-replay-complex-boundary.test.js.map +1 -1
- package/dist/test/safe-replay.test.js +35 -5
- package/dist/test/safe-replay.test.js.map +1 -1
- package/dist/test/safe-run.test.js +46 -4
- package/dist/test/safe-run.test.js.map +1 -1
- package/dist/test/setmetrics-boundary.test.d.ts +2 -0
- package/dist/test/setmetrics-boundary.test.d.ts.map +1 -0
- package/dist/test/setmetrics-boundary.test.js +195 -0
- package/dist/test/setmetrics-boundary.test.js.map +1 -0
- package/dist/test/task-with-boundaries.test.js +63 -2
- package/dist/test/task-with-boundaries.test.js.map +1 -1
- package/dist/test/timing-capture.test.d.ts +2 -0
- package/dist/test/timing-capture.test.d.ts.map +1 -0
- package/dist/test/timing-capture.test.js +304 -0
- package/dist/test/timing-capture.test.js.map +1 -0
- package/dist/test/timing-utilities.test.d.ts +2 -0
- package/dist/test/timing-utilities.test.d.ts.map +1 -0
- package/dist/test/timing-utilities.test.js +127 -0
- package/dist/test/timing-utilities.test.js.map +1 -0
- package/dist/types.d.ts +93 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +78 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/boundary.d.ts +3 -0
- package/dist/utils/boundary.d.ts.map +1 -1
- package/dist/utils/boundary.js +11 -2
- package/dist/utils/boundary.js.map +1 -1
- package/package.json +3 -2
- package/src/index.ts +97 -14
- package/src/test/add-listener-with-boundaries.test.ts +78 -7
- package/src/test/add-listener.test.ts +36 -0
- package/src/test/boundary-modes.test.ts +45 -5
- package/src/test/execution-record-boundaries.test.ts +12 -2
- package/src/test/listen-execution-records.test.ts +295 -0
- package/src/test/metrics-collection.test.ts +476 -0
- package/src/test/performance-edge-cases.test.ts +596 -0
- package/src/test/run-boundary.test.ts +27 -3
- package/src/test/safe-replay-complex-boundary.test.ts +115 -10
- package/src/test/safe-replay.test.ts +35 -5
- package/src/test/safe-run.test.ts +46 -4
- package/src/test/setmetrics-boundary.test.ts +223 -0
- package/src/test/task-with-boundaries.test.ts +71 -5
- package/src/test/timing-capture.test.ts +348 -0
- package/src/test/timing-utilities.test.ts +145 -0
- package/src/types.ts +139 -0
- package/src/utils/boundary.ts +15 -2
package/dist/utils/boundary.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { TimingInfo } from '../types';
|
|
1
2
|
type BaseBoundary = (...args: unknown[]) => unknown;
|
|
2
3
|
export type Mode = 'proxy' | 'proxy-pass' | 'proxy-catch' | 'replay';
|
|
3
4
|
/**
|
|
@@ -15,6 +16,7 @@ export type BoundarySuccessRecord<TInput = unknown[], TOutput = unknown> = {
|
|
|
15
16
|
input: TInput;
|
|
16
17
|
output: TOutput;
|
|
17
18
|
error?: null;
|
|
19
|
+
timing: TimingInfo;
|
|
18
20
|
};
|
|
19
21
|
/**
|
|
20
22
|
* Error record for a boundary function call
|
|
@@ -24,6 +26,7 @@ export type BoundaryErrorRecord<TInput = unknown[]> = {
|
|
|
24
26
|
input: TInput;
|
|
25
27
|
output?: null;
|
|
26
28
|
error: string;
|
|
29
|
+
timing: TimingInfo;
|
|
27
30
|
};
|
|
28
31
|
/**
|
|
29
32
|
* Represents a record of a boundary function call - either success or error
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"boundary.d.ts","sourceRoot":"","sources":["../../src/utils/boundary.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"boundary.d.ts","sourceRoot":"","sources":["../../src/utils/boundary.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAiB,MAAM,UAAU,CAAA;AAGpD,KAAK,YAAY,GAAG,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,CAAA;AAEnD,MAAM,MAAM,IAAI,GAAG,OAAO,GAAG,YAAY,GAAG,aAAa,GAAG,QAAQ,CAAA;AAEpE;;;;GAIG;AAEH,MAAM,MAAM,gBAAgB,CAAC,OAAO,GAAG,GAAG,IAAI,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;AAElF;;;;GAIG;AACH,MAAM,MAAM,qBAAqB,CAAC,MAAM,GAAG,OAAO,EAAE,EAAE,OAAO,GAAG,OAAO,IAAI;IACzE,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,OAAO,CAAC;IAChB,KAAK,CAAC,EAAE,IAAI,CAAC;IACb,MAAM,EAAE,UAAU,CAAC;CACpB,CAAA;AAED;;;GAGG;AACH,MAAM,MAAM,mBAAmB,CAAC,MAAM,GAAG,OAAO,EAAE,IAAI;IACpD,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,IAAI,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,UAAU,CAAC;CACpB,CAAA;AAED;;;;GAIG;AACH,MAAM,MAAM,cAAc,CAAC,MAAM,GAAG,OAAO,EAAE,EAAE,OAAO,GAAG,OAAO,IAC9D,qBAAqB,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,mBAAmB,CAAC,MAAM,CAAC,CAAC;AAEvE;;GAEG;AACH,MAAM,MAAM,gBAAgB,GAAG,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,cAAc,CAAC,CAAC,CAAC;AAErE;;GAEG;AACH,MAAM,WAAW,uBAAuB,CAAC,IAAI,SAAS,gBAAgB,GAAG,gBAAgB;IACvF,CAAC,GAAG,IAAI,EAAE,UAAU,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAA;IACtD,OAAO,EAAE,MAAM,KAAK,CAAC,cAAc,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAA;IACjF,OAAO,EAAE,CAAC,OAAO,EAAE,KAAK,CAAC,cAAc,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,IAAI,CAAA;IAC9F,OAAO,EAAE,MAAM,IAAI,CAAA;IACnB,OAAO,EAAE,CAAC,OAAO,EAAE,IAAI,KAAK,IAAI,CAAA;IAChC,QAAQ,EAAE,MAAM,IAAI,CAAA;IACpB,OAAO,EAAE,MAAM,IAAI,CAAA;IACnB,UAAU,EAAE,MAAM,KAAK,CAAC,cAAc,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAA;CACrF;AAED;;GAEG;AACH,MAAM,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAA;AAEzD;;GAEG;AACH,MAAM,MAAM,iBAAiB,CAAC,CAAC,SAAS,UAAU,GAAG,UAAU,IAAI;KAChE,CAAC,IAAI,MAAM,CAAC,GAAG,uBAAuB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;CAC9C,CAAA;AAED,eAAO,MAAM,cAAc,GAAI,IAAI,SAAS,YAAY,EAAE,IAAI,IAAI,KAAG,uBAAuB,CAAC,IAAI,SAAS,gBAAgB,GAAG,IAAI,GAAG,KAAK,CA2IxI,CAAA"}
|
package/dist/utils/boundary.js
CHANGED
|
@@ -35,6 +35,7 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
36
|
exports.createBoundary = void 0;
|
|
37
37
|
const assert = __importStar(require("assert"));
|
|
38
|
+
const types_1 = require("../types");
|
|
38
39
|
const createBoundary = (fn) => {
|
|
39
40
|
let runLog = [];
|
|
40
41
|
let cacheTape = [];
|
|
@@ -79,6 +80,8 @@ const createBoundary = (fn) => {
|
|
|
79
80
|
})();
|
|
80
81
|
}
|
|
81
82
|
return await (async () => {
|
|
83
|
+
const timer = types_1.TimingTracker.create();
|
|
84
|
+
timer.start();
|
|
82
85
|
let result, error;
|
|
83
86
|
try {
|
|
84
87
|
result = await fn(...args);
|
|
@@ -86,6 +89,10 @@ const createBoundary = (fn) => {
|
|
|
86
89
|
catch (e) {
|
|
87
90
|
error = e;
|
|
88
91
|
}
|
|
92
|
+
const timing = timer.end();
|
|
93
|
+
if (!timing) {
|
|
94
|
+
throw new Error('Failed to capture timing information');
|
|
95
|
+
}
|
|
89
96
|
if (typeof error !== 'undefined') {
|
|
90
97
|
const prevRecord = findRecord(args, cacheTape);
|
|
91
98
|
if (mode === 'proxy-catch' && typeof prevRecord !== 'undefined') {
|
|
@@ -97,7 +104,8 @@ const createBoundary = (fn) => {
|
|
|
97
104
|
// Create an error record
|
|
98
105
|
const errorRecord = {
|
|
99
106
|
input: args,
|
|
100
|
-
error: error.message
|
|
107
|
+
error: error.message,
|
|
108
|
+
timing
|
|
101
109
|
};
|
|
102
110
|
if (hasRun) {
|
|
103
111
|
runLog.push(errorRecord);
|
|
@@ -110,7 +118,8 @@ const createBoundary = (fn) => {
|
|
|
110
118
|
// Create a success record
|
|
111
119
|
const successRecord = {
|
|
112
120
|
input: args,
|
|
113
|
-
output: result
|
|
121
|
+
output: result,
|
|
122
|
+
timing
|
|
114
123
|
};
|
|
115
124
|
if (hasRun) {
|
|
116
125
|
runLog.push(successRecord);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"boundary.js","sourceRoot":"","sources":["../../src/utils/boundary.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,+CAAgC;
|
|
1
|
+
{"version":3,"file":"boundary.js","sourceRoot":"","sources":["../../src/utils/boundary.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@forgehive/task",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.4",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.js",
|
|
@@ -25,6 +25,7 @@
|
|
|
25
25
|
"build": "tsc",
|
|
26
26
|
"dev": "tsc --watch",
|
|
27
27
|
"clean": "rm -rf dist",
|
|
28
|
-
"test": "jest"
|
|
28
|
+
"test": "jest",
|
|
29
|
+
"lint:fix": "eslint src --ext .ts --fix"
|
|
29
30
|
}
|
|
30
31
|
}
|
package/src/index.ts
CHANGED
|
@@ -8,6 +8,13 @@ import {
|
|
|
8
8
|
type BoundaryRecord,
|
|
9
9
|
type BoundaryTapeData
|
|
10
10
|
} from './utils/boundary'
|
|
11
|
+
import {
|
|
12
|
+
TimingTracker,
|
|
13
|
+
type Metric,
|
|
14
|
+
type TimingInfo,
|
|
15
|
+
validateMetric,
|
|
16
|
+
createMetric
|
|
17
|
+
} from './types'
|
|
11
18
|
|
|
12
19
|
export interface Task {
|
|
13
20
|
id: string;
|
|
@@ -31,6 +38,17 @@ export type {
|
|
|
31
38
|
BoundaryTapeData
|
|
32
39
|
} from './utils/boundary'
|
|
33
40
|
|
|
41
|
+
// Re-export timing and metrics types for external use
|
|
42
|
+
export type {
|
|
43
|
+
TimingInfo,
|
|
44
|
+
Metric,
|
|
45
|
+
BoundaryTimingRecord,
|
|
46
|
+
BaseExecutionRecord
|
|
47
|
+
} from './types'
|
|
48
|
+
|
|
49
|
+
// Re-export timing and metrics utilities for external use
|
|
50
|
+
export { TimingTracker, validateMetric, createMetric }
|
|
51
|
+
|
|
34
52
|
// Re-export Schema for external use
|
|
35
53
|
export { Schema }
|
|
36
54
|
|
|
@@ -50,9 +68,6 @@ export interface ReplayConfig<B extends Boundaries = Boundaries> {
|
|
|
50
68
|
}
|
|
51
69
|
}
|
|
52
70
|
|
|
53
|
-
// ToDo: Add a type for the boundaries data
|
|
54
|
-
|
|
55
|
-
|
|
56
71
|
// Make BoundaryLog generic
|
|
57
72
|
export type BoundaryLog<I extends unknown[] = unknown[], O = unknown> = BoundaryRecord<I, O>;
|
|
58
73
|
|
|
@@ -79,6 +94,10 @@ export interface ExecutionRecord<InputType = unknown, OutputType = unknown, B ex
|
|
|
79
94
|
taskName?: string
|
|
80
95
|
/** Additional context metadata */
|
|
81
96
|
metadata?: Record<string, string>
|
|
97
|
+
/** Array of collected metrics */
|
|
98
|
+
metrics?: Metric[]
|
|
99
|
+
/** Main function execution timing */
|
|
100
|
+
timing?: TimingInfo
|
|
82
101
|
/** The type of execution record - computed from output/error state */
|
|
83
102
|
type: 'success' | 'error' | 'pending'
|
|
84
103
|
}
|
|
@@ -143,6 +162,7 @@ export type InferSchemaType<S> = S extends Schema<any> ? InferSchema<S> : Record
|
|
|
143
162
|
// When adding new execution boundaries, add their types here
|
|
144
163
|
export type ExecutionRecordBoundaries = {
|
|
145
164
|
setMetadata: (key: string, value: string) => Promise<void>
|
|
165
|
+
setMetrics: (metric: Metric) => Promise<void>
|
|
146
166
|
// Future execution boundaries can be added here:
|
|
147
167
|
// setContext: (context: Record<string, unknown>) => Promise<void>
|
|
148
168
|
// addTag: (tag: string) => Promise<void>
|
|
@@ -172,7 +192,11 @@ export const Task = class Task<
|
|
|
172
192
|
B extends Boundaries = Boundaries,
|
|
173
193
|
Func extends BaseFunction = BaseFunction
|
|
174
194
|
> implements TaskInstanceType<Func, B> {
|
|
175
|
-
public version: string = '0.1.
|
|
195
|
+
public version: string = '0.1.8'
|
|
196
|
+
|
|
197
|
+
// Static property for global listener
|
|
198
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
199
|
+
static globalListener?: (record: ExecutionRecord<any, any, any>) => Promise<void>
|
|
176
200
|
|
|
177
201
|
_fn: Func
|
|
178
202
|
_mode: Mode
|
|
@@ -190,6 +214,29 @@ export const Task = class Task<
|
|
|
190
214
|
_schema: Schema<Record<string, SchemaType>> | undefined
|
|
191
215
|
_listener?: ((record: ExecutionRecord<Parameters<Func>[0], ReturnType<Func>, B>) => void) | undefined
|
|
192
216
|
|
|
217
|
+
// Static method to set global listener
|
|
218
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
219
|
+
static listenExecutionRecords(listener: (record: ExecutionRecord<any, any, any>) => Promise<void>): void {
|
|
220
|
+
this.globalListener = listener
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// Static method to emit to global listener with error handling
|
|
224
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
225
|
+
static emitExecutionRecord(record: ExecutionRecord<any, any, any>): void {
|
|
226
|
+
if (this.globalListener) {
|
|
227
|
+
// Call listener on next tick to avoid blocking task execution
|
|
228
|
+
process.nextTick(async () => {
|
|
229
|
+
try {
|
|
230
|
+
await this.globalListener!(record)
|
|
231
|
+
} catch (error) {
|
|
232
|
+
// Log error but don't affect task execution
|
|
233
|
+
// eslint-disable-next-line no-console
|
|
234
|
+
console.error('ExecutionRecord listener error:', error)
|
|
235
|
+
}
|
|
236
|
+
})
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
|
|
193
240
|
constructor (fn: Func, conf: TaskConfig<B> = {
|
|
194
241
|
name: undefined,
|
|
195
242
|
description: undefined,
|
|
@@ -306,9 +353,13 @@ export const Task = class Task<
|
|
|
306
353
|
Plus all the boundary data
|
|
307
354
|
*/
|
|
308
355
|
emit (data: ExecutionRecord<Parameters<Func>[0], ReturnType<Func>, B>): void {
|
|
309
|
-
|
|
356
|
+
// Emit to instance listener
|
|
357
|
+
if (typeof this._listener !== 'undefined') {
|
|
358
|
+
this._listener(data)
|
|
359
|
+
}
|
|
310
360
|
|
|
311
|
-
|
|
361
|
+
// Emit to global listener (non-blocking)
|
|
362
|
+
Task.emitExecutionRecord(data)
|
|
312
363
|
}
|
|
313
364
|
|
|
314
365
|
getBoundaries (): WrappedBoundaries<B> {
|
|
@@ -373,16 +424,29 @@ export const Task = class Task<
|
|
|
373
424
|
* 2. Update the ExecutionRecordBoundaries type to include the new boundary
|
|
374
425
|
* 3. That's it! The boundary will be available in all tasks automatically
|
|
375
426
|
*/
|
|
376
|
-
_createExecutionBoundaries(metadata: Record<string, string
|
|
427
|
+
_createExecutionBoundaries(metadata: Record<string, string>, metrics: Metric[]): Record<string, WrappedBoundaryFunction> {
|
|
377
428
|
return {
|
|
378
429
|
// Allows setting metadata key-value pairs from within task execution
|
|
379
430
|
setMetadata: createBoundary(async (...args: unknown[]): Promise<void> => {
|
|
380
431
|
const [key, value] = args as [string, string]
|
|
381
432
|
metadata[key] = value
|
|
433
|
+
}),
|
|
434
|
+
|
|
435
|
+
// Allows setting metrics from within task execution
|
|
436
|
+
setMetrics: createBoundary(async (...args: unknown[]): Promise<void> => {
|
|
437
|
+
const [metric] = args as [Metric]
|
|
438
|
+
|
|
439
|
+
// Validate the metric
|
|
440
|
+
if (!validateMetric(metric)) {
|
|
441
|
+
throw new Error(`Invalid metric provided: ${JSON.stringify(metric)}`)
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
// Add to metrics array
|
|
445
|
+
metrics.push(metric)
|
|
382
446
|
})
|
|
383
447
|
|
|
384
448
|
// Future execution boundaries can be added here:
|
|
385
|
-
//
|
|
449
|
+
// setContext: createBoundary(async (...args: unknown[]): Promise<void> => { ... }),
|
|
386
450
|
}
|
|
387
451
|
}
|
|
388
452
|
|
|
@@ -441,12 +505,16 @@ export const Task = class Task<
|
|
|
441
505
|
// Need to implement that task have a ctx and setMetadata({key, value}) boundary
|
|
442
506
|
const metadata = {} as Record<string, string>
|
|
443
507
|
|
|
508
|
+
// Metrics array is empty at start. Then will be populated during task execution
|
|
509
|
+
const metrics: Metric[] = []
|
|
510
|
+
|
|
444
511
|
// Initialize log item (without type initially)
|
|
445
512
|
const logItemBase = {
|
|
446
513
|
input: argv as Parameters<Func>[0],
|
|
447
514
|
boundaries: {} as BoundaryLogsFor<B>,
|
|
448
515
|
taskName: this._name,
|
|
449
|
-
metadata: metadata || {}
|
|
516
|
+
metadata: metadata || {},
|
|
517
|
+
metrics
|
|
450
518
|
}
|
|
451
519
|
|
|
452
520
|
// Create the log item with computed type
|
|
@@ -462,8 +530,8 @@ export const Task = class Task<
|
|
|
462
530
|
mode: this._mode
|
|
463
531
|
})
|
|
464
532
|
|
|
465
|
-
// Create and inject execution record boundaries (setMetadata, etc.)
|
|
466
|
-
const executionRecordBoundaries = this._createExecutionBoundaries(metadata)
|
|
533
|
+
// Create and inject execution record boundaries (setMetadata, setMetrics, etc.)
|
|
534
|
+
const executionRecordBoundaries = this._createExecutionBoundaries(metadata, metrics)
|
|
467
535
|
const allBoundaries = {
|
|
468
536
|
...executionBoundaries,
|
|
469
537
|
...executionRecordBoundaries
|
|
@@ -504,6 +572,10 @@ export const Task = class Task<
|
|
|
504
572
|
let output: Awaited<ReturnType<Func>> | null = null
|
|
505
573
|
let error: Error | null = null
|
|
506
574
|
|
|
575
|
+
// Start timing for main function execution
|
|
576
|
+
const timer = TimingTracker.create()
|
|
577
|
+
timer.start()
|
|
578
|
+
|
|
507
579
|
try {
|
|
508
580
|
// Execute the task function
|
|
509
581
|
output = await this._fn(
|
|
@@ -520,6 +592,12 @@ export const Task = class Task<
|
|
|
520
592
|
error = new Error(errorMessage)
|
|
521
593
|
}
|
|
522
594
|
|
|
595
|
+
// Capture timing for main function execution
|
|
596
|
+
const timing = timer.end()
|
|
597
|
+
if (timing) {
|
|
598
|
+
logItem.timing = timing
|
|
599
|
+
}
|
|
600
|
+
|
|
523
601
|
// Process boundary data after execution (both success and error cases)
|
|
524
602
|
const boundariesRunLog: BoundaryLogsFor<B> = {} as BoundaryLogsFor<B>
|
|
525
603
|
|
|
@@ -571,12 +649,17 @@ export const Task = class Task<
|
|
|
571
649
|
// Extract the input from the execution log
|
|
572
650
|
const argv = executionLog.input
|
|
573
651
|
|
|
652
|
+
// Initialize metrics array for replay - start with original metrics if any
|
|
653
|
+
const metrics: Metric[] = executionLog.metrics ? [...executionLog.metrics] : []
|
|
654
|
+
|
|
574
655
|
// Initialize log item for this replay (without type initially)
|
|
575
656
|
const logItemBase = {
|
|
576
657
|
input: argv,
|
|
577
658
|
boundaries: {} as BoundaryLogsFor<B>,
|
|
578
659
|
taskName: this._name,
|
|
579
|
-
metadata: executionLog.metadata || {}
|
|
660
|
+
metadata: executionLog.metadata || {},
|
|
661
|
+
metrics,
|
|
662
|
+
timing: executionLog.timing // Preserve original timing
|
|
580
663
|
}
|
|
581
664
|
|
|
582
665
|
// Create the log item with computed type
|
|
@@ -607,10 +690,10 @@ export const Task = class Task<
|
|
|
607
690
|
boundaryModes: config.boundaries
|
|
608
691
|
})
|
|
609
692
|
|
|
610
|
-
// Create and inject execution record boundaries (setMetadata, etc.)
|
|
693
|
+
// Create and inject execution record boundaries (setMetadata, setMetrics, etc.)
|
|
611
694
|
// Clone the metadata to avoid mutating the original metadata
|
|
612
695
|
const replayMetadata = { ...(logItem.metadata || {}) }
|
|
613
|
-
const executionRecordBoundaries = this._createExecutionBoundaries(replayMetadata)
|
|
696
|
+
const executionRecordBoundaries = this._createExecutionBoundaries(replayMetadata, metrics)
|
|
614
697
|
const allBoundaries = {
|
|
615
698
|
...executionBoundaries,
|
|
616
699
|
...executionRecordBoundaries
|
|
@@ -30,11 +30,22 @@ describe('Listener with boundaries', () => {
|
|
|
30
30
|
boundaries: {
|
|
31
31
|
getTen: [{
|
|
32
32
|
input: [],
|
|
33
|
-
output: 10
|
|
33
|
+
output: 10,
|
|
34
|
+
timing: expect.objectContaining({
|
|
35
|
+
startTime: expect.any(Number),
|
|
36
|
+
endTime: expect.any(Number),
|
|
37
|
+
duration: expect.any(Number)
|
|
38
|
+
})
|
|
34
39
|
}]
|
|
35
40
|
},
|
|
36
41
|
taskName: 'test',
|
|
37
42
|
metadata: {},
|
|
43
|
+
metrics: [],
|
|
44
|
+
timing: expect.objectContaining({
|
|
45
|
+
startTime: expect.any(Number),
|
|
46
|
+
endTime: expect.any(Number),
|
|
47
|
+
duration: expect.any(Number)
|
|
48
|
+
}),
|
|
38
49
|
type: 'success'
|
|
39
50
|
}])
|
|
40
51
|
})
|
|
@@ -73,11 +84,22 @@ describe('Listener with boundaries', () => {
|
|
|
73
84
|
boundaries: {
|
|
74
85
|
getTen: [{
|
|
75
86
|
input: [],
|
|
76
|
-
error: 'Network error'
|
|
87
|
+
error: 'Network error',
|
|
88
|
+
timing: expect.objectContaining({
|
|
89
|
+
startTime: expect.any(Number),
|
|
90
|
+
endTime: expect.any(Number),
|
|
91
|
+
duration: expect.any(Number)
|
|
92
|
+
})
|
|
77
93
|
}]
|
|
78
94
|
},
|
|
79
95
|
taskName: 'test',
|
|
80
96
|
metadata: {},
|
|
97
|
+
metrics: [],
|
|
98
|
+
timing: expect.objectContaining({
|
|
99
|
+
startTime: expect.any(Number),
|
|
100
|
+
endTime: expect.any(Number),
|
|
101
|
+
duration: expect.any(Number)
|
|
102
|
+
}),
|
|
81
103
|
type: 'error'
|
|
82
104
|
}])
|
|
83
105
|
})
|
|
@@ -109,11 +131,22 @@ describe('Listener with boundaries', () => {
|
|
|
109
131
|
boundaries: {
|
|
110
132
|
addNumbers: [{
|
|
111
133
|
input: [3, 7],
|
|
112
|
-
output: 10
|
|
134
|
+
output: 10,
|
|
135
|
+
timing: expect.objectContaining({
|
|
136
|
+
startTime: expect.any(Number),
|
|
137
|
+
endTime: expect.any(Number),
|
|
138
|
+
duration: expect.any(Number)
|
|
139
|
+
})
|
|
113
140
|
}]
|
|
114
141
|
},
|
|
115
142
|
taskName: 'test',
|
|
116
143
|
metadata: {},
|
|
144
|
+
metrics: [],
|
|
145
|
+
timing: expect.objectContaining({
|
|
146
|
+
startTime: expect.any(Number),
|
|
147
|
+
endTime: expect.any(Number),
|
|
148
|
+
duration: expect.any(Number)
|
|
149
|
+
}),
|
|
117
150
|
type: 'success'
|
|
118
151
|
}])
|
|
119
152
|
})
|
|
@@ -147,11 +180,22 @@ describe('Listener with boundaries', () => {
|
|
|
147
180
|
boundaries: {
|
|
148
181
|
processValue: [{
|
|
149
182
|
input: [undefined],
|
|
150
|
-
output: 0
|
|
183
|
+
output: 0,
|
|
184
|
+
timing: expect.objectContaining({
|
|
185
|
+
startTime: expect.any(Number),
|
|
186
|
+
endTime: expect.any(Number),
|
|
187
|
+
duration: expect.any(Number)
|
|
188
|
+
})
|
|
151
189
|
}]
|
|
152
190
|
},
|
|
153
191
|
taskName: 'test',
|
|
154
192
|
metadata: {},
|
|
193
|
+
metrics: [],
|
|
194
|
+
timing: expect.objectContaining({
|
|
195
|
+
startTime: expect.any(Number),
|
|
196
|
+
endTime: expect.any(Number),
|
|
197
|
+
duration: expect.any(Number)
|
|
198
|
+
}),
|
|
155
199
|
type: 'success'
|
|
156
200
|
}])
|
|
157
201
|
})
|
|
@@ -187,16 +231,32 @@ describe('Listener with boundaries', () => {
|
|
|
187
231
|
multiplyByTwo: [
|
|
188
232
|
{
|
|
189
233
|
input: [3],
|
|
190
|
-
output: 6
|
|
234
|
+
output: 6,
|
|
235
|
+
timing: expect.objectContaining({
|
|
236
|
+
startTime: expect.any(Number),
|
|
237
|
+
endTime: expect.any(Number),
|
|
238
|
+
duration: expect.any(Number)
|
|
239
|
+
})
|
|
191
240
|
},
|
|
192
241
|
{
|
|
193
242
|
input: [6],
|
|
194
|
-
output: 12
|
|
243
|
+
output: 12,
|
|
244
|
+
timing: expect.objectContaining({
|
|
245
|
+
startTime: expect.any(Number),
|
|
246
|
+
endTime: expect.any(Number),
|
|
247
|
+
duration: expect.any(Number)
|
|
248
|
+
})
|
|
195
249
|
}
|
|
196
250
|
]
|
|
197
251
|
},
|
|
198
252
|
taskName: 'test',
|
|
199
253
|
metadata: {},
|
|
254
|
+
metrics: [],
|
|
255
|
+
timing: expect.objectContaining({
|
|
256
|
+
startTime: expect.any(Number),
|
|
257
|
+
endTime: expect.any(Number),
|
|
258
|
+
duration: expect.any(Number)
|
|
259
|
+
}),
|
|
200
260
|
type: 'success'
|
|
201
261
|
}])
|
|
202
262
|
})
|
|
@@ -238,11 +298,22 @@ describe('Listener with boundaries', () => {
|
|
|
238
298
|
boundaries: {
|
|
239
299
|
getResult: [{
|
|
240
300
|
input: [3],
|
|
241
|
-
error: 'Number too small'
|
|
301
|
+
error: 'Number too small',
|
|
302
|
+
timing: expect.objectContaining({
|
|
303
|
+
startTime: expect.any(Number),
|
|
304
|
+
endTime: expect.any(Number),
|
|
305
|
+
duration: expect.any(Number)
|
|
306
|
+
})
|
|
242
307
|
}]
|
|
243
308
|
},
|
|
244
309
|
taskName: 'test',
|
|
245
310
|
metadata: {},
|
|
311
|
+
metrics: [],
|
|
312
|
+
timing: expect.objectContaining({
|
|
313
|
+
startTime: expect.any(Number),
|
|
314
|
+
endTime: expect.any(Number),
|
|
315
|
+
duration: expect.any(Number)
|
|
316
|
+
}),
|
|
246
317
|
type: 'success'
|
|
247
318
|
}])
|
|
248
319
|
})
|
|
@@ -18,6 +18,12 @@ describe('Add listener', () => {
|
|
|
18
18
|
boundaries: {},
|
|
19
19
|
taskName: undefined,
|
|
20
20
|
metadata: {},
|
|
21
|
+
metrics: [],
|
|
22
|
+
timing: expect.objectContaining({
|
|
23
|
+
startTime: expect.any(Number),
|
|
24
|
+
endTime: expect.any(Number),
|
|
25
|
+
duration: expect.any(Number)
|
|
26
|
+
}),
|
|
21
27
|
type: 'success'
|
|
22
28
|
}])
|
|
23
29
|
})
|
|
@@ -44,6 +50,12 @@ describe('Add listener', () => {
|
|
|
44
50
|
boundaries: {},
|
|
45
51
|
taskName: undefined,
|
|
46
52
|
metadata: {},
|
|
53
|
+
metrics: [],
|
|
54
|
+
timing: expect.objectContaining({
|
|
55
|
+
startTime: expect.any(Number),
|
|
56
|
+
endTime: expect.any(Number),
|
|
57
|
+
duration: expect.any(Number)
|
|
58
|
+
}),
|
|
47
59
|
type: 'error'
|
|
48
60
|
}])
|
|
49
61
|
})
|
|
@@ -73,6 +85,12 @@ describe('Add listener', () => {
|
|
|
73
85
|
boundaries: {},
|
|
74
86
|
taskName: undefined,
|
|
75
87
|
metadata: {},
|
|
88
|
+
metrics: [],
|
|
89
|
+
timing: expect.objectContaining({
|
|
90
|
+
startTime: expect.any(Number),
|
|
91
|
+
endTime: expect.any(Number),
|
|
92
|
+
duration: expect.any(Number)
|
|
93
|
+
}),
|
|
76
94
|
type: 'error'
|
|
77
95
|
}])
|
|
78
96
|
})
|
|
@@ -97,6 +115,12 @@ describe('Add listener', () => {
|
|
|
97
115
|
boundaries: {},
|
|
98
116
|
taskName: undefined,
|
|
99
117
|
metadata: {},
|
|
118
|
+
metrics: [],
|
|
119
|
+
timing: expect.objectContaining({
|
|
120
|
+
startTime: expect.any(Number),
|
|
121
|
+
endTime: expect.any(Number),
|
|
122
|
+
duration: expect.any(Number)
|
|
123
|
+
}),
|
|
100
124
|
type: 'success'
|
|
101
125
|
},
|
|
102
126
|
{
|
|
@@ -105,6 +129,12 @@ describe('Add listener', () => {
|
|
|
105
129
|
boundaries: {},
|
|
106
130
|
taskName: undefined,
|
|
107
131
|
metadata: {},
|
|
132
|
+
metrics: [],
|
|
133
|
+
timing: expect.objectContaining({
|
|
134
|
+
startTime: expect.any(Number),
|
|
135
|
+
endTime: expect.any(Number),
|
|
136
|
+
duration: expect.any(Number)
|
|
137
|
+
}),
|
|
108
138
|
type: 'success'
|
|
109
139
|
}
|
|
110
140
|
])
|
|
@@ -132,6 +162,12 @@ describe('Add listener', () => {
|
|
|
132
162
|
boundaries: {},
|
|
133
163
|
taskName: undefined,
|
|
134
164
|
metadata: {},
|
|
165
|
+
metrics: [],
|
|
166
|
+
timing: expect.objectContaining({
|
|
167
|
+
startTime: expect.any(Number),
|
|
168
|
+
endTime: expect.any(Number),
|
|
169
|
+
duration: expect.any(Number)
|
|
170
|
+
}),
|
|
135
171
|
type: 'success'
|
|
136
172
|
}])
|
|
137
173
|
})
|
|
@@ -47,7 +47,15 @@ describe('Proxy pass mode', function () {
|
|
|
47
47
|
},
|
|
48
48
|
boundariesData: {
|
|
49
49
|
fetchIncrement: [
|
|
50
|
-
{
|
|
50
|
+
{
|
|
51
|
+
input: [{ value: 5 }],
|
|
52
|
+
output: 5,
|
|
53
|
+
timing: {
|
|
54
|
+
startTime: 1000,
|
|
55
|
+
endTime: 1100,
|
|
56
|
+
duration: 100
|
|
57
|
+
}
|
|
58
|
+
}
|
|
51
59
|
]
|
|
52
60
|
},
|
|
53
61
|
mode: 'proxy-pass'
|
|
@@ -76,7 +84,15 @@ describe('Proxy pass mode', function () {
|
|
|
76
84
|
},
|
|
77
85
|
boundariesData: {
|
|
78
86
|
fetchIncrement: [
|
|
79
|
-
{
|
|
87
|
+
{
|
|
88
|
+
input: [{ value: 6 }],
|
|
89
|
+
output: 5,
|
|
90
|
+
timing: {
|
|
91
|
+
startTime: 1000,
|
|
92
|
+
endTime: 1100,
|
|
93
|
+
duration: 100
|
|
94
|
+
}
|
|
95
|
+
}
|
|
80
96
|
]
|
|
81
97
|
},
|
|
82
98
|
mode: 'proxy-pass'
|
|
@@ -108,7 +124,15 @@ describe('Proxy catch mode', function () {
|
|
|
108
124
|
},
|
|
109
125
|
boundariesData: {
|
|
110
126
|
fetchIncrement: [
|
|
111
|
-
{
|
|
127
|
+
{
|
|
128
|
+
input: [{ value: 5 }],
|
|
129
|
+
output: 5,
|
|
130
|
+
timing: {
|
|
131
|
+
startTime: 1000,
|
|
132
|
+
endTime: 1100,
|
|
133
|
+
duration: 100
|
|
134
|
+
}
|
|
135
|
+
}
|
|
112
136
|
]
|
|
113
137
|
},
|
|
114
138
|
mode: 'proxy-catch'
|
|
@@ -137,7 +161,15 @@ describe('Proxy catch mode', function () {
|
|
|
137
161
|
},
|
|
138
162
|
boundariesData: {
|
|
139
163
|
fetchIncrement: [
|
|
140
|
-
{
|
|
164
|
+
{
|
|
165
|
+
input: [{ value: 5 }],
|
|
166
|
+
output: 5,
|
|
167
|
+
timing: {
|
|
168
|
+
startTime: 1000,
|
|
169
|
+
endTime: 1100,
|
|
170
|
+
duration: 100
|
|
171
|
+
}
|
|
172
|
+
}
|
|
141
173
|
]
|
|
142
174
|
},
|
|
143
175
|
mode: 'proxy-catch'
|
|
@@ -169,7 +201,15 @@ describe('Replay mode', function () {
|
|
|
169
201
|
},
|
|
170
202
|
boundariesData: {
|
|
171
203
|
fetchIncrement: [
|
|
172
|
-
{
|
|
204
|
+
{
|
|
205
|
+
input: [{ value: 5 }],
|
|
206
|
+
output: 5,
|
|
207
|
+
timing: {
|
|
208
|
+
startTime: 1000,
|
|
209
|
+
endTime: 1100,
|
|
210
|
+
duration: 100
|
|
211
|
+
}
|
|
212
|
+
}
|
|
173
213
|
]
|
|
174
214
|
},
|
|
175
215
|
mode: 'replay'
|
|
@@ -92,13 +92,23 @@ describe('execution-record-boundaries', () => {
|
|
|
92
92
|
expect(record.boundaries.multiply).toHaveLength(1)
|
|
93
93
|
expect(record.boundaries.multiply[0]).toEqual({
|
|
94
94
|
input: [3],
|
|
95
|
-
output: 6
|
|
95
|
+
output: 6,
|
|
96
|
+
timing: expect.objectContaining({
|
|
97
|
+
startTime: expect.any(Number),
|
|
98
|
+
endTime: expect.any(Number),
|
|
99
|
+
duration: expect.any(Number)
|
|
100
|
+
})
|
|
96
101
|
})
|
|
97
102
|
|
|
98
103
|
expect(record.boundaries.fetchData).toHaveLength(1)
|
|
99
104
|
expect(record.boundaries.fetchData[0]).toEqual({
|
|
100
105
|
input: ['test'],
|
|
101
|
-
output: 'fetched-test'
|
|
106
|
+
output: 'fetched-test',
|
|
107
|
+
timing: expect.objectContaining({
|
|
108
|
+
startTime: expect.any(Number),
|
|
109
|
+
endTime: expect.any(Number),
|
|
110
|
+
duration: expect.any(Number)
|
|
111
|
+
})
|
|
102
112
|
})
|
|
103
113
|
})
|
|
104
114
|
|