@parcel/profiler 2.12.1-dev.3185 → 2.12.1-dev.3188
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/lib/Tracer.d.ts +3 -3
- package/lib/Tracer.js +29 -65
- package/package.json +5 -5
- package/src/Tracer.js +38 -78
- package/test/Tracer.test.js +55 -104
package/lib/Tracer.d.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import type { TraceEvent, IDisposable,
|
|
1
|
+
import type { TraceEvent, IDisposable, PluginTracer as IPluginTracer } from "@parcel/types";
|
|
2
2
|
import type { TraceMeasurement as ITraceMeasurement } from "./types";
|
|
3
3
|
export default class Tracer {
|
|
4
4
|
|
|
5
5
|
onTrace(cb: (event: TraceEvent) => unknown): IDisposable;
|
|
6
|
-
|
|
6
|
+
wrap(name: string, fn: () => unknown): Promise<void>;
|
|
7
|
+
createMeasurement(name: string, category?: string, argumentName?: string, otherArgs?: Record<string, unknown>): ITraceMeasurement | null;
|
|
7
8
|
get enabled(): boolean;
|
|
8
9
|
enable(): void;
|
|
9
10
|
disable(): void;
|
|
@@ -23,6 +24,5 @@ export declare class PluginTracer implements IPluginTracer {
|
|
|
23
24
|
constructor(opts: TracerOpts);
|
|
24
25
|
get enabled(): boolean;
|
|
25
26
|
createMeasurement(name: string, category?: string, argumentName?: string, otherArgs?: Record<string, unknown>): ITraceMeasurement | null;
|
|
26
|
-
measure<T>(options: MeasurementOptions, fn: () => T): T;
|
|
27
27
|
}
|
|
28
28
|
export {};
|
package/lib/Tracer.js
CHANGED
|
@@ -62,37 +62,38 @@ class Tracer {
|
|
|
62
62
|
onTrace(cb) {
|
|
63
63
|
return this.#traceEmitter.addListener(cb);
|
|
64
64
|
}
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
categories,
|
|
68
|
-
name
|
|
69
|
-
}, fn) {
|
|
70
|
-
if (!this.enabled) {
|
|
71
|
-
return fn();
|
|
72
|
-
}
|
|
73
|
-
let measurement = new TraceMeasurement(this, name, pid, tid, {
|
|
74
|
-
categories,
|
|
75
|
-
args
|
|
76
|
-
});
|
|
77
|
-
let result;
|
|
78
|
-
let hasFinally = false;
|
|
65
|
+
async wrap(name, fn) {
|
|
66
|
+
let measurement = this.createMeasurement(name);
|
|
79
67
|
try {
|
|
80
|
-
|
|
81
|
-
// @ts-expect-error TypeScript types cannot infer that finally can exist
|
|
82
|
-
if (result != null && typeof result === 'object' && typeof result.finally === 'function') {
|
|
83
|
-
hasFinally = true;
|
|
84
|
-
// @ts-expect-error
|
|
85
|
-
// $FlowFixMe[incompatible-use] This will run for a promise type, but it cannot be easily typed in Flow
|
|
86
|
-
result = result.finally(() => {
|
|
87
|
-
measurement === null || measurement === void 0 || measurement.end();
|
|
88
|
-
});
|
|
89
|
-
}
|
|
68
|
+
await fn();
|
|
90
69
|
} finally {
|
|
91
|
-
|
|
92
|
-
|
|
70
|
+
measurement && measurement.end();
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
createMeasurement(name, category = 'Core', argumentName, otherArgs) {
|
|
74
|
+
if (!this.enabled) return null;
|
|
75
|
+
|
|
76
|
+
// We create `args` in a fairly verbose way to avoid object
|
|
77
|
+
// allocation where not required.
|
|
78
|
+
let args;
|
|
79
|
+
if (typeof argumentName === 'string') {
|
|
80
|
+
args = {
|
|
81
|
+
name: argumentName
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
if (typeof otherArgs === 'object') {
|
|
85
|
+
if (typeof args == 'undefined') {
|
|
86
|
+
args = {};
|
|
87
|
+
}
|
|
88
|
+
for (const [k, v] of Object.entries(otherArgs)) {
|
|
89
|
+
args[k] = v;
|
|
93
90
|
}
|
|
94
91
|
}
|
|
95
|
-
|
|
92
|
+
const data = {
|
|
93
|
+
categories: [category],
|
|
94
|
+
args
|
|
95
|
+
};
|
|
96
|
+
return new TraceMeasurement(this, name, pid, tid, data);
|
|
96
97
|
}
|
|
97
98
|
get enabled() {
|
|
98
99
|
return this.#enabled;
|
|
@@ -124,44 +125,7 @@ class PluginTracer {
|
|
|
124
125
|
return tracer.enabled;
|
|
125
126
|
}
|
|
126
127
|
createMeasurement(name, category, argumentName, otherArgs) {
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
// We create `args` in a fairly verbose way to avoid object
|
|
130
|
-
// allocation where not required.
|
|
131
|
-
let args;
|
|
132
|
-
if (typeof argumentName === 'string') {
|
|
133
|
-
args = {
|
|
134
|
-
name: argumentName
|
|
135
|
-
};
|
|
136
|
-
}
|
|
137
|
-
if (typeof otherArgs === 'object') {
|
|
138
|
-
if (typeof args == 'undefined') {
|
|
139
|
-
args = {};
|
|
140
|
-
}
|
|
141
|
-
for (const [k, v] of Object.entries(otherArgs)) {
|
|
142
|
-
args[k] = v;
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
const data = {
|
|
146
|
-
categories: [`${this.category}:${this.origin}${typeof category === 'string' ? `:${category}` : ''}`],
|
|
147
|
-
args
|
|
148
|
-
};
|
|
149
|
-
return new TraceMeasurement(tracer, name, pid, tid, data);
|
|
150
|
-
}
|
|
151
|
-
measure(options, fn) {
|
|
152
|
-
var _options$args;
|
|
153
|
-
if (!this.enabled) {
|
|
154
|
-
return fn();
|
|
155
|
-
}
|
|
156
|
-
return tracer.measure({
|
|
157
|
-
...options,
|
|
158
|
-
// $FlowFixMe[cannot-spread-inexact]
|
|
159
|
-
args: {
|
|
160
|
-
origin: this.origin,
|
|
161
|
-
...((_options$args = options.args) !== null && _options$args !== void 0 ? _options$args : {})
|
|
162
|
-
},
|
|
163
|
-
categories: [this.category, ...options.categories]
|
|
164
|
-
}, fn);
|
|
128
|
+
return tracer.createMeasurement(name, `${this.category}:${this.origin}${typeof category === 'string' ? `:${category}` : ''}`, argumentName, otherArgs);
|
|
165
129
|
}
|
|
166
130
|
}
|
|
167
131
|
exports.PluginTracer = PluginTracer;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@parcel/profiler",
|
|
3
|
-
"version": "2.12.1-dev.
|
|
3
|
+
"version": "2.12.1-dev.3188+c422b7ff3",
|
|
4
4
|
"description": "Blazing fast, zero configuration web application bundler",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"publishConfig": {
|
|
@@ -24,10 +24,10 @@
|
|
|
24
24
|
"check-ts": "tsc --noEmit lib/index.d.ts"
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"@parcel/diagnostic": "2.0.0-dev.
|
|
28
|
-
"@parcel/events": "2.0.0-dev.
|
|
29
|
-
"@parcel/types-internal": "2.12.1-dev.
|
|
27
|
+
"@parcel/diagnostic": "2.0.0-dev.1565+c422b7ff3",
|
|
28
|
+
"@parcel/events": "2.0.0-dev.1565+c422b7ff3",
|
|
29
|
+
"@parcel/types-internal": "2.12.1-dev.3188+c422b7ff3",
|
|
30
30
|
"chrome-trace-event": "^1.0.2"
|
|
31
31
|
},
|
|
32
|
-
"gitHead": "
|
|
32
|
+
"gitHead": "c422b7ff3c383779781ea5169d86191508b01e5b"
|
|
33
33
|
}
|
package/src/Tracer.js
CHANGED
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
import type {
|
|
4
4
|
TraceEvent,
|
|
5
5
|
IDisposable,
|
|
6
|
-
MeasurementOptions,
|
|
7
6
|
PluginTracer as IPluginTracer,
|
|
8
7
|
} from '@parcel/types';
|
|
9
8
|
import type {
|
|
@@ -65,44 +64,44 @@ export default class Tracer {
|
|
|
65
64
|
return this.#traceEmitter.addListener(cb);
|
|
66
65
|
}
|
|
67
66
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
67
|
+
async wrap(name: string, fn: () => mixed): Promise<void> {
|
|
68
|
+
let measurement = this.createMeasurement(name);
|
|
69
|
+
try {
|
|
70
|
+
await fn();
|
|
71
|
+
} finally {
|
|
72
|
+
measurement && measurement.end();
|
|
74
73
|
}
|
|
74
|
+
}
|
|
75
75
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
76
|
+
createMeasurement(
|
|
77
|
+
name: string,
|
|
78
|
+
category: string = 'Core',
|
|
79
|
+
argumentName?: string,
|
|
80
|
+
otherArgs?: {[key: string]: mixed},
|
|
81
|
+
): ITraceMeasurement | null {
|
|
82
|
+
if (!this.enabled) return null;
|
|
83
83
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
) {
|
|
92
|
-
|
|
93
|
-
// @ts-expect-error
|
|
94
|
-
// $FlowFixMe[incompatible-use] This will run for a promise type, but it cannot be easily typed in Flow
|
|
95
|
-
result = result.finally(() => {
|
|
96
|
-
measurement?.end();
|
|
97
|
-
});
|
|
84
|
+
// We create `args` in a fairly verbose way to avoid object
|
|
85
|
+
// allocation where not required.
|
|
86
|
+
let args: {[key: string]: mixed};
|
|
87
|
+
if (typeof argumentName === 'string') {
|
|
88
|
+
args = {name: argumentName};
|
|
89
|
+
}
|
|
90
|
+
if (typeof otherArgs === 'object') {
|
|
91
|
+
if (typeof args == 'undefined') {
|
|
92
|
+
args = {};
|
|
98
93
|
}
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
measurement?.end();
|
|
94
|
+
for (const [k, v] of Object.entries(otherArgs)) {
|
|
95
|
+
args[k] = v;
|
|
102
96
|
}
|
|
103
97
|
}
|
|
104
98
|
|
|
105
|
-
|
|
99
|
+
const data: TraceMeasurementData = {
|
|
100
|
+
categories: [category],
|
|
101
|
+
args,
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
return new TraceMeasurement(this, name, pid, tid, data);
|
|
106
105
|
}
|
|
107
106
|
|
|
108
107
|
get enabled(): boolean {
|
|
@@ -129,7 +128,6 @@ type TracerOpts = {|
|
|
|
129
128
|
origin: string,
|
|
130
129
|
category: string,
|
|
131
130
|
|};
|
|
132
|
-
|
|
133
131
|
export class PluginTracer implements IPluginTracer {
|
|
134
132
|
/** @private */
|
|
135
133
|
origin: string;
|
|
@@ -153,51 +151,13 @@ export class PluginTracer implements IPluginTracer {
|
|
|
153
151
|
argumentName?: string,
|
|
154
152
|
otherArgs?: {[key: string]: mixed},
|
|
155
153
|
): ITraceMeasurement | null {
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
}
|
|
164
|
-
if (typeof otherArgs === 'object') {
|
|
165
|
-
if (typeof args == 'undefined') {
|
|
166
|
-
args = {};
|
|
167
|
-
}
|
|
168
|
-
for (const [k, v] of Object.entries(otherArgs)) {
|
|
169
|
-
args[k] = v;
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
const data: TraceMeasurementData = {
|
|
174
|
-
categories: [
|
|
175
|
-
`${this.category}:${this.origin}${
|
|
176
|
-
typeof category === 'string' ? `:${category}` : ''
|
|
177
|
-
}`,
|
|
178
|
-
],
|
|
179
|
-
args,
|
|
180
|
-
};
|
|
181
|
-
|
|
182
|
-
return new TraceMeasurement(tracer, name, pid, tid, data);
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
measure<T>(options: MeasurementOptions, fn: () => T): T {
|
|
186
|
-
if (!this.enabled) {
|
|
187
|
-
return fn();
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
return tracer.measure(
|
|
191
|
-
{
|
|
192
|
-
...options,
|
|
193
|
-
// $FlowFixMe[cannot-spread-inexact]
|
|
194
|
-
args: {
|
|
195
|
-
origin: this.origin,
|
|
196
|
-
...(options.args ?? {}),
|
|
197
|
-
},
|
|
198
|
-
categories: [this.category, ...options.categories],
|
|
199
|
-
},
|
|
200
|
-
fn,
|
|
154
|
+
return tracer.createMeasurement(
|
|
155
|
+
name,
|
|
156
|
+
`${this.category}:${this.origin}${
|
|
157
|
+
typeof category === 'string' ? `:${category}` : ''
|
|
158
|
+
}`,
|
|
159
|
+
argumentName,
|
|
160
|
+
otherArgs,
|
|
201
161
|
);
|
|
202
162
|
}
|
|
203
163
|
}
|
package/test/Tracer.test.js
CHANGED
|
@@ -5,123 +5,74 @@ import assert from 'assert';
|
|
|
5
5
|
describe('Tracer', () => {
|
|
6
6
|
let onTrace;
|
|
7
7
|
let traceDisposable;
|
|
8
|
-
let opts = {name: 'test', categories: ['tracer']};
|
|
9
|
-
|
|
10
8
|
beforeEach(() => {
|
|
11
9
|
onTrace = sinon.spy();
|
|
12
10
|
traceDisposable = tracer.onTrace(onTrace);
|
|
13
11
|
tracer.enable();
|
|
14
12
|
});
|
|
15
|
-
|
|
16
13
|
afterEach(() => {
|
|
17
14
|
traceDisposable.dispose();
|
|
18
15
|
});
|
|
19
16
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
for (let [type, createFn] of cases) {
|
|
27
|
-
describe(`given a ${type} function`, () => {
|
|
28
|
-
it('does not trace when disabled', async () => {
|
|
29
|
-
tracer.disable();
|
|
30
|
-
|
|
31
|
-
let result = tracer.measure(opts, sinon.spy());
|
|
32
|
-
if (type === 'asynchronous') {
|
|
33
|
-
sinon.assert.notCalled(onTrace);
|
|
34
|
-
await result;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
assert(onTrace.notCalled);
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
it('emits a basic trace event', async () => {
|
|
41
|
-
let result = tracer.measure(opts, createFn());
|
|
42
|
-
if (type === 'asynchronous') {
|
|
43
|
-
sinon.assert.notCalled(onTrace);
|
|
44
|
-
await result;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
sinon.assert.calledOnce(onTrace);
|
|
48
|
-
sinon.assert.calledWith(
|
|
49
|
-
onTrace,
|
|
50
|
-
sinon.match({
|
|
51
|
-
type: 'trace',
|
|
52
|
-
name: 'test',
|
|
53
|
-
args: {},
|
|
54
|
-
categories: ['tracer'],
|
|
55
|
-
duration: sinon.match.number,
|
|
56
|
-
}),
|
|
57
|
-
);
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
it('emits a complex trace event', async () => {
|
|
61
|
-
let result = tracer.measure(
|
|
62
|
-
{...opts, args: {hello: 'world'}},
|
|
63
|
-
createFn(),
|
|
64
|
-
);
|
|
65
|
-
if (type === 'asynchronous') {
|
|
66
|
-
sinon.assert.notCalled(onTrace);
|
|
67
|
-
await result;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
sinon.assert.calledOnce(onTrace);
|
|
71
|
-
sinon.assert.calledWith(
|
|
72
|
-
onTrace,
|
|
73
|
-
sinon.match({
|
|
74
|
-
type: 'trace',
|
|
75
|
-
name: 'test',
|
|
76
|
-
args: {hello: 'world'},
|
|
77
|
-
categories: ['tracer'],
|
|
78
|
-
duration: sinon.match.number,
|
|
79
|
-
}),
|
|
80
|
-
);
|
|
81
|
-
});
|
|
82
|
-
});
|
|
83
|
-
}
|
|
17
|
+
it('returns no measurement when disabled', () => {
|
|
18
|
+
tracer.disable();
|
|
19
|
+
const measurement = tracer.createMeasurement('test');
|
|
20
|
+
assert(measurement == null);
|
|
21
|
+
assert(onTrace.notCalled);
|
|
84
22
|
});
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
name: 'test',
|
|
102
|
-
args: {origin: 'origin'},
|
|
103
|
-
categories: ['cat', 'tracer'],
|
|
104
|
-
duration: sinon.match.number,
|
|
105
|
-
}),
|
|
106
|
-
);
|
|
107
|
-
});
|
|
23
|
+
it('emits a basic trace event', () => {
|
|
24
|
+
const measurement = tracer.createMeasurement('test');
|
|
25
|
+
measurement.end();
|
|
26
|
+
sinon.assert.calledWith(
|
|
27
|
+
onTrace,
|
|
28
|
+
sinon.match({
|
|
29
|
+
type: 'trace',
|
|
30
|
+
name: 'test',
|
|
31
|
+
args: undefined,
|
|
32
|
+
duration: sinon.match.number,
|
|
33
|
+
}),
|
|
34
|
+
);
|
|
35
|
+
});
|
|
36
|
+
it('emits a complex trace event', () => {
|
|
37
|
+
const measurement = tracer.createMeasurement('test', 'myPlugin', 'aaargh', {
|
|
38
|
+
extra: 'data',
|
|
108
39
|
});
|
|
40
|
+
measurement.end();
|
|
41
|
+
sinon.assert.calledWith(
|
|
42
|
+
onTrace,
|
|
43
|
+
sinon.match({
|
|
44
|
+
type: 'trace',
|
|
45
|
+
name: 'test',
|
|
46
|
+
categories: ['myPlugin'],
|
|
47
|
+
args: {extra: 'data', name: 'aaargh'},
|
|
48
|
+
duration: sinon.match.number,
|
|
49
|
+
}),
|
|
50
|
+
);
|
|
51
|
+
});
|
|
52
|
+
it('calling end twice on measurment should be a no-op', () => {
|
|
53
|
+
const measurement = tracer.createMeasurement('test');
|
|
54
|
+
measurement.end();
|
|
55
|
+
measurement.end();
|
|
56
|
+
sinon.assert.calledOnce(onTrace);
|
|
57
|
+
});
|
|
109
58
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
sinon.assert.calledWith(
|
|
116
|
-
onTrace,
|
|
117
|
-
sinon.match({
|
|
118
|
-
type: 'trace',
|
|
119
|
-
name: 'test',
|
|
120
|
-
categories: ['cat:origin:customCat'],
|
|
121
|
-
duration: sinon.match.number,
|
|
122
|
-
}),
|
|
123
|
-
);
|
|
59
|
+
describe('PluginTracer', () => {
|
|
60
|
+
it('emits events with proper origin/category', () => {
|
|
61
|
+
const pluginTracer = new PluginTracer({
|
|
62
|
+
origin: 'origin',
|
|
63
|
+
category: 'cat',
|
|
124
64
|
});
|
|
65
|
+
const measurement = pluginTracer.createMeasurement('test', 'customCat');
|
|
66
|
+
measurement.end();
|
|
67
|
+
sinon.assert.calledWith(
|
|
68
|
+
onTrace,
|
|
69
|
+
sinon.match({
|
|
70
|
+
type: 'trace',
|
|
71
|
+
name: 'test',
|
|
72
|
+
categories: ['cat:origin:customCat'],
|
|
73
|
+
duration: sinon.match.number,
|
|
74
|
+
}),
|
|
75
|
+
);
|
|
125
76
|
});
|
|
126
77
|
});
|
|
127
78
|
});
|