@loadmill/executer 0.1.51 → 0.1.54

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 (39) hide show
  1. package/dist/mill-version.js +1 -1
  2. package/dist/sequence.d.ts +1 -1
  3. package/dist/sequence.js +12 -5
  4. package/dist/sequence.js.map +1 -1
  5. package/dist/single-runner.d.ts +1 -0
  6. package/dist/single-runner.js +1 -1
  7. package/dist/single-runner.js.map +1 -1
  8. package/package.json +3 -3
  9. package/src/asserter.ts +0 -137
  10. package/src/errors.ts +0 -10
  11. package/src/extraction-combiner.ts +0 -110
  12. package/src/failures.ts +0 -79
  13. package/src/message-creators.ts +0 -44
  14. package/src/mill-info.ts +0 -81
  15. package/src/mill-version.ts +0 -7
  16. package/src/post-script/ast-walker/index.ts +0 -160
  17. package/src/post-script/ast-walker/type-guard.ts +0 -73
  18. package/src/post-script/ast-walker/types.ts +0 -35
  19. package/src/post-script/console-log.ts +0 -24
  20. package/src/post-script/parser/acorn-js-parser.ts +0 -8
  21. package/src/post-script/parser/js-parser.ts +0 -22
  22. package/src/post-script/parser/parser.ts +0 -5
  23. package/src/post-script/post-script-executor.ts +0 -93
  24. package/src/post-script/virtual-machine/virtual-machine.ts +0 -15
  25. package/src/post-script/virtual-machine/vm2-virtual-machine.ts +0 -45
  26. package/src/report-types.ts +0 -127
  27. package/src/request-sequence-result.ts +0 -63
  28. package/src/request-stats.ts +0 -20
  29. package/src/res-keeper.ts +0 -53
  30. package/src/sampler.ts +0 -133
  31. package/src/sequence.ts +0 -1109
  32. package/src/single-runner.ts +0 -66
  33. package/src/test-run-event-emitter.ts +0 -25
  34. package/src/utils.ts +0 -8
  35. package/src/work.ts +0 -17
  36. package/src/ws.ts +0 -286
  37. package/test/post-script-console-log.spec.ts +0 -73
  38. package/test/post-script-executor.spec.ts +0 -685
  39. package/tsconfig.json +0 -9
