feat(trace-viewer): render wall time for each action (#9982)
This commit is contained in:
parent
ad4632935f
commit
6a30c90590
|
|
@ -154,6 +154,7 @@ export class DispatcherConnection {
|
|||
objectId: sdkObject?.guid,
|
||||
pageId: sdkObject?.attribution?.page?.guid,
|
||||
frameId: sdkObject?.attribution?.frame?.guid,
|
||||
wallTime: Date.now(),
|
||||
startTime: monotonicTime(),
|
||||
endTime: 0,
|
||||
type,
|
||||
|
|
@ -228,6 +229,7 @@ export class DispatcherConnection {
|
|||
objectId: sdkObject?.guid,
|
||||
pageId: sdkObject?.attribution?.page?.guid,
|
||||
frameId: sdkObject?.attribution?.frame?.guid,
|
||||
wallTime: Date.now(),
|
||||
startTime: monotonicTime(),
|
||||
endTime: 0,
|
||||
type: dispatcher._type,
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ import { Point, StackFrame, SerializedError } from './channels';
|
|||
|
||||
export type CallMetadata = {
|
||||
id: string;
|
||||
wallTime: number;
|
||||
startTime: number;
|
||||
endTime: number;
|
||||
pauseStartTime?: number;
|
||||
|
|
|
|||
|
|
@ -88,6 +88,7 @@ export function createInstrumentation(): Instrumentation {
|
|||
export function internalCallMetadata(): CallMetadata {
|
||||
return {
|
||||
id: '',
|
||||
wallTime: 0,
|
||||
startTime: 0,
|
||||
endTime: 0,
|
||||
type: 'Internal',
|
||||
|
|
|
|||
|
|
@ -440,6 +440,7 @@ class ContextRecorder extends EventEmitter {
|
|||
objectId: frame.guid,
|
||||
pageId: frame._page.guid,
|
||||
frameId: frame.guid,
|
||||
wallTime: Date.now(),
|
||||
startTime: monotonicTime(),
|
||||
endTime: 0,
|
||||
type: 'Frame',
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@
|
|||
}
|
||||
|
||||
.action-duration {
|
||||
margin-left: 4px;
|
||||
margin: 0 4px;
|
||||
color: var(--gray);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -90,8 +90,8 @@ export const ActionList: React.FC<ActionListProps> = ({
|
|||
<span>{metadata.apiName}</span>
|
||||
{metadata.params.selector && <div className='action-selector' title={metadata.params.selector}>{metadata.params.selector}</div>}
|
||||
{metadata.method === 'goto' && metadata.params.url && <div className='action-url' title={metadata.params.url}>{metadata.params.url}</div>}
|
||||
<span className='action-duration'>— {metadata.endTime ? msToString(metadata.endTime - metadata.startTime) : 'Timed Out'}</span>
|
||||
</div>
|
||||
<div className='action-duration' style={{ flex: 'none' }}>{metadata.endTime ? msToString(metadata.endTime - metadata.startTime) : 'Timed Out'}</div>
|
||||
<div className='action-icons' onClick={() => setSelectedTab('console')}>
|
||||
{!!errors && <div className='action-icon'><span className={'codicon codicon-error'}></span><span className="action-icon-value">{errors}</span></div>}
|
||||
{!!warnings && <div className='action-icon'><span className={'codicon codicon-warning'}></span><span className="action-icon-value">{warnings}</span></div>}
|
||||
|
|
|
|||
|
|
@ -54,10 +54,7 @@
|
|||
overflow: hidden;
|
||||
}
|
||||
|
||||
.call-duration {
|
||||
color: var(--gray);
|
||||
}
|
||||
|
||||
.call-line .datetime,
|
||||
.call-line .string {
|
||||
color: var(--orange);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,12 +32,19 @@ export const CallTab: React.FunctionComponent<{
|
|||
// Strip down the waitForEventInfo data, we never need it.
|
||||
delete params.info;
|
||||
const paramKeys = Object.keys(params);
|
||||
const wallTime = new Date(action.metadata.wallTime).toLocaleString();
|
||||
const duration = msToString(action.metadata.endTime - action.metadata.startTime);
|
||||
return <div className='call-tab'>
|
||||
<div className='call-error' key='error' hidden={!error}>
|
||||
<div className='codicon codicon-issues'/>
|
||||
{error}
|
||||
</div>
|
||||
<div className='call-line'>{action.metadata.apiName} <span className='call-duration'>— {msToString(action.metadata.endTime - action.metadata.startTime)}</span></div>
|
||||
<div className='call-line'>{action.metadata.apiName}</div>
|
||||
{<>
|
||||
<div className='call-section'>Time</div>
|
||||
<div className='call-line'>wall time: <span className='datetime' title={wallTime}>{wallTime}</span></div>
|
||||
<div className='call-line'>duration: <span className='datetime' title={duration}>{duration}</span></div>
|
||||
</>}
|
||||
{ !!paramKeys.length && <div className='call-section'>Parameters</div> }
|
||||
{
|
||||
!!paramKeys.length && paramKeys.map((name, index) => renderLine(action.metadata, name, params[name], 'param-' + index))
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ class LineReporter extends BaseReporter {
|
|||
const title = `[${++this._current}/${this._total}] ${formatTestTitle(this.config, test)}`.substring(0, width);
|
||||
process.stdout.write(`\u001B[1A\u001B[2K${title}\n`);
|
||||
|
||||
if (!this._omitFailures && !this.willRetry(test) && (test.outcome() === 'flaky' || test.outcome() === 'unexpected')) {
|
||||
if (!this.willRetry(test) && (test.outcome() === 'flaky' || test.outcome() === 'unexpected')) {
|
||||
process.stdout.write(`\u001B[1A\u001B[2K`);
|
||||
console.log(formatFailure(this.config, test, {
|
||||
index: ++this._failures
|
||||
|
|
|
|||
|
|
@ -180,19 +180,19 @@ test('should show empty trace viewer', async ({ showTraceViewer }, testInfo) =>
|
|||
test('should open simple trace viewer', async ({ showTraceViewer }) => {
|
||||
const traceViewer = await showTraceViewer(traceFile);
|
||||
await expect(traceViewer.actionTitles).toHaveText([
|
||||
/browserContext.newPage— [\d.ms]+/,
|
||||
/page.gotodata:text\/html,<html>Hello world<\/html>— [\d.ms]+/,
|
||||
/page.setContent— [\d.ms]+/,
|
||||
/expect.toHaveTextbutton— [\d.ms]+/,
|
||||
/page.evaluate— [\d.ms]+/,
|
||||
/page.click"Click"— [\d.ms]+/,
|
||||
/page.waitForEvent— [\d.ms]+/,
|
||||
/page.route— [\d.ms]+/,
|
||||
/page.waitForNavigation— [\d.ms]+/,
|
||||
/page.waitForTimeout— [\d.ms]+/,
|
||||
/page.gotohttp:\/\/localhost:\d+\/frames\/frame.html— [\d.ms]+/,
|
||||
/route.continue— [\d.ms]+/,
|
||||
/page.setViewportSize— [\d.ms]+/,
|
||||
/browserContext.newPage/,
|
||||
/page.gotodata:text\/html,<html>Hello world<\/html>/,
|
||||
/page.setContent/,
|
||||
/expect.toHaveTextbutton/,
|
||||
/page.evaluate/,
|
||||
/page.click"Click"/,
|
||||
/page.waitForEvent/,
|
||||
/page.route/,
|
||||
/page.waitForNavigation/,
|
||||
/page.waitForTimeout/,
|
||||
/page.gotohttp:\/\/localhost:\d+\/frames\/frame.html/,
|
||||
/route.continue/,
|
||||
/page.setViewportSize/,
|
||||
]);
|
||||
});
|
||||
|
||||
|
|
@ -235,7 +235,9 @@ test('should show params and return value', async ({ showTraceViewer, browserNam
|
|||
const traceViewer = await showTraceViewer(traceFile);
|
||||
await traceViewer.selectAction('page.evaluate');
|
||||
await expect(traceViewer.callLines).toHaveText([
|
||||
/page.evaluate — [\d.ms]+/,
|
||||
/page.evaluate/,
|
||||
/wall time: [0-9/:,APM ]+/,
|
||||
/duration: [\d]+ms/,
|
||||
'expression: "({↵ a↵ }) => {↵ console.log(\'Info\');↵ console.warn(\'Warning\');↵ con…"',
|
||||
'isFunction: true',
|
||||
'arg: {"a":"paramA","b":4}',
|
||||
|
|
|
|||
Loading…
Reference in a new issue