Skip to content

Commit dbd98c9

Browse files
committed
Add Duration column to ViewEventList
1 parent 6e2af0a commit dbd98c9

File tree

3 files changed

+81
-40
lines changed

3 files changed

+81
-40
lines changed

src/components/common/duration-pill.tsx

Lines changed: 3 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -5,47 +5,10 @@ import { TimingEvents } from '../../types';
55
import { observableClock } from '../../util/observable';
66

77
import { Pill } from './pill';
8+
import { calculateAndFormatDuration, FormattedDurationProps } from "../../util/utils";
89

9-
function sigFig(num: number, figs: number): string {
10-
return num.toFixed(figs);
11-
}
12-
13-
type DurationPillProps = { className?: string } & (
14-
| { durationMs: number }
15-
| { timingEvents: Partial<TimingEvents> }
16-
);
17-
18-
const calculateDuration = (timingEvents: Partial<TimingEvents>) => {
19-
const doneTimestamp = timingEvents.responseSentTimestamp ?? timingEvents.abortedTimestamp;
20-
21-
if (timingEvents.startTimestamp !== undefined && doneTimestamp !== undefined) {
22-
return doneTimestamp - timingEvents.startTimestamp;
23-
}
24-
25-
if (timingEvents.startTime !== undefined) {
26-
// This may not be perfect - note that startTime comes from the server so we might be
27-
// mildly out of sync (ehhhh, in theory) but this is only for pending requests where
28-
// that's unlikely to be an issue - the final time will be correct regardless.
29-
return observableClock.getTime() - timingEvents.startTime;
30-
}
31-
}
10+
type DurationPillProps = { className?: string } & FormattedDurationProps;
3211

3312
export const DurationPill = observer((p: DurationPillProps) => {
34-
let duration: number | undefined;
35-
36-
if ('durationMs' in p) {
37-
duration = p.durationMs;
38-
} else if (p.timingEvents) {
39-
duration = calculateDuration(p.timingEvents);
40-
}
41-
42-
if (duration === undefined) return null;
43-
44-
return <Pill className={p.className}>{
45-
duration < 100 ? sigFig(duration, 1) + 'ms' : // 22.3ms
46-
duration < 1000 ? sigFig(duration, 0) + 'ms' : // 999ms
47-
duration < 5000 ? sigFig(duration / 1000, 2) + ' seconds' : // 3.04 seconds
48-
duration < 9900 ? sigFig(duration / 1000, 1) + ' seconds' : // 8.2 seconds
49-
sigFig(duration / 1000, 0) + ' seconds' // 30 seconds
50-
}</Pill>;
13+
return <Pill className={p.className}>{calculateAndFormatDuration(p)}</Pill>;
5114
});

src/components/view/view-event-list.tsx

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import {
2727
} from '../../model/events/categorization';
2828
import { nameStepClass } from '../../model/rules/rule-descriptions';
2929
import { getReadableSize } from '../../util/buffer';
30+
import { calculateAndFormatDuration } from "../../util/utils";
3031

3132
import { UnreachableCheck } from '../../util/error';
3233
import { filterProps } from '../component-utils';
@@ -212,6 +213,33 @@ const PathAndQuery = styled(Column)`
212213
flex-basis: 1000px;
213214
`;
214215

216+
const BaseDuration = observer(({ exchange, role = 'cell', className, children }: {
217+
exchange?: HttpExchange, role?: 'columnheader' | 'cell',
218+
className?: string,
219+
children?: React.ReactNode
220+
}) => {
221+
let duration: string | null | undefined;
222+
if (exchange != null) {
223+
duration = calculateAndFormatDuration({ timingEvents: exchange.timingEvents });
224+
}
225+
return (
226+
<div role={role} className={className}>
227+
{duration ?
228+
duration :
229+
(children ?? 'Duration')
230+
}
231+
</div>
232+
);
233+
});
234+
235+
const Duration = styled(BaseDuration)`
236+
${columnStyles};
237+
flex-basis: 71px;
238+
flex-shrink: 0;
239+
flex-grow: 0;
240+
`;
241+
242+
215243
// Match Method + Status, but shrink right margin slightly so that
216244
// spinner + "WebRTC Media" fits OK.
217245
const EventTypeColumn = styled(Column)`
@@ -515,6 +543,7 @@ const ExchangeRow = inject('uiStore')(observer(({
515543
<PathAndQuery role='cell' title={request.parsedUrl.pathname + request.parsedUrl.search}>
516544
{request.parsedUrl.pathname + request.parsedUrl.search}
517545
</PathAndQuery>
546+
<Duration role='cell' exchange={exchange} />
518547
</TrafficEventListRow>;
519548
}));
520549

@@ -833,6 +862,7 @@ export class ViewEventList extends React.Component<ViewEventListProps> {
833862
<Source role="columnheader">Source</Source>
834863
<Host role="columnheader">Host</Host>
835864
<PathAndQuery role="columnheader">Path and query</PathAndQuery>
865+
<Duration role="columnheader">Duration</Duration>
836866
</TableHeaderRow>
837867

838868
{

src/util/utils.ts

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import { TimingEvents } from "../types";
2+
import { observableClock } from "./observable";
3+
4+
export type FormattedDurationProps =
5+
{
6+
durationMs?: number,
7+
timingEvents: Partial<TimingEvents>
8+
};
9+
10+
export const calculateDuration = (timingEvents: Partial<TimingEvents>): number | undefined => {
11+
const doneTimestamp = timingEvents.responseSentTimestamp ?? timingEvents.abortedTimestamp ?? timingEvents.wsClosedTimestamp;
12+
13+
if (timingEvents.startTimestamp !== undefined && doneTimestamp !== undefined) {
14+
return doneTimestamp - timingEvents.startTimestamp;
15+
}
16+
17+
if (timingEvents.startTime !== undefined) {
18+
// This may not be perfect - note that startTime comes from the server so we might be
19+
// mildly out of sync (ehhhh, in theory) but this is only for pending requests where
20+
// that's unlikely to be an issue - the final time will be correct regardless.
21+
return observableClock.getTime() - timingEvents.startTime;
22+
}
23+
}
24+
25+
export const calculateAndFormatDuration = (props: FormattedDurationProps): string | null | undefined => {
26+
let duration: number | undefined;
27+
28+
if (props.durationMs !== undefined) {
29+
duration = props.durationMs;
30+
} else if (props.timingEvents) {
31+
duration = calculateDuration(props.timingEvents);
32+
}
33+
34+
if (duration === undefined)
35+
return null;
36+
37+
return (
38+
duration < 100 ? sigFig(duration, 1) + 'ms' : // 22.3ms
39+
duration < 1000 ? sigFig(duration, 0) + 'ms' : // 999ms
40+
duration < 5000 ? sigFig(duration / 1000, 2) + 's' : // 3.04s
41+
duration < 59000 ? sigFig(duration / 1000, 1) + 's' : // 30.2s
42+
sigFig(duration / 60000, 1) + 'm' // 1.1m
43+
);
44+
};
45+
46+
function sigFig(num: number, figs: number): string {
47+
return num.toFixed(figs);
48+
}

0 commit comments

Comments
 (0)