63 lines
1.6 KiB
TypeScript
63 lines
1.6 KiB
TypeScript
import { Alert, AlertDescription } from "@/components/ui/alert";
|
|
import { Skeleton } from "@/components/ui/skeleton";
|
|
import { SectionCard } from "../components/SectionCard";
|
|
import { useWidgetData } from "../hooks/useWidgets";
|
|
import type { WidgetInstance } from "../types";
|
|
|
|
interface Props {
|
|
widget: WidgetInstance;
|
|
refreshIntervalMs: number;
|
|
description?: string;
|
|
}
|
|
|
|
type PromQLResult = {
|
|
resultType?: string;
|
|
result?: unknown;
|
|
};
|
|
|
|
type PromQLVectorSample = {
|
|
metric?: Record<string, string>;
|
|
value?: [number, string];
|
|
};
|
|
|
|
function formatPrometheusValue(result: PromQLResult | undefined): string {
|
|
if (!result) return "No data";
|
|
if (result.resultType === "scalar" && Array.isArray(result.result)) {
|
|
return String(result.result[1] ?? "No data");
|
|
}
|
|
if (
|
|
result.resultType === "vector" &&
|
|
Array.isArray(result.result) &&
|
|
result.result.length > 0
|
|
) {
|
|
const first = result.result[0] as PromQLVectorSample;
|
|
if (first.value) return String(first.value[1]);
|
|
}
|
|
return JSON.stringify(result, null, 2);
|
|
}
|
|
|
|
export function PrometheusMetricWidget({
|
|
widget,
|
|
refreshIntervalMs,
|
|
description,
|
|
}: Props) {
|
|
const { data, isLoading } = useWidgetData(widget.id, refreshIntervalMs);
|
|
const result = data?.data?.result as PromQLResult | undefined;
|
|
|
|
return (
|
|
<SectionCard title={widget.title} description={description}>
|
|
{isLoading && !data ? (
|
|
<Skeleton className="h-10 w-32" />
|
|
) : data?.error ? (
|
|
<Alert variant="destructive">
|
|
<AlertDescription>{data.error}</AlertDescription>
|
|
</Alert>
|
|
) : (
|
|
<pre className="whitespace-pre-wrap text-sm">
|
|
{formatPrometheusValue(result)}
|
|
</pre>
|
|
)}
|
|
</SectionCard>
|
|
);
|
|
}
|