Skip to content

Commit

Permalink
Create a Timings tab (#1063)
Browse files Browse the repository at this point in the history
A new way to see the time network time between chunks.
  • Loading branch information
alvarlagerlof committed Jun 9, 2024
1 parent b2e3f15 commit 44a478e
Show file tree
Hide file tree
Showing 4 changed files with 165 additions and 0 deletions.
11 changes: 11 additions & 0 deletions .changeset/chilled-socks-flow.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
"@rsc-parser/core": minor
"@rsc-parser/embedded-example": minor
"@rsc-parser/chrome-extension": minor
"@rsc-parser/embedded": minor
"@rsc-parser/react-client": minor
"@rsc-parser/storybook": minor
"@rsc-parser/website": minor
---

Create a Timings tab
10 changes: 10 additions & 0 deletions packages/core/src/components/RequestDetail.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { RequestDetailTabParsedPayload } from "./RequestDetailTabParsedPayload";
import { RequestDetailTabNetwork } from "./RequestDetailTabNetwork";
import { RequestDetailTabHeaders } from "./RequestDetailTabHeaders";
import { useTabStoreWithTransitions } from "./useTabStoreWithTransitions";
import { RequestDetailTabTimings } from "./RequestDetailTabTimings";

export function RequestDetail({ events }: { events: RscEvent[] }) {
const { currentTab, isPending, tabStore } = useTabStoreWithTransitions({
Expand Down Expand Up @@ -42,6 +43,12 @@ export function RequestDetail({ events }: { events: RscEvent[] }) {
>
Raw payload
</Tab>
<Tab
id="timings"
className="rounded-md bg-slate-200 px-2 py-0.5 aria-disabled:opacity-50 aria-selected:bg-slate-300 dark:bg-slate-700 dark:aria-selected:text-black"
>
Timings
</Tab>
<Tab
id="network"
className="text-nowrap rounded-md bg-slate-200 px-2 py-0.5 aria-disabled:opacity-50 aria-selected:bg-slate-300 dark:bg-slate-700 dark:aria-selected:text-black"
Expand All @@ -68,6 +75,9 @@ export function RequestDetail({ events }: { events: RscEvent[] }) {
{currentTab === "rawPayload" ? (
<RequestDetailTabRawPayload events={events} />
) : null}
{currentTab === "timings" ? (
<RequestDetailTabTimings events={events} />
) : null}
{currentTab === "network" ? (
<RequestDetailTabNetwork events={events} />
) : null}
Expand Down
35 changes: 35 additions & 0 deletions packages/core/src/components/RequestDetailTabTimings.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import React from "react";
import type { Meta, StoryObj } from "@storybook/react";

import { RequestDetailTabTimings } from "./RequestDetailTabTimings";
import { alvarDevExampleData } from "../example-data/alvar-dev";
import { ghFredkissDevExampleData } from "../example-data/gh-fredkiss-dev";
import { nextjsOrgExampleData } from "../example-data/nextjs-org";

const meta: Meta<typeof RequestDetailTabTimings> = {
component: RequestDetailTabTimings,
};

export default meta;
type Story = StoryObj<typeof RequestDetailTabTimings>;

export const alvarDev: Story = {
name: "alvar.dev",
render: () => {
return <RequestDetailTabTimings events={alvarDevExampleData} />;
},
};

export const ghFredKissDev: Story = {
name: "gh.fredkiss.dev",
render: () => {
return <RequestDetailTabTimings events={ghFredkissDevExampleData} />;
},
};

export const nextjsOrg: Story = {
name: "nextjs.org",
render: () => {
return <RequestDetailTabTimings events={nextjsOrgExampleData} />;
},
};
109 changes: 109 additions & 0 deletions packages/core/src/components/RequestDetailTabTimings.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
import React from "react";
import { eventsFilterByMaxTimestamp } from "../eventArrayHelpers";
import {
RscEvent,
isRscChunkEvent,
isRscRequestEvent,
isRscResponseEvent,
} from "../events";
import { useEndTime } from "./EndTimeContext";
import { RequestDetailTabEmptyState } from "./RequestDetailTabEmptyState";
import { getColorForFetch } from "../color";

export function RequestDetailTabTimings({ events }: { events: RscEvent[] }) {
const { endTime } = useEndTime();

const timeFilteredEvents = eventsFilterByMaxTimestamp(events, endTime);

if (timeFilteredEvents.length === 0) {
return <RequestDetailTabEmptyState />;
}

const requestEvent = timeFilteredEvents.filter(isRscRequestEvent)[0];
const responseEvent = timeFilteredEvents.filter(isRscResponseEvent)[0];

if (!requestEvent) {
return <RequestDetailTabEmptyState />;
}

const startTimeStamp = requestEvent.data.timestamp;
const endTimestamp = events.at(-1)?.data.timestamp;

if (!endTimestamp) {
return <RequestDetailTabEmptyState />;
}

const timings: {
name: string;
offset: number | null;
color: string;
}[] = [];

timings.push({
name: "Request start",
offset: startTimeStamp - startTimeStamp,
color: getColorForFetch("1"),
});

if (responseEvent) {
timings.push({
name: "Response start",
offset: responseEvent.data.timestamp - startTimeStamp,
color: getColorForFetch("20"),
});

timeFilteredEvents.filter(isRscChunkEvent).forEach((event, index) => {
timings.push({
name: `Chunk ${index}`,
offset: event.data.timestamp - startTimeStamp,
color: getColorForFetch("30"),
});
});

if (
timeFilteredEvents.find((event) => event.data.timestamp === endTimestamp)
) {
timings.push({
name: "Response end",
offset: endTimestamp ? endTimestamp - startTimeStamp : null,
color: getColorForFetch("20"),
});
}
}

const maxOffset = (endTimestamp ?? 500) - startTimeStamp;

return (
<ul className="flex max-w-lg flex-col gap-3">
{timings.map((timing) => {
return (
<li key={timing.name} className="flex flex-col gap-0">
<p>{timing.name}</p>
<div className="flex flex-row items-center gap-2">
<div
className="h-3 rounded-full"
style={{
background: timing.color,
width: getWidthByOffset(timing.offset, maxOffset),
}}
/>
{timing.offset !== null ? <p>{timing.offset}ms</p> : <p>-</p>}
</div>
</li>
);
})}
</ul>
);
}

function getWidthByOffset(offset: number | null, biggestOffset: number) {
if (offset === null) {
return "100%";
}

if (offset === 0) {
return "3px";
}

return `${(offset / biggestOffset) * 100}%`;
}

0 comments on commit 44a478e

Please sign in to comment.