chore(tracing): remove proactive snapshotSizes caching (#8126)

This commit is contained in:
Pavel Feldman 2021-08-10 17:06:14 -07:00 committed by GitHub
parent 362aed4cce
commit 76150f1bcb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 56 additions and 37 deletions

View file

@ -33,6 +33,10 @@ export class SnapshotRenderer {
return this._snapshots[this._index]; return this._snapshots[this._index];
} }
viewport(): { width: number, height: number } {
return this._snapshots[this._index].viewport;
}
render(): RenderedFrameSnapshot { render(): RenderedFrameSnapshot {
const visit = (n: NodeSnapshot, snapshotIndex: number): string => { const visit = (n: NodeSnapshot, snapshotIndex: number): string => {
// Text node. // Text node.

View file

@ -28,6 +28,7 @@ export class SnapshotServer {
this._snapshotStorage = snapshotStorage; this._snapshotStorage = snapshotStorage;
server.routePrefix('/snapshot/', this._serveSnapshot.bind(this)); server.routePrefix('/snapshot/', this._serveSnapshot.bind(this));
server.routePrefix('/snapshotSize/', this._serveSnapshotSize.bind(this));
server.routePrefix('/resources/', this._serveResource.bind(this)); server.routePrefix('/resources/', this._serveResource.bind(this));
} }
@ -152,16 +153,28 @@ export class SnapshotServer {
return this._serveSnapshotRoot(request, response); return this._serveSnapshotRoot(request, response);
if (request.url!.endsWith('/snapshot/service-worker.js')) if (request.url!.endsWith('/snapshot/service-worker.js'))
return this._serveServiceWorker(request, response); return this._serveServiceWorker(request, response);
const snapshot = this._snapshot(request.url!.substring('/snapshot/'.length));
this._respondWithJson(response, snapshot ? snapshot.render() : { html: '' });
return true;
}
private _serveSnapshotSize(request: http.IncomingMessage, response: http.ServerResponse): boolean {
const snapshot = this._snapshot(request.url!.substring('/snapshotSize/'.length));
this._respondWithJson(response, snapshot ? snapshot.viewport() : {});
return true;
}
private _snapshot(uri: string) {
const [ pageOrFrameId, query ] = uri.split('?');
const parsed: any = querystring.parse(query);
return this._snapshotStorage.snapshotByName(pageOrFrameId, parsed.name);
}
private _respondWithJson(response: http.ServerResponse, object: any) {
response.statusCode = 200; response.statusCode = 200;
response.setHeader('Cache-Control', 'public, max-age=31536000'); response.setHeader('Cache-Control', 'public, max-age=31536000');
response.setHeader('Content-Type', 'application/json'); response.setHeader('Content-Type', 'application/json');
const [ pageOrFrameId, query ] = request.url!.substring('/snapshot/'.length).split('?'); response.end(JSON.stringify(object));
const parsed: any = querystring.parse(query);
const snapshot = this._snapshotStorage.snapshotByName(pageOrFrameId, parsed.name);
const snapshotData: any = snapshot ? snapshot.render() : { html: '' };
response.end(JSON.stringify(snapshotData));
return true;
} }
private _serveResource(request: http.IncomingMessage, response: http.ServerResponse): boolean { private _serveResource(request: http.IncomingMessage, response: http.ServerResponse): boolean {

View file

@ -38,7 +38,6 @@ export class TraceModel {
options: { sdkLanguage: '' }, options: { sdkLanguage: '' },
pages: [], pages: [],
resources: [], resources: [],
snapshotSizes: {},
}; };
} }
@ -98,8 +97,6 @@ export class TraceModel {
break; break;
case 'frame-snapshot': case 'frame-snapshot':
this._snapshotStorage.addFrameSnapshot(event.snapshot); this._snapshotStorage.addFrameSnapshot(event.snapshot);
if (event.snapshot.snapshotName && event.snapshot.isMainFrame)
this.contextEntry.snapshotSizes[event.snapshot.snapshotName] = event.snapshot.viewport;
break; break;
} }
if (event.type === 'action' || event.type === 'event') { if (event.type === 'action' || event.type === 'event') {
@ -142,7 +139,6 @@ export type ContextEntry = {
options: BrowserContextOptions; options: BrowserContextOptions;
pages: PageEntry[]; pages: PageEntry[];
resources: ResourceSnapshot[]; resources: ResourceSnapshot[];
snapshotSizes: { [snapshotName: string]: { width: number, height: number } };
}; };
export type PageEntry = { export type PageEntry = {

View file

@ -19,14 +19,12 @@ import './snapshotTab.css';
import './tabbedPane.css'; import './tabbedPane.css';
import * as React from 'react'; import * as React from 'react';
import { useMeasure } from './helpers'; import { useMeasure } from './helpers';
import type { Point } from '../../../common/types';
import { ActionTraceEvent } from '../../../server/trace/common/traceEvents'; import { ActionTraceEvent } from '../../../server/trace/common/traceEvents';
export const SnapshotTab: React.FunctionComponent<{ export const SnapshotTab: React.FunctionComponent<{
action: ActionTraceEvent | undefined, action: ActionTraceEvent | undefined,
snapshotSizes: { [snapshotName: string]: Size },
defaultSnapshotSize: Size, defaultSnapshotSize: Size,
}> = ({ action, snapshotSizes, defaultSnapshotSize }) => { }> = ({ action, defaultSnapshotSize }) => {
const [measure, ref] = useMeasure<HTMLDivElement>(); const [measure, ref] = useMeasure<HTMLDivElement>();
const [snapshotIndex, setSnapshotIndex] = React.useState(0); const [snapshotIndex, setSnapshotIndex] = React.useState(0);
@ -36,35 +34,44 @@ export const SnapshotTab: React.FunctionComponent<{
const actionSnapshot = snapshotMap.get('action') || snapshotMap.get('after'); const actionSnapshot = snapshotMap.get('action') || snapshotMap.get('after');
const snapshots = [actionSnapshot ? { ...actionSnapshot, title: 'action' } : undefined, snapshotMap.get('before'), snapshotMap.get('after')].filter(Boolean) as { title: string, snapshotName: string }[]; const snapshots = [actionSnapshot ? { ...actionSnapshot, title: 'action' } : undefined, snapshotMap.get('before'), snapshotMap.get('after')].filter(Boolean) as { title: string, snapshotName: string }[];
let snapshotUrl = 'data:text/html,<body style="background: #ddd"></body>';
let snapshotSizeUrl: string | undefined;
let pointX: number | undefined;
let pointY: number | undefined;
if (action) {
const snapshot = snapshots[snapshotIndex];
if (snapshot && snapshot.snapshotName) {
snapshotUrl = `${window.location.origin}/snapshot/${action.metadata.pageId}?name=${snapshot.snapshotName}`;
snapshotSizeUrl = `${window.location.origin}/snapshotSize/${action.metadata.pageId}?name=${snapshot.snapshotName}`;
if (snapshot.snapshotName.includes('action')) {
pointX = action.metadata.point?.x;
pointY = action.metadata.point?.y;
}
}
}
React.useEffect(() => { React.useEffect(() => {
if (snapshots.length >= 1 && snapshotIndex >= snapshots.length) if (snapshots.length >= 1 && snapshotIndex >= snapshots.length)
setSnapshotIndex(snapshots.length - 1); setSnapshotIndex(snapshots.length - 1);
}, [snapshotIndex, snapshots]); }, [snapshotIndex, snapshots]);
const iframeRef = React.createRef<HTMLIFrameElement>(); const iframeRef = React.useRef<HTMLIFrameElement>(null);
const [snapshotSize, setSnapshotSize] = React.useState(defaultSnapshotSize);
React.useEffect(() => { React.useEffect(() => {
if (!iframeRef.current) (async () => {
return; if (snapshotSizeUrl) {
let snapshotUri = undefined; const response = await fetch(snapshotSizeUrl);
let point: Point | undefined = undefined; setSnapshotSize(await response.json());
if (action) {
const snapshot = snapshots[snapshotIndex];
if (snapshot && snapshot.snapshotName) {
snapshotUri = `${action.metadata.pageId}?name=${snapshot.snapshotName}`;
if (snapshot.snapshotName.includes('action'))
point = action.metadata.point;
} }
} if (!iframeRef.current)
const snapshotUrl = snapshotUri ? `${window.location.origin}/snapshot/${snapshotUri}` : 'data:text/html,<body style="background: #ddd"></body>'; return;
try { try {
(iframeRef.current.contentWindow as any).showSnapshot(snapshotUrl, { point }); const point = pointX === undefined ? undefined : { x: pointX, y: pointY };
} catch (e) { (iframeRef.current.contentWindow as any).showSnapshot(snapshotUrl, { point });
} } catch (e) {
}, [action, snapshotIndex, iframeRef, snapshots]); }
})();
let snapshotSize = defaultSnapshotSize; }, [iframeRef, snapshotUrl, snapshotSizeUrl, pointX, pointY]);
if (snapshots[snapshotIndex] && snapshots[snapshotIndex].snapshotName)
snapshotSize = snapshotSizes[snapshots[snapshotIndex].snapshotName] || defaultSnapshotSize;
const scale = Math.min(measure.width / snapshotSize.width, measure.height / snapshotSize.height); const scale = Math.min(measure.width / snapshotSize.width, measure.height / snapshotSize.height);
const scaledSize = { const scaledSize = {

View file

@ -89,7 +89,7 @@ export const Workbench: React.FunctionComponent<{
</div> </div>
<SplitView sidebarSize={300} orientation='horizontal' sidebarIsFirst={true}> <SplitView sidebarSize={300} orientation='horizontal' sidebarIsFirst={true}>
<SplitView sidebarSize={300} orientation='horizontal'> <SplitView sidebarSize={300} orientation='horizontal'>
<SnapshotTab action={selectedAction} snapshotSizes={context.snapshotSizes} defaultSnapshotSize={defaultSnapshotSize} /> <SnapshotTab action={selectedAction} defaultSnapshotSize={defaultSnapshotSize} />
<TabbedPane tabs={[ <TabbedPane tabs={[
{ id: 'logs', title: 'Call', count: 0, render: () => <CallTab action={selectedAction} /> }, { id: 'logs', title: 'Call', count: 0, render: () => <CallTab action={selectedAction} /> },
{ id: 'console', title: 'Console', count: consoleCount, render: () => <ConsoleTab action={selectedAction} /> }, { id: 'console', title: 'Console', count: consoleCount, render: () => <ConsoleTab action={selectedAction} /> },
@ -125,5 +125,4 @@ const emptyContext: ContextEntry = {
}, },
pages: [], pages: [],
resources: [], resources: [],
snapshotSizes: {},
}; };