diff --git a/src/components/view/http/http-performance-card.tsx b/src/components/view/http/http-performance-card.tsx
index 9ec10940..70e24ed1 100644
--- a/src/components/view/http/http-performance-card.tsx
+++ b/src/components/view/http/http-performance-card.tsx
@@ -5,7 +5,6 @@ import { get } from 'typesafe-get';
import { styled } from '../../../styles';
import {
- Omit,
HttpExchange,
TimingEvents,
ExchangeMessage
@@ -14,7 +13,7 @@ import { asHeaderArray, joinAnd } from '../../../util';
import { Icon, WarningIcon, SuggestionIcon } from '../../../icons';
import { AccountStore } from '../../../model/account/account-store';
-import { getReadableSize, testEncodings } from '../../../model/events/bodies';
+import {getReadableDuration, getReadableSize, testEncodings} from '../../../model/events/bodies';
import {
explainCacheability,
explainCacheLifetime,
@@ -41,10 +40,6 @@ interface HttpPerformanceCardProps extends CollapsibleCardProps {
accountStore?: AccountStore;
}
-function sigFig(num: number, figs: number): number {
- return parseFloat(num.toFixed(figs));
-}
-
const TimingPill = observer((p: { className?: string, timingEvents: TimingEvents }) => {
// We can't show timing info if the request is still going
const doneTimestamp = p.timingEvents.responseSentTimestamp || p.timingEvents.abortedTimestamp;
@@ -52,12 +47,7 @@ const TimingPill = observer((p: { className?: string, timingEvents: TimingEvents
const durationMs = doneTimestamp - p.timingEvents.startTimestamp;
- return {
- durationMs < 100 ? sigFig(durationMs, 2) + 'ms' : // 22.34ms
- durationMs < 1000 ? sigFig(durationMs, 1) + 'ms' : // 999.5ms
- durationMs < 10000 ? sigFig(durationMs / 1000, 3) + ' seconds' : // 3.045 seconds
- sigFig(durationMs / 1000, 1) + ' seconds' // 11.2 seconds
- };
+ return {getReadableDuration(durationMs)};
});
export const HttpPerformanceCard = inject('accountStore')(observer((props: HttpPerformanceCardProps) => {
@@ -342,4 +332,4 @@ const CachingPerformance = observer((p: { exchange: HttpExchange }) => {
) }
>;
-});
\ No newline at end of file
+});
diff --git a/src/components/view/view-event-list.tsx b/src/components/view/view-event-list.tsx
index 9b197f3d..d11195a3 100644
--- a/src/components/view/view-event-list.tsx
+++ b/src/components/view/view-event-list.tsx
@@ -23,7 +23,11 @@ import {
} from '../../model/events/categorization';
import { UnreachableCheck } from '../../util/error';
-import { getReadableSize } from '../../model/events/bodies';
+import {
+ getReadableSize,
+ getReadableDuration
+} from '../../model/events/bodies';
+
import { filterProps } from '../component-utils';
import { EmptyState } from '../common/empty-state';
@@ -166,6 +170,18 @@ const PathAndQuery = styled(Column)`
flex-basis: 1000px;
`;
+const Duration = styled(Column)`
+ flex-basis: 80px;
+ flex-shrink: 0;
+ flex-grow: 0;
+`;
+
+const Size = styled(Column)`
+ flex-basis: 80px;
+ flex-shrink: 0;
+ flex-grow: 0;
+`;
+
// Match Method + Status, but shrink right margin slightly so that
// spinner + "WebRTC Media" fits OK.
const EventTypeColumn = styled(Column)`
@@ -372,6 +388,10 @@ const ExchangeRow = observer(({
category
} = exchange;
+ let durationMs = ('startTime' in exchange.timingEvents) ? (
+ (exchange.timingEvents.responseSentTimestamp || exchange.timingEvents.abortedTimestamp || 0) - exchange.timingEvents.startTimestamp
+ ) : 0;
+
return
{ request.parsedUrl.pathname + request.parsedUrl.search }
+
+ {durationMs > 0 ? getReadableDuration(durationMs) : ''}
+
+
+ { exchange.isSuccessfulExchange() ? getReadableSize(exchange.response.body.encoded.byteLength) : ''}
+
;
});
@@ -666,6 +692,8 @@ export class ViewEventList extends React.Component {
Host
Path and query
+ Duration
+ Size
{
@@ -869,4 +897,4 @@ export class ViewEventList extends React.Component {
event.preventDefault();
}
-}
\ No newline at end of file
+}
diff --git a/src/model/events/bodies.ts b/src/model/events/bodies.ts
index 36bf7fca..e4020a45 100644
--- a/src/model/events/bodies.ts
+++ b/src/model/events/bodies.ts
@@ -18,6 +18,17 @@ export function getReadableSize(bytes: number, siUnits = true) {
return (bytes / Math.pow(thresh, unitIndex)).toFixed(1).replace(/\.0$/, '') + ' ' + unitName;
}
+function sigFig(num: number, figs: number): number {
+ return parseFloat(num.toFixed(figs));
+}
+
+export function getReadableDuration(durationMs: number): string {
+ return (durationMs < 100) ? (sigFig(durationMs, 2) + 'ms') // 22.34ms
+ : (durationMs < 1000 ? sigFig(durationMs, 1) + 'ms' // 999.5ms
+ : (durationMs < 10000 ? sigFig(durationMs / 1000, 3) + ' s' // 3.045 seconds
+ : sigFig(durationMs / 1000, 1) + ' s')) // 11.2 seconds
+}
+
const EncodedSizesCacheKey = Symbol('encoded-body-test');
type EncodedBodySizes = { [encoding: string]: number };
type EncodedSizesCache = Map