mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
feat(site): display client errors in DERP Region health page (#12318)
This commit is contained in:
@@ -2,7 +2,7 @@ import Tooltip from "@mui/material/Tooltip";
|
||||
import CodeOutlined from "@mui/icons-material/CodeOutlined";
|
||||
import TagOutlined from "@mui/icons-material/TagOutlined";
|
||||
import ArrowBackOutlined from "@mui/icons-material/ArrowBackOutlined";
|
||||
import { useTheme } from "@emotion/react";
|
||||
import { Interpolation, Theme, useTheme } from "@emotion/react";
|
||||
import { type FC } from "react";
|
||||
import { Helmet } from "react-helmet-async";
|
||||
import { Link, useOutletContext, useParams } from "react-router-dom";
|
||||
@@ -57,7 +57,7 @@ export const DERPRegionPage: FC = () => {
|
||||
color: theme.palette.text.primary,
|
||||
},
|
||||
marginBottom: 8,
|
||||
lineHeight: "120%",
|
||||
lineHeight: "1.2",
|
||||
}}
|
||||
to="/health/derp"
|
||||
>
|
||||
@@ -115,62 +115,20 @@ export const DERPRegionPage: FC = () => {
|
||||
fontSize: 14,
|
||||
}}
|
||||
>
|
||||
<header
|
||||
css={{
|
||||
padding: 24,
|
||||
display: "flex",
|
||||
justifyContent: "space-between",
|
||||
alignItems: "center",
|
||||
}}
|
||||
>
|
||||
<header css={reportStyles.header}>
|
||||
<div>
|
||||
<h4
|
||||
css={{
|
||||
fontWeight: 500,
|
||||
margin: 0,
|
||||
lineHeight: "120%",
|
||||
}}
|
||||
>
|
||||
{node.HostName}
|
||||
</h4>
|
||||
<div
|
||||
css={{
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
gap: 8,
|
||||
color: theme.palette.text.secondary,
|
||||
fontSize: 12,
|
||||
lineHeight: "120%",
|
||||
marginTop: 8,
|
||||
}}
|
||||
>
|
||||
<h4 css={reportStyles.title}>{node.HostName}</h4>
|
||||
<div css={reportStyles.ports}>
|
||||
<span>DERP Port: {node.DERPPort ?? "None"}</span>
|
||||
<span>STUN Port: {node.STUNPort ?? "None"}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div css={{ display: "flex", gap: 8, alignItems: "center" }}>
|
||||
<div css={reportStyles.pills}>
|
||||
<Tooltip title="Round trip ping">
|
||||
<Pill
|
||||
css={{ color: latencyColor }}
|
||||
icon={
|
||||
<div
|
||||
css={{
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
}}
|
||||
>
|
||||
<div
|
||||
css={{
|
||||
width: 8,
|
||||
height: 8,
|
||||
backgroundColor: latencyColor,
|
||||
borderRadius: 9999,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
}
|
||||
icon={<StatusCircle color={latencyColor} />}
|
||||
>
|
||||
{report.round_trip_ping_ms}ms
|
||||
</Pill>
|
||||
@@ -183,14 +141,13 @@ export const DERPRegionPage: FC = () => {
|
||||
</BooleanPill>
|
||||
</div>
|
||||
</header>
|
||||
<Logs
|
||||
lines={logs?.[0] ?? []}
|
||||
css={{
|
||||
borderBottomLeftRadius: 8,
|
||||
borderBottomRightRadius: 8,
|
||||
borderTop: `1px solid ${theme.palette.divider}`,
|
||||
}}
|
||||
/>
|
||||
<Logs lines={logs?.flat() ?? []} css={reportStyles.logs} />
|
||||
{report.client_errs.length > 0 && (
|
||||
<Logs
|
||||
lines={report.client_errs.flat()}
|
||||
css={[reportStyles.logs, reportStyles.clientErrors]}
|
||||
/>
|
||||
)}
|
||||
</section>
|
||||
);
|
||||
})}
|
||||
@@ -199,4 +156,68 @@ export const DERPRegionPage: FC = () => {
|
||||
);
|
||||
};
|
||||
|
||||
type StatusCircleProps = { color: string };
|
||||
|
||||
const StatusCircle: FC<StatusCircleProps> = ({ color }) => {
|
||||
return (
|
||||
<div
|
||||
css={{
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
}}
|
||||
>
|
||||
<div
|
||||
css={{
|
||||
width: 8,
|
||||
height: 8,
|
||||
backgroundColor: color,
|
||||
borderRadius: 9999,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const reportStyles = {
|
||||
header: {
|
||||
padding: 24,
|
||||
display: "flex",
|
||||
justifyContent: "space-between",
|
||||
alignItems: "center",
|
||||
},
|
||||
title: {
|
||||
fontWeight: 500,
|
||||
margin: 0,
|
||||
lineHeight: "1",
|
||||
},
|
||||
pills: {
|
||||
display: "flex",
|
||||
gap: 8,
|
||||
alignItems: "center",
|
||||
},
|
||||
ports: (theme) => ({
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
gap: 8,
|
||||
color: theme.palette.text.secondary,
|
||||
fontSize: 12,
|
||||
lineHeight: "1.2",
|
||||
marginTop: 8,
|
||||
}),
|
||||
divider: (theme) => ({
|
||||
height: 1,
|
||||
backgroundColor: theme.palette.divider,
|
||||
}),
|
||||
logs: (theme) => ({
|
||||
borderBottomLeftRadius: 8,
|
||||
borderBottomRightRadius: 8,
|
||||
borderTop: `1px solid ${theme.palette.divider}`,
|
||||
}),
|
||||
clientErrors: (theme) => ({
|
||||
background: theme.roles.error.background,
|
||||
color: theme.roles.error.text,
|
||||
}),
|
||||
} satisfies Record<string, Interpolation<Theme>>;
|
||||
|
||||
export default DERPRegionPage;
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import type { Meta } from "@storybook/react";
|
||||
import { useQueryClient } from "react-query";
|
||||
import {
|
||||
reactRouterParameters,
|
||||
reactRouterOutlet,
|
||||
@@ -7,6 +6,7 @@ import {
|
||||
} from "storybook-addon-react-router-v6";
|
||||
import { chromatic } from "testHelpers/chromatic";
|
||||
import {
|
||||
MockAppearanceConfig,
|
||||
MockBuildInfo,
|
||||
MockEntitlements,
|
||||
MockExperiments,
|
||||
@@ -14,8 +14,8 @@ import {
|
||||
MockHealthSettings,
|
||||
} from "testHelpers/entities";
|
||||
import { HEALTH_QUERY_KEY, HEALTH_QUERY_SETTINGS_KEY } from "api/queries/debug";
|
||||
import { DashboardProvider } from "modules/dashboard/DashboardProvider";
|
||||
import { HealthLayout } from "./HealthLayout";
|
||||
import { withDashboardProvider } from "testHelpers/storybook";
|
||||
|
||||
type MetaOptions = {
|
||||
element: RouteDefinition;
|
||||
@@ -33,27 +33,15 @@ export const generateMeta = ({ element, path, params }: MetaOptions): Meta => {
|
||||
location: { pathParams: params },
|
||||
routing: reactRouterOutlet({ path }, element),
|
||||
}),
|
||||
queries: [
|
||||
{ key: HEALTH_QUERY_KEY, data: MockHealth },
|
||||
{ key: HEALTH_QUERY_SETTINGS_KEY, data: MockHealthSettings },
|
||||
{ key: ["buildInfo"], data: MockBuildInfo },
|
||||
{ key: ["entitlements"], data: MockEntitlements },
|
||||
{ key: ["experiments"], data: MockExperiments },
|
||||
{ key: ["appearance"], data: MockAppearanceConfig },
|
||||
],
|
||||
decorators: [withDashboardProvider],
|
||||
},
|
||||
decorators: [
|
||||
(Story) => {
|
||||
const queryClient = useQueryClient();
|
||||
queryClient.setQueryData(HEALTH_QUERY_KEY, MockHealth);
|
||||
queryClient.setQueryData(HEALTH_QUERY_SETTINGS_KEY, MockHealthSettings);
|
||||
return <Story />;
|
||||
},
|
||||
(Story) => {
|
||||
const queryClient = useQueryClient();
|
||||
queryClient.setQueryData(["buildInfo"], MockBuildInfo);
|
||||
queryClient.setQueryData(["entitlements"], MockEntitlements);
|
||||
queryClient.setQueryData(["experiments"], MockExperiments);
|
||||
queryClient.setQueryData(["appearance"], MockExperiments);
|
||||
|
||||
return (
|
||||
<DashboardProvider>
|
||||
<Story />
|
||||
</DashboardProvider>
|
||||
);
|
||||
},
|
||||
],
|
||||
};
|
||||
};
|
||||
|
||||
@@ -2591,7 +2591,17 @@ export const MockHealth: TypesGen.HealthcheckReport = {
|
||||
"derphttp.Client.Connect: connecting to https://dev.coder.com/derp",
|
||||
],
|
||||
],
|
||||
client_errs: [[], []],
|
||||
client_errs: [
|
||||
["recv derp message: derphttp.Client closed"],
|
||||
[
|
||||
"connect to derp: derphttp.Client.Connect connect to <https://sao-paulo.fly.dev.coder.com/derp>: context deadline exceeded: read tcp 10.44.1.150:59546->149.248.214.149:443: use of closed network connection",
|
||||
"connect to derp: derphttp.Client closed",
|
||||
"connect to derp: derphttp.Client closed",
|
||||
"connect to derp: derphttp.Client closed",
|
||||
"connect to derp: derphttp.Client closed",
|
||||
"couldn't connect after 5 tries, last error: couldn't connect after 5 tries, last error: derphttp.Client closed",
|
||||
],
|
||||
],
|
||||
stun: {
|
||||
Enabled: false,
|
||||
CanSTUN: false,
|
||||
|
||||
Reference in New Issue
Block a user