feat: machines logs viewer

This commit is contained in:
BennyKok
2023-12-22 00:24:12 +08:00
parent 9cc3c6ffe3
commit 2690db12b5
5 changed files with 181 additions and 15 deletions
+88 -5
View File
@@ -1,9 +1,17 @@
"use client";
import { Badge } from "@/components/ui/badge";
import {
Dialog,
DialogContent,
DialogDescription,
DialogHeader,
DialogTitle,
DialogTrigger,
} from "@/components/ui/dialog";
import type { getMachines } from "@/server/curdMachine";
import { Check, CircleOff, SatelliteDish } from "lucide-react";
import React, { useEffect } from "react";
import React, { useEffect, useRef, useState } from "react";
import useWebSocket, { ReadyState } from "react-use-websocket";
import { create } from "zustand";
@@ -16,6 +24,12 @@ type State = {
data: any;
};
}[];
logs: {
machine_id: string;
logs: string;
timestamp: number;
}[];
addLogs: (id: string, logs: string) => void;
addData: (
id: string,
json: {
@@ -27,6 +41,13 @@ type State = {
export const useStore = create<State>((set) => ({
data: [],
logs: [],
addLogs(id, logs) {
set((state) => ({
...state,
logs: [...state.logs, { machine_id: id, logs, timestamp: Date.now() }],
}));
},
addData: (id, json) =>
set((state) => ({
...state,
@@ -54,7 +75,14 @@ function MachineWS({
}: {
machine: Awaited<ReturnType<typeof getMachines>>[0];
}) {
const { addData } = useStore();
const { addData, addLogs } = useStore();
const logs = useStore((x) =>
x.logs
.filter((p) => p.machine_id === machine.id)
.sort((a, b) => a.timestamp - b.timestamp)
);
const [sid, setSid] = useState("");
const wsEndpoint = machine.endpoint.replace(/^http/, "ws");
const { lastMessage, readyState } = useWebSocket(
`${wsEndpoint}/comfyui-deploy/ws`,
@@ -62,6 +90,9 @@ function MachineWS({
shouldReconnect: () => true,
reconnectAttempts: 20,
reconnectInterval: 1000,
// queryParams: {
// clientId: sid,
// },
}
);
@@ -75,20 +106,72 @@ function MachineWS({
[ReadyState.UNINSTANTIATED]: "Uninstantiated",
}[readyState];
const container = useRef<HTMLDivElement | null>(null);
useEffect(() => {
if (!lastMessage?.data) return;
const message = JSON.parse(lastMessage.data);
console.log(message.event, message);
if (message.data.sid) {
setSid(message.data.sid);
}
if (message.data?.prompt_id) {
addData(message.data.prompt_id, message);
}
if (message.event === "LOGS") {
addLogs(machine.id, message.data);
}
}, [lastMessage]);
useEffect(() => {
// console.log(logs.length, container.current);
if (container.current) {
const scrollHeight = container.current.scrollHeight;
container.current.scrollTo({
top: scrollHeight,
behavior: "smooth",
});
}
}, [logs.length]);
return (
<Badge className="text-sm flex gap-2 font-normal" variant="outline">
{machine.name} {connectionStatus}
</Badge>
<Dialog>
<DialogTrigger asChild className="">
<Badge className="text-sm flex gap-2 font-normal" variant="outline">
{machine.name} {connectionStatus}
</Badge>
</DialogTrigger>
<DialogContent className="max-w-3xl max-h-full">
<DialogHeader>
<DialogTitle>Machine Logs</DialogTitle>
<DialogDescription>
You can view your run&apos;s outputs here
</DialogDescription>
</DialogHeader>
<div
ref={(ref) => {
if (!container.current && ref) {
const scrollHeight = ref.scrollHeight;
ref.scrollTo({
top: scrollHeight,
behavior: "instant",
});
}
container.current = ref;
}}
className="flex flex-col text-xs p-2 overflow-y-scroll max-h-[400px] whitespace-break-spaces"
>
{logs.map((x, i) => (
<div key={i}>{x.logs}</div>
))}
</div>
</DialogContent>
</Dialog>
);
}
+3 -7
View File
@@ -1,6 +1,5 @@
import { RunInputs } from "@/components/RunInputs";
import { LiveStatus } from "./LiveStatus";
import { RunInputs } from "@/components/RunInputs";
import { RunOutputs } from "@/components/RunOutputs";
import {
Dialog,
@@ -22,10 +21,7 @@ export async function RunDisplay({
}) {
return (
<Dialog>
<DialogTrigger
asChild
className="appearance-none hover:cursor-pointer"
>
<DialogTrigger asChild className="appearance-none hover:cursor-pointer">
<TableRow>
<TableCell>{run.number}</TableCell>
<TableCell className="font-medium">{run.machine?.name}</TableCell>
@@ -42,7 +38,7 @@ export async function RunDisplay({
</DialogDescription>
</DialogHeader>
<div className="max-h-96 overflow-y-scroll">
<RunInputs run={run}/>
<RunInputs run={run} />
<Suspense>
<RunOutputs run_id={run.id} />
</Suspense>
+1 -1
View File
@@ -39,7 +39,7 @@ export async function RunsTable(props: { workflow_id: string }) {
export async function DeploymentsTable(props: { workflow_id: string }) {
const allRuns = await findAllDeployments(props.workflow_id);
return (
<div className="overflow-auto h-fit lg:h-[400px] w-full">
<div className="overflow-auto h-fit w-full">
<Table className="">
<TableCaption>A list of your deployments</TableCaption>
<TableHeader className="bg-background top-0 sticky">