Initial curated ServiceMap source from 7a0a61232d05ba9097432abef6f7f4102a64d0b8
This commit is contained in:
commit
105251b9c8
96 files changed
+23587
No files matched your search
@@ -0,0 +1,117 @@
|
||||
import { Handle, Position, type Node, type NodeProps } from "@xyflow/react";
|
||||
|
||||
import type {
|
||||
ComponentRole,
|
||||
Criticality,
|
||||
HealthStatus,
|
||||
ServiceKind,
|
||||
} from "../api";
|
||||
|
||||
export type ServiceNodeData = {
|
||||
name: string;
|
||||
status: HealthStatus;
|
||||
kind: ServiceKind;
|
||||
latency: number | null;
|
||||
dependencyCount: number;
|
||||
rootCause: boolean;
|
||||
impacted: boolean;
|
||||
group: string | null;
|
||||
criticality: Criticality;
|
||||
flapping: boolean;
|
||||
category: string;
|
||||
application?: string;
|
||||
applicationNode?: boolean;
|
||||
memberIds?: string[];
|
||||
nodeKind?: "domain" | "application" | "component";
|
||||
role?: ComponentRole;
|
||||
roles?: ComponentRole[];
|
||||
explanation?: string;
|
||||
monitoredComponents?: number;
|
||||
unmonitoredComponents?: number;
|
||||
domainId?: string;
|
||||
};
|
||||
|
||||
export type ServiceNode = Node<ServiceNodeData, "service">;
|
||||
|
||||
const statusLabel = (status: HealthStatus) =>
|
||||
status === "unmonitored"
|
||||
? "Not monitored"
|
||||
: status[0].toUpperCase() + status.slice(1);
|
||||
const statusIcon = (status: HealthStatus) =>
|
||||
({
|
||||
healthy: "✓",
|
||||
degraded: "△",
|
||||
down: "!",
|
||||
recovering: "↻",
|
||||
maintenance: "Ⅱ",
|
||||
unknown: "?",
|
||||
unmonitored: "○",
|
||||
})[status];
|
||||
|
||||
export function ServiceNodeView({ data }: NodeProps<ServiceNode>) {
|
||||
const targetLabel =
|
||||
data.nodeKind === "domain"
|
||||
? `${data.memberIds?.length ?? 0} components`
|
||||
: data.applicationNode
|
||||
? `${data.monitoredComponents ?? 0} resolved · ${data.unmonitoredComponents ?? 0} unresolved`
|
||||
: data.latency != null
|
||||
? `${data.latency} ms · ${data.kind.toUpperCase()}`
|
||||
: data.kind.toUpperCase();
|
||||
return (
|
||||
<>
|
||||
<Handle type="target" position={Position.Left} />
|
||||
<div
|
||||
className={`service-node-body status-${data.status}`}
|
||||
aria-label={`${data.name}, ${statusLabel(data.status)}${data.rootCause ? ", likely root cause" : ""}`}
|
||||
>
|
||||
<div className="node-badges">
|
||||
{data.rootCause && (
|
||||
<span className="node-badge root-cause-badge">ROOT CAUSE</span>
|
||||
)}
|
||||
{!data.rootCause && data.impacted && (
|
||||
<span className="node-badge impacted-badge">IMPACTED</span>
|
||||
)}
|
||||
{data.flapping && (
|
||||
<span className="node-badge flap-badge">FLAPPING</span>
|
||||
)}
|
||||
</div>
|
||||
{data.nodeKind === "domain" && (
|
||||
<span className="node-kicker">
|
||||
DOMAIN · {data.memberIds?.length ?? 0} components
|
||||
</span>
|
||||
)}
|
||||
{data.applicationNode && (
|
||||
<span className="node-kicker">
|
||||
APPLICATION · {data.memberIds?.length ?? 0} components
|
||||
</span>
|
||||
)}
|
||||
{data.applicationNode && data.roles?.length ? (
|
||||
<span
|
||||
className="app-micro-topology"
|
||||
aria-label={`Component roles: ${data.roles.join(", ")}`}
|
||||
>
|
||||
{data.roles.slice(0, 5).map((role) => (
|
||||
<i key={role} className={`role-${role}`}>
|
||||
{role.slice(0, 1).toUpperCase()}
|
||||
</i>
|
||||
))}
|
||||
</span>
|
||||
) : null}
|
||||
{data.nodeKind === "component" && (
|
||||
<span className="node-kicker">{data.role ?? data.category}</span>
|
||||
)}
|
||||
<strong>{data.name}</strong>
|
||||
<span className={`node-status status-${data.status}`}>
|
||||
<i aria-hidden="true">{statusIcon(data.status)}</i>{" "}
|
||||
{statusLabel(data.status)}
|
||||
</span>
|
||||
<small>{targetLabel} · {data.criticality}</small>
|
||||
<small>
|
||||
{data.explanation ??
|
||||
`${data.category.replace("_", " ")} · ${data.dependencyCount} ${data.dependencyCount === 1 ? "dependency" : "dependencies"}`}
|
||||
</small>
|
||||
</div>
|
||||
<Handle type="source" position={Position.Right} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user