Skip to content

Commit 6ded7b3

Browse files
authored
Add performance markers to Kevin overlay + configurable prefix string for perf marker names (#28)
* Add performance markers * Introduce perfMarkerPrefix as an option * Add tests and README * Add link to perf info * Bump minor version
1 parent c52eb43 commit 6ded7b3

File tree

5 files changed

+89
-6
lines changed

5 files changed

+89
-6
lines changed

README.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,19 @@ claim to serve it.
142142

143143
This is a string that's inserted into the overlay, in order to provide users with additional information. It's useful if you'd like to provide feedback to users of your server, like "If you run into issues, try running restart_server_please.sh". This string may contain valid HTML.
144144

145+
#### `perfMarkerPrefix`
146+
147+
- Type: `String`
148+
- Default: `""`
149+
150+
The overlay will fire 3 performance markers:
151+
152+
- performance.mark("kevin-overlay-start") - when the overlay first renders
153+
- performance.mark("kevin-overlay-end") - assets are finished building, and right before the page refreshes
154+
- performance.measure("kevin-overlay") - right after the above, indicating total time overlay was visible to user.
155+
156+
If you would like to add a prefix to these marker names, you may pass it in as an option, otherwise the marker names will be as below. Please see documentation on performance markers here: https://developer.mozilla.org/en-US/docs/Web/API/Performance.
157+
145158
## Hooks
146159

147160
To further extend Kevin's capabilities, we used Webpack's [Tapable][tapable] framework to provide access to some of Kevin's core functionality. You can use a hook much like you would with Webpack:

lib/buildingTemplate.js

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,13 @@
44
* initial loading time. Note that it re-renders the page each time it's called with the
55
* most up-to-date list of currently-being-built assets.
66
*/
7-
module.exports = (assetName, configName, kevinStatusUrl, additionalInfo) => {
7+
module.exports = (
8+
assetName,
9+
configName,
10+
kevinStatusUrl,
11+
additionalInfo,
12+
perfMarkerPrefix = ""
13+
) => {
814
return `
915
/**
1016
* Hi! If you're seeing this, it means Kevin just started a compiler to build this
@@ -108,9 +114,16 @@ if (!isIframe() && !window.__KEVIN_CHECKS_ON_BUILDS) {
108114
.every(function(config) {
109115
return data[config] !== "first-build";
110116
});
117+
111118
if (doneBuilding) {
112119
clearInterval(window.__KEVIN_CHECKS_ON_BUILDS);
113-
window.location.reload(true);
120+
performance.mark("${perfMarkerPrefix}kevin-overlay-end");
121+
performance.measure("${perfMarkerPrefix}kevin-overlay", "${perfMarkerPrefix}kevin-overlay-start", "${perfMarkerPrefix}kevin-overlay-end");
122+
//Ensure that current event loop completes before reloading page
123+
//This will ensure that perf markers are registered.
124+
setTimeout(() => {
125+
window.location.reload(true);
126+
}, 0);
114127
}
115128
116129
}
@@ -178,6 +191,7 @@ ready(function() {
178191
"</div>"
179192
"<br/>" +
180193
"</div>";
194+
performance.mark("${perfMarkerPrefix}kevin-overlay-start");
181195
});
182196
183197
})();

lib/middleware.js

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,10 @@ class Kevin {
8080
// to users of your server, like "If you run into issues, try running restart_server_please.sh"
8181
// This string may contain valid HTML.
8282
additionalOverlayInfo = "",
83+
84+
// This string will be used to prefix any performance markers fired from the kevin overlay script
85+
// in buildingTemplate.js
86+
perfMarkerPrefix = "",
8387
} = {}
8488
) {
8589
this.hooks = {
@@ -98,6 +102,7 @@ class Kevin {
98102
this.kevinPublicPath = kevinPublicPath;
99103
this.kevinApiPrefix = kevinApiPrefix;
100104
this.additionalOverlayInfo = additionalOverlayInfo;
105+
this.perfMarkerPrefix = perfMarkerPrefix;
101106

102107
this.entryMap = initializeEntryMap(this.configs);
103108
}
@@ -267,8 +272,17 @@ class Kevin {
267272
* @param {bool} $0.buildOnly - true if we shouldn't worry about serving the file
268273
* @param {string} $0.configName - the name of the config responsible for this request
269274
* if kevinApiPrefix is provided.
275+
* @param {string} $0.perfMarkerPrefix - string to prefix any perf markers sent by kevin
270276
*/
271-
serveAsset({ req, res, next, isNewCompiler, assetName, configName } = {}) {
277+
serveAsset({
278+
req,
279+
res,
280+
next,
281+
isNewCompiler,
282+
assetName,
283+
configName,
284+
perfMarkerPrefix,
285+
} = {}) {
272286
// If the compiler is going through its first build, serve an overlay until it's
273287
// finished (the first build takes more time because the cache is cold).
274288
if (isNewCompiler) {
@@ -282,7 +296,8 @@ class Kevin {
282296
assetName,
283297
configName,
284298
kevinBuildStatusUrl,
285-
this.additionalOverlayInfo
299+
this.additionalOverlayInfo,
300+
perfMarkerPrefix
286301
);
287302
logInfo(`Serving temporary asset for ${assetName}...`);
288303
res.setHeader("Content-Length", content.length);
@@ -367,7 +382,8 @@ class Kevin {
367382
compilers[name] = { status: NOT_BUILT };
368383
});
369384

370-
const hasMaxActiveCompilersBeenReached = this.hasMaxActiveCompilersBeenReached();
385+
const hasMaxActiveCompilersBeenReached =
386+
this.hasMaxActiveCompilersBeenReached();
371387

372388
res.json({
373389
compilers,
@@ -536,6 +552,8 @@ class Kevin {
536552
return next();
537553
}
538554
const configName = config.name;
555+
const perfMarkerPrefix = this.perfMarkerPrefix;
556+
539557
logInfo(`Using config "${configName}" to build ${assetName}`);
540558
this.hooks.handleRequest.call(req, assetName, configName);
541559

@@ -551,6 +569,7 @@ class Kevin {
551569
isNewCompiler,
552570
assetName,
553571
configName,
572+
perfMarkerPrefix,
554573
});
555574
})
556575
.catch((err) => {

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "kevin-middleware",
3-
"version": "1.6.1",
3+
"version": "1.7.1",
44
"description": "This is an Express middleware that makes developing javascript in a monorepo easier.",
55
"main": "index.js",
66
"directories": {

test/lib/buildingTemplate.test.js

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
const buildingTemplate = require("../../lib/buildingTemplate");
2+
3+
describe("buildingTemplate", () => {
4+
describe("perfMarkerPrefix argument", () => {
5+
const assetName = "fish.js";
6+
const configName = "aquatic";
7+
const kevinStatusUrl = "http://gonefishingtonight.com";
8+
const additionalInfo = "blub blub";
9+
it("uses empty string when not passed in", () => {
10+
const result = buildingTemplate(
11+
assetName,
12+
configName,
13+
kevinStatusUrl,
14+
additionalInfo
15+
);
16+
expect(result).toContain(`performance.mark("kevin-overlay-start")`);
17+
expect(result).toContain(`performance.mark("kevin-overlay-end")`);
18+
expect(result).toContain(
19+
`performance.measure("kevin-overlay", "kevin-overlay-start", "kevin-overlay-end")`
20+
);
21+
});
22+
it("uses provided prefix string", () => {
23+
const result = buildingTemplate(
24+
assetName,
25+
configName,
26+
kevinStatusUrl,
27+
additionalInfo,
28+
"ocean_"
29+
);
30+
expect(result).toContain(`performance.mark("ocean_kevin-overlay-start")`);
31+
expect(result).toContain(`performance.mark("ocean_kevin-overlay-end")`);
32+
expect(result).toContain(
33+
`performance.measure("ocean_kevin-overlay", "ocean_kevin-overlay-start", "ocean_kevin-overlay-end")`
34+
);
35+
});
36+
});
37+
});

0 commit comments

Comments
 (0)