Skip to content

Commit c152521

Browse files
committed
Sandbox metrics collection
1 parent e112aa7 commit c152521

File tree

3 files changed

+82
-7
lines changed

3 files changed

+82
-7
lines changed

packages/app/src/sandbox/compile.ts

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import handleExternalResources from './external-resources';
2727
import { loadDependencies, NPMDependencies } from './npm';
2828
import { resetScreen } from './status-screen';
2929
import { showRunOnClick } from './status-screen/run-on-click';
30+
import * as metrics from './utils/metrics';
3031

3132
let initializedResizeListener = false;
3233
let manager: Manager | null = null;
@@ -78,6 +79,7 @@ let lastHeadHTML = null;
7879
let lastBodyHTML = null;
7980
let lastHeight = 0;
8081
let changedModuleCount = 0;
82+
let usedCache = false;
8183

8284
const DEPENDENCY_ALIASES = {
8385
'@vue/cli-plugin-babel': '@vue/babel-preset-app',
@@ -419,6 +421,7 @@ async function compile({
419421
dispatch({
420422
type: 'start',
421423
});
424+
metrics.measure('compilation');
422425

423426
const startTime = Date.now();
424427
try {
@@ -513,10 +516,10 @@ async function compile({
513516
manager.setManifest(manifest);
514517
// We save the state of transpiled modules, and load it here again. Gives
515518
// faster initial loads.
516-
await consumeCache(manager);
519+
usedCache = await consumeCache(manager);
517520
}
518521

519-
const t = Date.now();
522+
metrics.measure('transpilation');
520523

521524
const updatedModules = (await updateManager(modules, configurations)) || [];
522525

@@ -541,7 +544,7 @@ async function compile({
541544
await manager.verifyTreeTranspiled();
542545
await manager.transpileModules(managerModuleToTranspile);
543546

544-
debug(`Transpilation time ${Date.now() - t}ms`);
547+
metrics.endMeasure('transpilation', 'Transpilation');
545548

546549
dispatch({ type: 'status', status: 'evaluating' });
547550
manager.setStage('evaluation');
@@ -604,16 +607,17 @@ async function compile({
604607
lastHeadHTML = head;
605608
}
606609

607-
const extDate = Date.now();
610+
metrics.measure('external-resources');
608611
await handleExternalResources(externalResources);
609-
debug('Loaded external resources in ' + (Date.now() - extDate) + 'ms');
612+
metrics.endMeasure('external-resources', 'External Resources');
610613

611-
const tt = Date.now();
612614
const oldHTML = document.body.innerHTML;
615+
metrics.measure('evaluation');
613616
const evalled = manager.evaluateModule(managerModuleToTranspile, {
614617
force: isModuleView,
615618
});
616-
debug(`Evaluation time: ${Date.now() - tt}ms`);
619+
metrics.endMeasure('evaluation', 'Evaluation');
620+
617621
const domChanged =
618622
!manager.preset.htmlDisabled && oldHTML !== document.body.innerHTML;
619623

@@ -662,6 +666,8 @@ async function compile({
662666

663667
debug(`Total time: ${Date.now() - startTime}ms`);
664668

669+
metrics.endMeasure('compilation', 'Compilation');
670+
metrics.endMeasure('total', 'Total', { lastTime: 0 });
665671
dispatch({
666672
type: 'success',
667673
});
@@ -731,6 +737,14 @@ async function compile({
731737
state: managerState,
732738
});
733739
}
740+
741+
if (firstLoad) {
742+
metrics.persistMeasurements({
743+
sandboxId,
744+
usedCache,
745+
browser: navigator.userAgent,
746+
});
747+
}
734748
}
735749
firstLoad = false;
736750

packages/app/src/sandbox/index.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import {
1717
import { show404 } from 'sandbox-hooks/not-found-screen';
1818

1919
import compile, { getCurrentManager } from './compile';
20+
import { endMeasure } from './utils/metrics';
2021

2122
// Call this before importing React (or any other packages that might import React).
2223
initialize(window);
@@ -29,6 +30,8 @@ export const SCRIPT_VERSION =
2930

3031
debug('Booting sandbox v2');
3132

33+
endMeasure('boot', 'Boot', { lastTime: 0 });
34+
3235
requirePolyfills().then(() => {
3336
registerServiceWorker('/sandbox-service-worker.js', {});
3437

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import _debug from '@codesandbox/common/lib/utils/debug';
2+
3+
const debug = _debug('cs:compiler:measurements');
4+
5+
type MeasurementKey = string;
6+
7+
const runningMeasurements = new Map<string, number>();
8+
const measurements: { [meaurement: string]: number } = {};
9+
10+
export function measure(key: MeasurementKey) {
11+
runningMeasurements.set(key, performance.now());
12+
}
13+
14+
export function endMeasure(
15+
key: MeasurementKey,
16+
name?: string,
17+
options: {
18+
lastTime?: number;
19+
} = {}
20+
) {
21+
const lastMeasurement =
22+
typeof options.lastTime === 'undefined'
23+
? runningMeasurements.get(key)
24+
: options.lastTime;
25+
if (typeof lastMeasurement === 'undefined') {
26+
console.warn(
27+
`Measurement for '${key}' was requested, but never was started`
28+
);
29+
return;
30+
}
31+
32+
measurements[key] = performance.now() - lastMeasurement;
33+
debug(`${name || key} Time: ${measurements[key].toFixed(2)}ms`);
34+
runningMeasurements.delete(key);
35+
}
36+
37+
const MEASUREMENT_API = `https://mij9yockq9.execute-api.us-east-1.amazonaws.com/prod/metrics`;
38+
39+
export function persistMeasurements(data: {
40+
sandboxId: string;
41+
usedCache: boolean;
42+
browser: string;
43+
}) {
44+
// if (process.env.NODE_ENV === 'development') {
45+
// return Promise.resolve();
46+
// }
47+
48+
const finalData = { ...data, ...measurements };
49+
50+
return fetch(MEASUREMENT_API, {
51+
method: 'POST',
52+
body: JSON.stringify(finalData),
53+
headers: {
54+
Accept: 'application/json',
55+
'Content-Type': 'application/json',
56+
},
57+
});
58+
}

0 commit comments

Comments
 (0)