package/src/mill-info.ts DELETED
@@ -1,81 +0,0 @@
1
- export interface MillInfo {
2
- /**
3
- * The mill socket IP address (or addresses in case IP is forwarded).
4
- */
5
- IPs: string[];
6
-
7
- /**
8
- * True if and only if this mill is a spy.
9
- */
10
- spy: boolean;
11
-
12
- /**
13
- * True if and only if this mill is a simulator.
14
- */
15
- sim: boolean;
16
-
17
- /**
18
- * True if and only if this mill restricted to using SSL.
19
- */
20
- onlySsl: boolean;
21
-
22
- /**
23
- * True if and only if this mill has cookie support.
24
- */
25
- cookieAble: boolean;
26
-
27
- /**
28
- * True if and only if this mill runs through a proxy.
29
- */
30
- proxyAble: boolean;
31
-
32
- /**
33
- * Number of loads capable of running (Angie)
34
- */
35
- loadsCapacity: number;
36
-
37
- /**
38
- * The location resolved from the first mill IP or an empty string.
39
- */
40
- location: string;
41
-
42
- /**
43
- * The country code provided by Cloudflare or empty string.
44
- */
45
- countryCode: string;
46
-
47
- /**
48
- * The mill user-agent string or an empty string.
49
- */
50
- userAgent: string;
51
-
52
- /**
53
- * The mill browser and version (parsed from user-agent string).
54
- */
55
- browserVersion: string;
56
-
57
- /**
58
- * The full affiliate id.
59
- */
60
- affiliateId: string;
61
-
62
- /**
63
- * The owner of the agent.
64
- */
65
- userId?: string;
66
-
67
- /**
68
- * The agent's owner's team.
69
- */
70
- teamId?: string;
71
-
72
- /**
73
- * Agent pool(if the user supplied)
74
- */
75
- pool?: string;
76
-
77
- /**
78
- * If the agent can't handle API tests
79
- */
80
- noApi: boolean;
81
- }
@@ -1,7 +0,0 @@
1
- export const millVersion = {
2
- major: 9,
3
- minor: 55,
4
- patch: 0,
5
- };
6
-
7
- export const millVersionString = `${millVersion.major}.${millVersion.minor}.${millVersion.patch}`;
@@ -1,160 +0,0 @@
1
- import {
2
- AssignmentExpression,
3
- AssignmentProperty,
4
- ExpressionStatement,
5
- Identifier,
6
- ObjectPattern,
7
- Pattern,
8
- RestElement,
9
- SequenceExpression,
10
- VariableDeclaration,
11
- } from 'estree';
12
- import { ESTree } from '../parser/js-parser';
13
- import { AcornJSParser } from '../parser/acorn-js-parser';
14
- import { ArrayPattern, FunctionDeclaration } from './types';
15
- import {
16
- isArray,
17
- isAssignmentExpression,
18
- isExpressionStatement,
19
- isFunctionDeclaration,
20
- isIdentifier,
21
- isObject,
22
- isRestElement,
23
- isSequenceExpression,
24
- isVariableDeclaration,
25
- } from './type-guard';
26
-
27
- export class ASTWalker {
28
- private ast: ESTree;
29
- private untouchables: string[];
30
- private detected: Set<string>;
31
-
32
- constructor(script: string) {
33
- this.ast = new AcornJSParser().parse(script);
34
- this.untouchables = [];
35
- this.detected = new Set();
36
- }
37
-
38
- public detectDeclarations = (untouchables: string[]): string[] => {
39
- this.untouchables = untouchables;
40
-
41
- for (const node of this.ast.body) {
42
- if (isFunctionDeclaration(node)) {
43
- this.addDeclaredFunction(node as FunctionDeclaration);
44
- }
45
- else if (isVariableDeclaration(node)) {
46
- this.addDeclaredVariables(node as VariableDeclaration);
47
- }
48
- else if (isExpressionStatement(node)) {
49
- this.addImplicitDeclarations(node as ExpressionStatement);
50
- }
51
- }
52
- return Array.from(this.detected);
53
- };
54
-
55
- private addDeclaredFunction = (node: FunctionDeclaration) => {
56
- this.addIdentifier(node.id);
57
- };
58
-
59
- private getIdentifierName = (id: Identifier) => id.name;
60
-
61
- private addNestedDeclaredProps = ({ properties }: ObjectPattern) => {
62
- for (const prop of properties) {
63
- if (isRestElement(prop)) {
64
- this.addRestElement(prop as RestElement);
65
- }
66
- else {
67
- this.addAssignmentProperty(prop as AssignmentProperty);
68
- }
69
- }
70
- };
71
-
72
- private addAssignmentProperty = ({ value }: AssignmentProperty) => {
73
- if (isIdentifier(value)) {
74
- this.addIdentifier(value as Identifier);
75
- }
76
- else if (isObject(value)) {
77
- this.addNestedDeclaredProps(value as ObjectPattern);
78
- }
79
- else if (isArray(value)) {
80
- this.addDestructuredArrayElements(value as ArrayPattern);
81
- }
82
- };
83
-
84
- private addRestElement = ({ argument }: RestElement) => {
85
- if (isIdentifier(argument)) {
86
- this.addIdentifier(argument as Identifier);
87
- }
88
- else if (isObject(argument)) {
89
- this.addNestedDeclaredProps(argument as ObjectPattern);
90
- }
91
- };
92
-
93
- private addDestructuredArrayElements = ({ elements }: ArrayPattern) => {
94
- for (const element of elements) {
95
- if (isIdentifier(element)) {
96
- this.addIdentifier(element as Identifier);
97
- }
98
- else if (isRestElement(element)) {
99
- this.addRestElement(element as RestElement);
100
- }
101
- else if (isObject(element)) {
102
- this.addNestedDeclaredProps(element as ObjectPattern);
103
- }
104
- else if (isArray(element)) {
105
- this.addDestructuredArrayElements(element as ArrayPattern);
106
- }
107
- }
108
- };
109
-
110
- private addDeclaredVariables = (node: VariableDeclaration) => {
111
- for (const declaration of node.declarations) {
112
- const pattern: Pattern = declaration.id;
113
- if (isIdentifier(pattern)) {
114
- this.addIdentifier(pattern as Identifier);
115
- }
116
- else if (isObject(pattern)) {
117
- this.addNestedDeclaredProps(pattern as ObjectPattern);
118
- }
119
- else if (isArray(pattern)) {
120
- this.addDestructuredArrayElements(pattern as ArrayPattern);
121
- }
122
- }
123
- };
124
-
125
- private addImplicitDeclarations = ({ expression }: ExpressionStatement) => {
126
- if (isAssignmentExpression(expression)) {
127
- this.addSingleImplicitVar(expression as AssignmentExpression);
128
- }
129
- else if (isSequenceExpression(expression)) {
130
- this.addMultipleImplicitVar(expression as SequenceExpression);
131
- }
132
- };
133
-
134
- private addSingleImplicitVar = (expression: AssignmentExpression) => {
135
- if (isIdentifier(expression.left)) {
136
- const assignedName = this.getIdentifierName(expression.left as Identifier);
137
- if (!this.untouchables.includes(assignedName)) {
138
- this.addIdentifier(expression.left as Identifier);
139
- }
140
- }
141
- else if (isObject(expression.left)) {
142
- this.addNestedDeclaredProps(expression.left as ObjectPattern);
143
- }
144
- else if (isArray(expression.left)) {
145
- this.addDestructuredArrayElements(expression.left as ArrayPattern);
146
- }
147
- };
148
-
149
- private addMultipleImplicitVar = ({ expressions }: SequenceExpression) => {
150
- for (const expression of expressions) {
151
- if (isAssignmentExpression(expression)) {
152
- this.addSingleImplicitVar(expression as AssignmentExpression);
153
- }
154
- }
155
- };
156
-
157
- private addIdentifier(id: Identifier) {
158
- this.detected.add(this.getIdentifierName(id));
159
- }
160
- }
@@ -1,73 +0,0 @@
1
- import {
2
- AssignmentExpression,
3
- ExpressionStatement,
4
- Identifier,
5
- Node,
6
- ObjectPattern,
7
- RestElement,
8
- SequenceExpression,
9
- VariableDeclaration,
10
- } from 'estree';
11
- import { isNonEmptyString } from '@loadmill/universal/dist/string-utils';
12
- import {
13
- ArrayPattern,
14
- Declarations,
15
- Expressions,
16
- FunctionDeclaration,
17
- Patterns,
18
- Statements,
19
- } from './types';
20
- import './types';
21
-
22
- export const isFunctionDeclaration = (node: Node) => {
23
- return isOfType(node, Declarations, Declarations.FunctionDeclaration) && hasId(node as FunctionDeclaration);
24
- };
25
- const hasId = (node: FunctionDeclaration) => !!node.id;
26
-
27
- export const isVariableDeclaration = (node: Node) => {
28
- return isOfType(node, Declarations, Declarations.VariableDeclaration) && hasDeclarations(node as VariableDeclaration);
29
- };
30
- const hasDeclarations = (node: VariableDeclaration) => Array.isArray(node.declarations);
31
-
32
- export const isExpressionStatement = (node: Node) => {
33
- return isOfType(node, Statements, Statements.ExpressionStatement) && hasExpression(node as ExpressionStatement);
34
- };
35
- const hasExpression = (node: ExpressionStatement) => !!node.expression;
36
-
37
- export const isAssignmentExpression = (node: Node) => {
38
- return isOfType(node, Expressions, Expressions.AssignmentExpression) && hasLeft(node as AssignmentExpression);
39
- };
40
- const hasLeft = (node: AssignmentExpression) => !!node.left;
41
-
42
- export const isSequenceExpression = (node: Node) => {
43
- return isOfType(node, Expressions, Expressions.SequenceExpression) && hasExpressions(node as SequenceExpression);
44
- };
45
- const hasExpressions = (node: SequenceExpression) => Array.isArray(node.expressions);
46
-
47
- export const isIdentifier = (node: Node) => {
48
- return isOfType(node, Patterns, Patterns.Identifier) && hasName(node as Identifier);
49
- };
50
- const hasName = (id: Identifier) => isNonEmptyString(id.name);
51
-
52
- export const isArray = (node: Node) => {
53
- return isOfType(node, Patterns, Patterns.ArrayPattern) && hasElements(node as ArrayPattern);
54
- };
55
- const hasElements = (node: ArrayPattern) => Array.isArray(node.elements);
56
-
57
- export const isObject = (node: Node) => {
58
- return isOfType(node, Patterns, Patterns.ObjectPattern) && hasProperties(node as ObjectPattern);
59
- };
60
- const hasProperties = (node: ObjectPattern) => Array.isArray(node.properties);
61
-
62
- export const isRestElement = (node: Node) => {
63
- return isOfType(node, Patterns, Patterns.RestElement) && hasArgument(node as RestElement);
64
- };
65
- const hasArgument = (rest: RestElement) => !!rest.argument;
66
-
67
- const isOfType = (
68
- node: Node,
69
- enumerator: any, // can't type an enum for some reason
70
- type: Expressions | Patterns | Statements | Declarations
71
- ) => {
72
- return node.type === enumerator[type];
73
- };
@@ -1,35 +0,0 @@
1
- import {
2
- ArrayPattern as ESTArrayPattern,
3
- FunctionDeclaration as ESTFunctionDeclaration,
4
- Identifier,
5
- Pattern,
6
- } from 'estree';
7
-
8
- export interface ArrayPattern extends ESTArrayPattern {
9
- elements: Array<Pattern>;
10
- }
11
-
12
- export interface FunctionDeclaration extends ESTFunctionDeclaration {
13
- id: Identifier;
14
- }
15
-
16
- export enum Declarations {
17
- FunctionDeclaration = 'FunctionDeclaration',
18
- VariableDeclaration = 'VariableDeclaration',
19
- }
20
-
21
- export enum Expressions {
22
- AssignmentExpression = 'AssignmentExpression',
23
- SequenceExpression = 'SequenceExpression',
24
- }
25
-
26
- export enum Patterns {
27
- ObjectPattern = 'ObjectPattern',
28
- ArrayPattern = 'ArrayPattern',
29
- RestElement = 'RestElement',
30
- Identifier = 'Identifier',
31
- }
32
-
33
- export enum Statements {
34
- ExpressionStatement = 'ExpressionStatement',
35
- }
@@ -1,24 +0,0 @@
1
- export const LINE_LIMIT = 1000;
2
- export const CONSOLE_LOG_LIMIT = 100;
3
-
4
- const isPassedTheLimit = (line) => line.length > LINE_LIMIT;
5
-
6
- export const myConsole = {
7
- stdout: [] as string[],
8
- log: (...args) => {
9
- if (myConsole.stdout.length >= CONSOLE_LOG_LIMIT) {
10
- return;
11
- }
12
- let line = '';
13
- for (const item of args) {
14
- line += typeof item === 'object' ? JSON.stringify(item, undefined, 2) : item;
15
- if (isPassedTheLimit(line)) {
16
- line = line.substring(0, LINE_LIMIT) + '\n...';
17
- break;
18
- }
19
- line += ' ';
20
- }
21
- !!line && myConsole.stdout.push(line);
22
- },
23
- setStdout: (newStdout) => myConsole.stdout = newStdout,
24
- };
@@ -1,8 +0,0 @@
1
- import { parse, Options } from 'acorn';
2
- import { ESTree, JSParser } from './js-parser';
3
-
4
- export class AcornJSParser implements JSParser {
5
- parse(script: string, options: Options = { ecmaVersion: 2020 }): ESTree {
6
- return parse(script, options) as ESTree;
7
- }
8
- }
@@ -1,22 +0,0 @@
1
- import { Node, Program } from 'estree';
2
- import { Parser } from './parser';
3
-
4
- interface JSParser extends Parser {
5
- parse(script: string, options?: JSParserOptions): ESTree;
6
- }
7
-
8
- type ExtendNode<T> = {
9
- [K in keyof T]: T[K] extends object ? ExtendNode<T[K]> : T[K];
10
- } & (T extends Node ? {
11
- start: number;
12
- end: number;
13
- } : {});
14
-
15
- type ESTree = ExtendNode<Program>;
16
- type JSParserOptions = { ecmaVersion: number | string }
17
-
18
- export {
19
- ESTree,
20
- JSParser,
21
- JSParserOptions,
22
- };
@@ -1,5 +0,0 @@
1
- export interface Parser {
2
- parse(script: string): AbstractSyntaxTree;
3
- }
4
-
5
- export type AbstractSyntaxTree = { [name: string]: any };
@@ -1,93 +0,0 @@
1
- import { strict as assert } from 'assert';
2
- import { SequenceExecutorParameters } from '@loadmill/core/dist/parameters';
3
- import { ParameterFunctionOperations } from '@loadmill/core/dist/parameters/parameter-functions/parameter-functions';
4
- import { ASTWalker } from './ast-walker';
5
- import { VM2VirtualMachine } from './virtual-machine/vm2-virtual-machine';
6
- import { myConsole } from './console-log';
7
-
8
- export class PostScriptRunner {
9
- public run = (
10
- staticContext: OuterStaticContext = { staticContext: { $: {}, __: {} } },
11
- dynamicContext: SequenceExecutorParameters = {},
12
- userCode: string = ''
13
- ): SequenceExecutorParameters => {
14
- const newVariables = new ASTWalker(userCode).detectDeclarations(Object.keys(staticContext));
15
- const wrappedUserCode = this.wrapUserCode(dynamicContext, userCode, newVariables);
16
- const stdout = [];
17
- myConsole.setStdout(stdout);
18
-
19
- const vm = new VM2VirtualMachine();
20
- vm.create({
21
- globalObject: { assert, ...dynamicContext, console: myConsole },
22
- staticObject: staticContext,
23
- });
24
-
25
- const modifiedDynamicContext = vm.run(wrappedUserCode);
26
- this.validateCircularDependency(modifiedDynamicContext);
27
- this.removeAssertModule(modifiedDynamicContext);
28
- return { result: modifiedDynamicContext, stdout: myConsole.stdout };
29
- };
30
-
31
- private wrapUserCode = (
32
- dynamicContext: SequenceExecutorParameters = {},
33
- userCode: string = '',
34
- newVariables: string[] = []
35
- ) => {
36
- const prefix =
37
- `
38
- Buffer = {};
39
- global = { assert: global.assert, console: global.console };
40
- const $ = staticContext.$;
41
- const __ = staticContext.__;
42
- `;
43
-
44
- const suffix =
45
- `
46
- exports = {
47
- ${[...Object.keys(dynamicContext), ...newVariables].join()}
48
- };
49
- `;
50
-
51
- return prefix + userCode + suffix;
52
- }
53
-
54
- validateCircularDependency = (obj: SequenceExecutorParameters) => {
55
- function circularError (propName: string) {
56
- return new TypeError(`Cyclic object value. Circular reference in property ${propName}`);
57
- }
58
-
59
- findCircular(obj);
60
-
61
- function findCircular(
62
- obj: SequenceExecutorParameters,
63
- _refs: WeakSet<SequenceExecutorParameters> = new WeakSet()
64
- ) {
65
- if (typeof obj === 'object' && obj !== null) {
66
- _refs.add(obj);
67
- for (const key in obj) {
68
- if (_refs.has(obj[key])) {
69
- throw circularError(key);
70
- }
71
- findCircular(obj[key], _refs);
72
- }
73
- _refs.delete(obj);
74
- }
75
- }
76
- };
77
-
78
- private removeAssertModule(context: SequenceExecutorParameters) {
79
- Object.keys(context).forEach(key => {
80
- if (context[key]?.assert?.name === 'strict') {
81
- context[key] = {};
82
- }
83
- });
84
- }
85
- }
86
- type OuterStaticContext = {
87
- staticContext: StaticContext;
88
- };
89
-
90
- type StaticContext = {
91
- $: SequenceExecutorParameters;
92
- __: ParameterFunctionOperations;
93
- };
@@ -1,15 +0,0 @@
1
- export interface VirtualMachine {
2
- engine: Engine;
3
- create(options: VirtualMachineOptions): Engine;
4
- run(code: string): object;
5
- }
6
-
7
- export interface VirtualMachineOptions {
8
- globalObject?: object;
9
- staticObject?: object;
10
- timeout?: number;
11
- memoryLimit?: number;
12
- async?: boolean;
13
- }
14
-
15
- export type Engine = any;
@@ -1,45 +0,0 @@
1
- import { VM } from 'vm2';
2
- import { SequenceExecutorParameters } from '../../../../core/dist/parameters';
3
-
4
- import { Engine, VirtualMachine, VirtualMachineOptions } from './virtual-machine';
5
-
6
- export class VM2VirtualMachine implements VirtualMachine {
7
- public engine: VM;
8
- private DEFAULT_TIMOUT_MS = Number(process.env.POSTSCRIPT_TIMEOUT_MS) || 1000;
9
-
10
- create(options: VirtualMachineOptions): Engine {
11
- const { timeout, globalObject, async, staticObject } = options;
12
- this.engine = new VM({
13
- timeout: timeout || this.DEFAULT_TIMOUT_MS,
14
- fixAsync: !async,
15
- eval: false,
16
- wasm: false,
17
- });
18
-
19
- this.makeStatic(staticObject);
20
-
21
- this.setGlobals(globalObject);
22
- }
23
-
24
- makeStatic(obj: object = {}) {
25
- this.deepFreeze(obj);
26
- }
27
-
28
- deepFreeze = (obj: object) => {
29
- for (const key of Object.keys(obj)) {
30
- if (typeof obj[key] === 'object' && obj[key] !== null) {
31
- this.engine.freeze(obj[key], key); // freeze me
32
- this.deepFreeze(obj[key]); // freeze my childrens
33
- }
34
- }
35
- return this.engine.freeze(obj); // freeze root
36
- };
37
-
38
- setGlobals = (globalObject: SequenceExecutorParameters = {}) => {
39
- this.engine.setGlobals(globalObject);
40
- }
41
-
42
- run(code: string): SequenceExecutorParameters {
43
- return this.engine.run(code);
44
- }
45
- }
@@ -1,127 +0,0 @@
1
- import { Failures } from './failures';
2
- import { MillInfo } from './mill-info';
3
- import { PerRequestResTime, PerRequestStats } from './request-stats';
4
-
5
- export type LoadResult = 'done' | 'aborted' | 'failed';
6
-
7
- /**
8
- * This report contains all the info that comes from Redis each time there is a status update.
9
- */
10
- export interface LoadStatusReport extends AggregatedStatsReport {
11
- endTime?: number;
12
- startTime?: number;
13
- result?: LoadResult;
14
- activeSessions?: number;
15
- }
16
-
17
- /**
18
- * This report contains all the aggregated stats computed from individual mill reports.
19
- */
20
- export interface AggregatedStatsReport extends BasicStatsReport {
21
- /**
22
- * The number of separate sessions / mills that sent at least one report.
23
- */
24
- reportedSessions?: number;
25
-
26
- append?: boolean;
27
- failures?: Failures;
28
- browserStatsMap?: StatsMap;
29
- locationStatsMap?: StatsMap;
30
- serverMetrics?: ServerMetrics;
31
- avgResTimeSequence?: SequenceObj;
32
- requestStats?: PerRequestResTime;
33
- failureReportsMap?: HashKeysToReportIds;
34
- }
35
-
36
- /**
37
- * A mapping that aggregates stats according to a certain feature, e.g. stats per browser version.
38
- */
39
- export interface StatsMap {
40
- [feature: string]: BasicStatsReport & {
41
- sessions: number;
42
- };
43
- }
44
-
45
- /**
46
- * A sequence of stats (currently only the average response time) reported within a certain
47
- * interval (between `firstTime` and `lastTime`).
48
- */
49
- export interface SequenceObj {
50
- append?: boolean;
51
- sequence: ClientMetrics;
52
- }
53
-
54
- export type ClientMetrics = ClientMetricsClump[];
55
-
56
- export type ClientMetricsClump = {
57
- s?: number;
58
- f?: number;
59
- avg: number;
60
- time: number;
61
- p50?: number;
62
- p95?: number;
63
- weight: number;
64
- concurrency: number;
65
- };
66
-
67
- export type ServerMetrics = ServerMetricsClump[];
68
-
69
- export type ServerMetricsClump = {
70
- _t: number;
71
-
72
- uc?: number;
73
- tc?: number;
74
-
75
- tm?: number;
76
- hm?: number;
77
- uhm?: number;
78
- };
79
-
80
- export type HashKeysToReportIds = { [hashKey: string]: string };
81
-
82
- /**
83
- * This is the report sent to Redis every time a mill report is received.
84
- */
85
- export type ToStoreStatsReport = StatsReportWithMillInfo & {
86
- timestamp: number;
87
- firstReport: boolean;
88
- };
89
-
90
- /**
91
- * This report includes a single mill stats report along with additional meta data.
92
- */
93
- export type StatsReportWithMillInfo = FromMillStatsReport &
94
- MillInfo & {
95
- lordId: string;
96
- };
97
-
98
- /**
99
- * The stats report sent by the mill.
100
- */
101
- export interface FromMillStatsReport extends BasicStatsReport {
102
- failures?: Failures;
103
- requestStats?: PerRequestStats;
104
- }
105
-
106
- /**
107
- * The basic stats we are usually interested in.
108
- */
109
- export interface BasicStatsReport {
110
- hits?: number;
111
- avgResTime?: number;
112
- failedIterations?: number;
113
- successfulIterations?: number;
114
- }
115
-
116
- export function isInformative({
117
- hits,
118
- avgResTime,
119
- failedIterations,
120
- successfulIterations,
121
- }: FromMillStatsReport) {
122
- return (
123
- (hits && hits > 0 && avgResTime != null && avgResTime >= 0) ||
124
- (failedIterations && failedIterations > 0) ||
125
- (successfulIterations && successfulIterations > 0)
126
- );
127
- }