Skip to content

Commit

Permalink
feat(resource-catalog): add queue metrics component
Browse files Browse the repository at this point in the history
  • Loading branch information
yomatters committed Jul 12, 2024
1 parent 2e8f0e6 commit 6f4da60
Show file tree
Hide file tree
Showing 9 changed files with 184 additions and 2 deletions.
20 changes: 19 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@
"@glidejs/glide": "^3.6.1",
"fuse.js": "^7.0.0",
"preact": "^10.13.1",
"preact-iso": "^2.6.3"
"preact-iso": "^2.6.3",
"tippy.js": "^6.3.7"
},
"devDependencies": {
"@preact/preset-vite": "^2.5.0",
Expand Down
31 changes: 31 additions & 0 deletions public/api/resource-groups/1/queue-metrics.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
{
"queueMetrics": [
{
"resourceId": 1,
"name": "Bridges-2 Regular Memory",
"resourceRepositoryKey": 2900,
"waitTime": 5.909166,
"wallTime": 2.007403,
"expansionFactor": 5.3611,
"order": 1
},
{
"resourceId": 2,
"name": "Bridges-2 Extreme Memory",
"resourceRepositoryKey": 2903,
"waitTime": 5.233983,
"wallTime": 6.61043,
"expansionFactor": 1.7911,
"order": 2
},
{
"resourceId": 3,
"name": "Bridges-2 GPU",
"resourceRepositoryKey": 2902,
"waitTime": 19.670669,
"wallTime": 2.072165,
"expansionFactor": 10.4929,
"order": 3
}
]
}
1 change: 1 addition & 0 deletions src/footer.css
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ a.linkedin {
text-indent: -999999px;
transition: opacity 0.25s ease-out;
width: 40px;
z-index: 100;
}
.scroll-to-top.visible {
opacity: 1;
Expand Down
26 changes: 26 additions & 0 deletions src/info-tip.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
.info-tip {
background-color: transparent;
border: 0 none transparent;
}
.tippy-box[data-theme~="access"] {
background-color: var(--teal-700);
border-radius: 0;
color: white;
font-weight: 400;
padding: 5px;
}
.tippy-box[data-theme~="access"][data-placement^="top"] > .tippy-arrow::before {
border-top-color: var(--teal-700);
}
.tippy-box[data-theme~="access"][data-placement^="bottom"]
> .tippy-arrow::before {
border-bottom-color: var(--teal-700);
}
.tippy-box[data-theme~="access"][data-placement^="left"]
> .tippy-arrow::before {
border-left-color: var(--teal-700);
}
.tippy-box[data-theme~="access"][data-placement^="right"]
> .tippy-arrow::before {
border-right-color: var(--teal-700);
}
22 changes: 22 additions & 0 deletions src/info-tip.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { useLayoutEffect, useRef } from "preact/hooks";
import tippy from "tippy.js";

import Icon from "./icon";

export default function InfoTip({
color = "var(--contrast-6)",
icon = "info-circle-fill",
tooltip,
}) {
const trigger = useRef(null);
useLayoutEffect(() => {
if (trigger.current)
tippy(trigger.current, { content: tooltip, theme: "access" });
}, [trigger.current]);

return (
<button class="info-tip" style={{ color }} ref={trigger}>
<Icon name={icon} />
</button>
);
}
4 changes: 4 additions & 0 deletions src/resource-catalog.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import baseStyle from "./base.css?inline";
import componentsStyle from "./components.css?inline";
import contentStyle from "./content.css?inline";
import iconStyle from "./icon.css?inline";
import infoTipStyle from "./info-tip.css?inline";
import glideCoreStyle from "@glidejs/glide/dist/css/glide.core.min.css?inline";
import glideThemeStyle from "@glidejs/glide/dist/css/glide.theme.min.css?inline";
import gridStyle from "./grid.css?inline";
Expand All @@ -12,6 +13,7 @@ import resourceFiltersStyle from "./resource-filters.css?inline";
import resourceGroupStyle from "./resource-group.css?inline";
import searchStyle from "./search.css?inline";
import tagsStyle from "./tags.css?inline";
import tippyStyle from "tippy.js/dist/tippy.css?inline";

const ResourceGroupDetail = lazy(() => import("./resource-group-detail.jsx"));
const ResourceHome = lazy(() => import("./resource-home.jsx"));
Expand Down Expand Up @@ -48,6 +50,7 @@ export function ResourceCatalog({
<style>{componentsStyle}</style>
<style>{accordionStyle}</style>
<style>{iconStyle}</style>
<style>{infoTipStyle}</style>
<style>{glideCoreStyle}</style>
<style>{glideThemeStyle}</style>
<style>{gridStyle}</style>
Expand All @@ -56,6 +59,7 @@ export function ResourceCatalog({
<style>{resourceGroupStyle}</style>
<style>{searchStyle}</style>
<style>{tagsStyle}</style>
<style>{tippyStyle}</style>
</>
);
}
5 changes: 5 additions & 0 deletions src/resource-group-detail.jsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import ResourceGroupDescription from "./resource-group-description";
import ResourceGroupQueueMetrics from "./resource-group-queue-metrics";
import ResourceGroupResources from "./resource-group-resources";
import ResourceGroupSoftware from "./resource-group-software";

Expand All @@ -17,6 +18,10 @@ export default function ResourceGroupDetail({ baseUri, resourceGroupId }) {
baseUri={baseUri}
resourceGroupId={resourceGroupId}
/>
<ResourceGroupQueueMetrics
baseUri={baseUri}
resourceGroupId={resourceGroupId}
/>
</div>
);
}
74 changes: 74 additions & 0 deletions src/resource-group-queue-metrics.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import { useJSON } from "./utils";

import Grid from "./grid";
import Icon from "./icon";
import InfoTip from "./info-tip";

const formatTime = (value) => {
const hours = Math.floor(value);
const minutes = Math.floor((value - hours) * 60);
const seconds = Math.round((value - hours) * 3600 - minutes * 60);
return [hours, minutes, seconds]
.map((value) => value.toString().padStart(2, "0"))
.join(":");
};

const formatHeaderTip = (content) => (value) => {
return (
<>
<span>{value}</span> <InfoTip tooltip={content} />
</>
);
};

export default function ResourceGroupQueueMetrics({
baseUri,
resourceGroupId,
}) {
const data = useJSON(
`${baseUri}/api/resource-groups/${resourceGroupId}/queue-metrics.json`,
null
);
if (!data || data.error) return;

const columns = [
{
key: "name",
name: "Resource",
},
{
key: "waitTime",
name: "Wait Time",
format: formatTime,
formatHeader: formatHeaderTip(
"Wait time is the average time a job spends waiting in the queue before running on a resource."
),
},
{
key: "wallTime",
name: "Wall Time",
format: formatTime,
formatHeader: formatHeaderTip(
"Wall time is the average time a job spends running on a resource."
),
},
{
key: "expansionFactor",
name: "Expansion Factor",
format: (value) => value.toFixed(2),
formatHeader: formatHeaderTip(
'Expansion factor is the ratio of the total time (wait time and wall time) to the wall time. It measures how much waiting in the queue "expands" the total time taken to complete a job relative to its length.'
),
},
];

return (
<>
<h2>
<Icon name="clock" />
Queue Metrics
</h2>
<Grid columns={columns} rows={data.queueMetrics} />
</>
);
}

0 comments on commit 6f4da60

Please sign in to comment.