Skip to content

Commit e3dd09d

Browse files
committed
Client: Implement performance measurement
1 parent d3cdb94 commit e3dd09d

10 files changed

+92
-9
lines changed

client/src/api/BackendManager.ts

+2
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import {
2222
SampleRetrievalResult,
2323
SampleRequest
2424
} from "@backend/types/SampleTypes";
25+
import { perfStart } from "../utils/misc";
2526

2627
export {
2728
SampleRetrieval,
@@ -79,6 +80,7 @@ export class BackendManager implements IBackendClient {
7980
};
8081

8182
await fetchAdapter(fetchProps);
83+
perfStart("fetch");
8284
}
8385

8486
private successHandler = (data: any): void => {

client/src/components/BaseComponent.tsx

+5
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
**/
1313
import * as React from "react";
1414
import styles from "../css/base-component.module.css";
15+
import { perfEnd } from "../utils/misc";
1516

1617
const cssStyle: Record<string, string> = {
1718
container: styles["component_container"],
@@ -28,6 +29,10 @@ export const BaseComponent: React.FC<IBaseComponent> = props => {
2829
const LeftComponent = props.leftComponent;
2930
const RightComponent = props.rightComponent;
3031

32+
React.useEffect(() => {
33+
perfEnd();
34+
}, []);
35+
3136
return (
3237
<main className={cssStyle.container}>
3338
<div className={cssStyle.left}>

client/src/components/ComponentA.tsx

+4-1
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,9 @@ const Description: React.FC = _props => {
4141

4242
export const ComponentA: React.FC = _props => {
4343
return (
44-
<BaseComponent leftComponent={Navigation} rightComponent={Description} />
44+
<BaseComponent
45+
leftComponent={Navigation}
46+
rightComponent={Description}
47+
/>
4548
);
4649
};

client/src/components/ComponentB.tsx

+4-1
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,10 @@ export const ComponentB: React.FC = _props => {
9292
name={pageName}
9393
description={pageDescription}
9494
/>
95-
<BaseComponent leftComponent={Navigation} rightComponent={Description} />
95+
<BaseComponent
96+
leftComponent={Navigation}
97+
rightComponent={Description}
98+
/>
9699
</React.Fragment>
97100
);
98101
};

client/src/components/Lighthouse.tsx

+4-1
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,9 @@ const Description: React.FC = _props => {
8686

8787
export const Lighthouse: React.FC = _props => {
8888
return (
89-
<BaseComponent leftComponent={Navigation} rightComponent={Description} />
89+
<BaseComponent
90+
leftComponent={Navigation}
91+
rightComponent={Description}
92+
/>
9093
);
9194
};

client/src/components/NameLookup.tsx

+13-2
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,11 @@ import {
3333
isError,
3434
isCustomError,
3535
} from "../utils/typeguards";
36-
import { getTitle, getCanonical } from "../utils/misc";
36+
import {
37+
getTitle,
38+
getCanonical,
39+
perfEnd
40+
} from "../utils/misc";
3741

3842
//#region CSS
3943

@@ -160,6 +164,10 @@ const NameLookupContent: React.FC = _props => {
160164
(outcome as SampleRetrievalResult).response.gender;
161165
}
162166

167+
React.useEffect(() => {
168+
!!outcome && !isOutcomeFailure() && perfEnd();
169+
}, [outcome]);
170+
163171
//#region Render
164172

165173
return (
@@ -255,6 +263,9 @@ const NameLookupContent: React.FC = _props => {
255263

256264
export const NameLookup: React.FC = _props => {
257265
return (
258-
<BaseComponent leftComponent={Navigation} rightComponent={NameLookupContent} />
266+
<BaseComponent
267+
leftComponent={Navigation}
268+
rightComponent={NameLookupContent}
269+
/>
259270
);
260271
};

client/src/components/Navigation.tsx

+7
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import { Menu, Icon } from "semantic-ui-react";
1010
import * as SPAs from "../../config/spa.config";
1111
import styles from "../css/navigation.module.css";
1212
import { isServer } from "../utils/postprocess/misc";
13+
import { perfStart } from "../utils/misc";
1314

1415
const cssStyle: Record<string, string> = {
1516
menu: styles["menu"],
@@ -36,6 +37,8 @@ export const Navigation: React.FC = _props => {
3637
}
3738
}, []); // run once upon initial rendering
3839

40+
const onClickHandler = () => perfStart("click");
41+
3942
return (
4043
<nav className={cssStyle.menu}>
4144
<Menu
@@ -51,6 +54,7 @@ export const Navigation: React.FC = _props => {
5154
header
5255
as={NavLink}
5356
exact to={pathArray[0]}
57+
onClick={onClickHandler}
5458
>
5559
Overview
5660
<Icon name="file alternate outline" size="large" />
@@ -59,6 +63,7 @@ export const Navigation: React.FC = _props => {
5963
header
6064
as={NavLink}
6165
to={pathArray[1]}
66+
onClick={onClickHandler}
6267
>
6368
ComponentA
6469
<Icon name="cube" size="large" />
@@ -67,6 +72,7 @@ export const Navigation: React.FC = _props => {
6772
header
6873
as={NavLink}
6974
to={pathArray[2]}
75+
onClick={onClickHandler}
7076
>
7177
Lighthouse
7278
<Icon name="tachometer alternate" size="large" />
@@ -75,6 +81,7 @@ export const Navigation: React.FC = _props => {
7581
header
7682
as={NavLink}
7783
to={pathArray[3]}
84+
onClick={onClickHandler}
7885
>
7986
NameLookup
8087
<Icon name="search" size="large" />

client/src/components/NotFound.tsx

+4-1
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,9 @@ as a replacement for HTML 404 status code.";
3939

4040
export const NotFound: React.FC = _props => {
4141
return (
42-
<BaseComponent leftComponent={Navigation} rightComponent={Description} />
42+
<BaseComponent
43+
leftComponent={Navigation}
44+
rightComponent={Description}
45+
/>
4346
);
4447
};

client/src/components/Overview.tsx

+10-3
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,12 @@ const Description: React.FC = _props => {
7272
name={pageName}
7373
description={pageDescription}
7474
/>
75-
<Message css={cssMessage} className={cssStyle.msg}>
76-
<Icon css={cssIcon}
75+
<Message
76+
css={cssMessage}
77+
className={cssStyle.msg}
78+
>
79+
<Icon
80+
css={cssIcon}
7781
name="info circle"
7882
color="blue"
7983
size="big"
@@ -119,6 +123,9 @@ const Description: React.FC = _props => {
119123

120124
export const Overview: React.FC = _props => {
121125
return (
122-
<BaseComponent leftComponent={Navigation} rightComponent={Description} />
126+
<BaseComponent
127+
leftComponent={Navigation}
128+
rightComponent={Description}
129+
/>
123130
);
124131
};

client/src/utils/misc.ts

+39
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
import { isServer } from "./postprocess/misc";
22
import * as SPAs from "../../config/spa.config";
3+
import logger from "./logger";
4+
5+
//#region SEO
36

47
const regexPath1Literal = `/${SPAs.getRedirectName()}(.html)?$`;
58
const regexPath1 = new RegExp(regexPath1Literal, "i");
@@ -20,3 +23,39 @@ export const getTitle = (pageTitle?: string): string => {
2023
const ret = !!pageTitle? `${SPAs.appTitle} - ${pageTitle}` : SPAs.appTitle;
2124
return ret + (CF_PAGES? " (Jamstack build)" : " (Full stack build)");
2225
}
26+
27+
//#endregion
28+
29+
//#region Performance Benchmarking
30+
31+
const perfLiterals = ["fetch", "click", "end", "measure", "mark"];
32+
33+
export const perfStart = (name: "click"|"fetch") => {
34+
const perf = window?.performance;
35+
perf?.mark(name);
36+
}
37+
38+
export const perfEnd = (): undefined|number => {
39+
if (typeof(window?.performance?.getEntriesByName) !== "function") {
40+
return undefined;
41+
}
42+
43+
const perf = window.performance;
44+
const fetchEntries = perf.getEntriesByName(perfLiterals[0], perfLiterals[4]);
45+
const clickEntries = perf.getEntriesByName(perfLiterals[1], perfLiterals[4]);
46+
const clickEntriesLen = Math.min(...[clickEntries.length, 1]);
47+
48+
if (clickEntriesLen === 0 && fetchEntries.length === 0) {
49+
return undefined;
50+
}
51+
52+
perf.mark(perfLiterals[2]);
53+
perf.measure(perfLiterals[3], perfLiterals[clickEntriesLen], perfLiterals[2]);
54+
const duration = performance.getEntriesByType(perfLiterals[3])[0].duration;
55+
logger.info(`${clickEntriesLen === 0? "Updating" : "Transition to"} internal SPA page ${clickEntriesLen === 0? "after fetch ": ""}took ${Math.round(duration)} msec`);
56+
perf.clearMarks();
57+
perf.clearMeasures();
58+
return duration;
59+
}
60+
61+
//#endregion

0 commit comments

Comments
 (0)