Skip to content

Commit

Permalink
add '/stats/nodes/lock' page
Browse files Browse the repository at this point in the history
Signed-off-by: Vallari <[email protected]>
  • Loading branch information
VallariAg committed Aug 14, 2023
1 parent ba485ea commit 85d3c45
Show file tree
Hide file tree
Showing 4 changed files with 118 additions and 4 deletions.
4 changes: 3 additions & 1 deletion src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { useState } from "react";

import { Routes, Route } from "react-router-dom";
import { Routes, Route, Navigate } from "react-router-dom";
import { Helmet } from "react-helmet";

import AppBar from "./components/AppBar";
Expand All @@ -11,6 +11,7 @@ import Job from "./pages/Job";
import Queue from "./pages/Queue";
import Nodes from "./pages/Nodes";
import Node from "./pages/Node";
import StatsNodesLock from "./pages/StatsNodesLock";

import "./App.css";

Expand Down Expand Up @@ -39,6 +40,7 @@ function App(props: AppProps) {
<Route path="/" element={<Runs />} />
<Route path="/nodes" element={<Nodes />} />
<Route path="/nodes/:name" element={<Node />} />
<Route path="/stats/nodes/lock" element={<StatsNodesLock />} />
<Route path="/runs" element={<Runs />} />
<Route path="/runs/:name" element={<Run />} />
<Route path="/runs/:name/jobs/:job_id" element={<Job />} />
Expand Down
7 changes: 7 additions & 0 deletions src/lib/paddles.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,3 +46,10 @@ export type Node = {
export type NodeJobs = {
jobs?: Job[];
}

export type StatsLocksResponse = {
id: string;
owner: string;
machine_type: string;
count: number;
}
38 changes: 35 additions & 3 deletions src/lib/paddles.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useQuery } from "@tanstack/react-query";
import type { UseQueryResult } from "@tanstack/react-query";

import type { GetURLParams, Run, Job, Node, NodeJobs } from "./paddles.d";
import type { GetURLParams, Run, Job, Node, NodeJobs, StatsLocksResponse } from "./paddles.d";

const PADDLES_SERVER =
import.meta.env.VITE_PADDLES_SERVER || "https://paddles.front.sepia.ceph.com";
Expand Down Expand Up @@ -97,8 +97,8 @@ function useMachineTypes() {
function useNodeJobs(name: string, params: GetURLParams): UseQueryResult<NodeJobs> {
// 'page' and 'count' are mandatory query params for this paddles endpoint
params = { "page": params?.page || 0, "pageSize": params?.pageSize || 25 }
const url = getURL(`/nodes/${name}/jobs`, params);
const query = useQuery(["nodes", { url }], {
const url = getURL(`/nodes/${name}/jobs/`, params);
const query = useQuery(["nodeJobs", { url }], {
select: (data: Job[]) => {
data.forEach((item) => {
item.id = item.job_id;
Expand Down Expand Up @@ -132,6 +132,37 @@ function useNodes(params: GetURLParams): UseQueryResult<Node[]> {
return query;
}

function useStatsNodeLocks(params: GetURLParams): UseQueryResult<StatsLocksResponse[]> {
const params_ = JSON.parse(JSON.stringify(params || {}));
params_["up"] = "True"

const queryString = new URLSearchParams(params_).toString();
let uri = `nodes/?${queryString}`;
const url = new URL(uri, PADDLES_SERVER).href

const query = useQuery(["statsLocks", { url }], {
select: (data: Node[]) => {
let users = new Map();
data.map((node) => {
let owner: string = node["locked"] ? (node["locked_by"] || "-") : "(free)";
let mtype: string = node["machine_type"] || "None";
let mtype_dict = users.get(owner) || new Map();
let mcount = mtype_dict.get(mtype) || 0 + 1;
mtype_dict.set(mtype, mcount);
users.set(owner, mtype_dict);
});
let resp: StatsLocksResponse[] = [];
users.forEach(((mtype_dict: Map<string, number>, owner: string) => {
mtype_dict.forEach((mcount: number, mtype: string) => {
resp.push({ id: owner + mtype, owner, machine_type: mtype, count: mcount })
})
}));
return resp;
},
});
return query;
}

function useStatuses() {
return {
data: [
Expand All @@ -156,4 +187,5 @@ export {
useNode,
useNodeJobs,
useNodes,
useStatsNodeLocks,
};
73 changes: 73 additions & 0 deletions src/pages/StatsNodesLock/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import { useQueryParams, StringParam } from "use-query-params";
import Typography from "@mui/material/Typography";
import { Helmet } from "react-helmet";
import type { GridColDef } from "@mui/x-data-grid";

import DataGrid from "../../components/DataGrid";
import FilterMenu from "../../components/FilterMenu";

import { useStatsNodeLocks } from "../../lib/paddles";
import { useMachineTypes } from "../../lib/paddles";


export const columns: GridColDef[] = [
{
field: "owner",
width: 200,
},
{
headerName: "machine type",
field: "machine_type",
width: 200,
},
{
field: "count",
width: 125,
},

]

export default function StatsNodesLock() {
const [params, setParams] = useQueryParams({
machine_type: StringParam,
});
const machine_type = params["machine_type"];
const query = useStatsNodeLocks(params);

if (query === null) return <Typography>404</Typography>;
if (query.isError) return null;

return (
<div>
<Helmet>
<title>Stats Nodes Lock - Pulpito</title>
</Helmet>
<Typography variant="h6" style={{ marginBottom: "20px" }}>
Machine usage for up {machine_type || ""} nodes
</Typography>

<div style={{ height: "auto", display: "flex" }}>
<div style={{ display: "flex", flexWrap: "wrap", marginLeft: "auto" }}>
<div>
<Typography style={{ padding: "10px" }}>
Filter&nbsp;by:
</Typography>
</div>
<FilterMenu
type="machine_type"
value={machine_type}
setter={setParams}
optionsHook={useMachineTypes}
width={150}
/>
</div>
</div>
<DataGrid
columns={columns}
rows={query.data || []}
loading={query.isLoading || query.isFetching}
hideFooter={true}
/>
</div>
);
}

0 comments on commit 85d3c45

Please sign in to comment.