Path: blob/master/src/packages/frontend/app/connection-status.tsx
1496 views
import { Badge, Progress, Descriptions, Typography, Space, Alert } from "antd";1import {2CheckCircleOutlined,3CloseCircleOutlined,4SendOutlined,5DownloadOutlined,6UsergroupAddOutlined,7DatabaseOutlined,8} from "@ant-design/icons";9import type { ConatConnectionStatus } from "@cocalc/frontend/conat/client";10import { capitalize } from "@cocalc/util/misc";11import { MAX_SUBSCRIPTIONS_PER_CLIENT } from "@cocalc/conat/core/constants";1213let MAX_SEND_MESSAGES = 1000,14MAX_SEND_BYTES = 1_000_000;15let MAX_RECV_MESSAGES = 2000,16MAX_RECV_BYTES = 10_000_000;1718function bytesToStr(bytes: number): string {19if (bytes < 1024) return bytes + " B";20if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(1) + " KB";21return (bytes / (1024 * 1024)).toFixed(2) + " MB";22}2324export function ConnectionStatsDisplay({25status,26hub,27}: {28status: ConatConnectionStatus;29hub?: string;30}) {31const connected = status.state === "connected";32const statusText = connected33? `Connected${hub ? " to hub " + hub : ""}`34: "Disconnected";35const statusColor = connected ? "green" : "red";3637const icon = connected ? <CheckCircleOutlined /> : <CloseCircleOutlined />;3839if (MAX_SEND_MESSAGES <= status.stats.send.messages) {40MAX_SEND_MESSAGES *= 1.2;41}42if (MAX_SEND_BYTES <= status.stats.send.bytes) {43MAX_SEND_BYTES *= 1.2;44}45if (MAX_RECV_MESSAGES <= status.stats.recv.messages) {46MAX_RECV_MESSAGES *= 1.2;47}48if (MAX_RECV_BYTES <= status.stats.recv.bytes) {49MAX_RECV_BYTES *= 1.2;50}5152if (status?.stats == null) {53return null;54}5556return (57<Space direction="vertical" size="large" style={{ width: "100%" }}>58<Typography.Title level={5}>59<Badge status={statusColor as any} text={statusText} /> {icon}60</Typography.Title>6162{!connected && !!status.reason && (63<Alert64message={capitalize(status.reason)}65type="warning"66showIcon67style={{ marginBottom: 10 }}68/>69)}7071<Descriptions bordered size="middle" column={1}>72<Descriptions.Item73label={74<>75<SendOutlined /> Messages sent76</>77}78>79<Progress80percent={Math.min(81100,82(100 * status.stats.send.messages) / MAX_SEND_MESSAGES,83)}84size="small"85status="active"86strokeColor="#1890ff"87format={() => `${status.stats.send.messages}`}88/>89</Descriptions.Item>90<Descriptions.Item91label={92<>93<DatabaseOutlined /> Bytes sent94</>95}96>97<Progress98percent={Math.min(99100,100(100 * status.stats.send.bytes) / MAX_SEND_BYTES,101)}102size="small"103status="active"104strokeColor="#40a9ff"105format={() => bytesToStr(status.stats.send.bytes)}106/>107</Descriptions.Item>108<Descriptions.Item109label={110<>111<DownloadOutlined /> Messages received112</>113}114>115<Progress116percent={Math.min(117100,118(100 * status.stats.recv.messages) / MAX_RECV_MESSAGES,119)}120size="small"121strokeColor="#52c41a"122status="active"123format={() => `${status.stats.recv.messages}`}124/>125</Descriptions.Item>126<Descriptions.Item127label={128<>129<DatabaseOutlined /> Bytes received130</>131}132>133<Progress134percent={Math.min(135100,136(100 * status.stats.recv.bytes) / MAX_RECV_BYTES,137)}138size="small"139strokeColor="#73d13d"140status="active"141format={() => bytesToStr(status.stats.recv.bytes)}142/>143</Descriptions.Item>144<Descriptions.Item145label={146<>147<UsergroupAddOutlined /> Subscriptions148</>149}150>151<Progress152percent={Math.min(153100,154(100 * status.stats.subs) / MAX_SUBSCRIPTIONS_PER_CLIENT,155)}156size="small"157strokeColor="purple"158status="active"159format={() => `${status.stats.subs}`}160/>161</Descriptions.Item>162</Descriptions>163164{/* Optionally, details debugging */}165{status.details && (166<Typography.Paragraph167copyable168code169style={{ maxHeight: 120, overflow: "auto", marginTop: 12 }}170>171{JSON.stringify(status.details, null, 2)}172</Typography.Paragraph>173)}174</Space>175);176}177178179