Skip to content

Commit cea97a7

Browse files
committed
Better Origin metric integration on the Director
- Add Origin metric page to the director - Add click through interactions on data points to allow investigation to outlier servers
1 parent 410c157 commit cea97a7

File tree

13 files changed

+339
-170
lines changed

13 files changed

+339
-170
lines changed

web_ui/frontend/app/director/metrics/components/MetricBoxPlot.tsx

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
'use client';
22

3+
import Link from 'next/link';
34
import { Chart } from 'react-chartjs-2';
45
import {
56
CategoryScale,
@@ -19,6 +20,7 @@ import {
1920
TooltipLabelStyle,
2021
TooltipItem,
2122
} from 'chart.js';
23+
import { getRelativePosition } from 'chart.js/helpers';
2224
import { useContext, useEffect, useMemo, useState } from 'react';
2325
import {
2426
BoxAndWiskers,
@@ -43,6 +45,7 @@ import {
4345
toBytesString,
4446
} from '@/helpers/bytes';
4547
import { evaluateOrReturn, TypeOrTypeFunction } from '@/helpers/util';
48+
import { useRouter } from 'next/navigation';
4649

4750
ChartJS.register(
4851
BoxPlotController,
@@ -69,6 +72,7 @@ export const BytesMetricBoxPlot = ({
6972
title: string;
7073
options?: ChartOptions;
7174
}) => {
75+
const router = useRouter();
7276
const { rate, time, resolution, range } = useContext(GraphContext);
7377

7478
const { data } = useSWR(
@@ -118,6 +122,22 @@ export const BytesMetricBoxPlot = ({
118122
type: 'logarithmic',
119123
},
120124
},
125+
onClick: function (evt: any, item: any) {
126+
if (item.length === 0) {
127+
return;
128+
}
129+
const position = getRelativePosition(evt, evt.Chart) as any; // Typing is wrong
130+
try {
131+
const serverName =
132+
position.chart.tooltip.body[0].lines[0].split(':')[0];
133+
if (serverName != 'Missing Server Name') {
134+
router.push(
135+
'/director/metrics/origin/?server_name=' +
136+
position.chart.tooltip.body[0].lines[0].split(':')[0]
137+
);
138+
}
139+
} catch {}
140+
},
121141
plugins: {
122142
tooltip: {
123143
callbacks: {
@@ -153,6 +173,7 @@ export const MetricBoxPlot = ({
153173
title: string;
154174
options?: ChartOptions;
155175
}) => {
176+
const router = useRouter();
156177
const { rate, time, resolution, range } = useContext(GraphContext);
157178

158179
const { data } = useSWR(
@@ -187,6 +208,22 @@ export const MetricBoxPlot = ({
187208
type: 'logarithmic',
188209
},
189210
},
211+
onClick: function (evt: any, item: any) {
212+
if (item.length === 0) {
213+
return;
214+
}
215+
const position = getRelativePosition(evt, evt.Chart) as any; // Typing is broken here for the Chartjs library
216+
try {
217+
const serverName =
218+
position.chart.tooltip.body[0].lines[0].split(':')[0];
219+
if (serverName != 'Missing Server Name') {
220+
router.push(
221+
'/director/metrics/origin/?server_name=' +
222+
position.chart.tooltip.body[0].lines[0].split(':')[0]
223+
);
224+
}
225+
} catch {}
226+
},
190227
plugins: {
191228
tooltip: {
192229
callbacks: {

web_ui/frontend/app/director/metrics/components/StorageTable.tsx

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
'use client';
22

3+
import Link from 'next/link';
34
import {
45
Box,
56
Table,
@@ -86,7 +87,13 @@ export const StorageTable = () => {
8687
)
8788
.map((d) => (
8889
<TableRow key={d.serverName}>
89-
<TableCell>{d.serverName}</TableCell>
90+
<TableCell>
91+
<Link
92+
href={`/director/metrics/origin/?server_name=${d.serverName}`}
93+
>
94+
{d.serverName}
95+
</Link>
96+
</TableCell>
9097
<TableCell
9198
sx={{
9299
bgcolor: chroma

web_ui/frontend/app/director/metrics/components/TransferBarGraph.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ const TransferBarGraph = () => {
5555

5656
const { data } = useSWR<ChartDataset<any, any>>(
5757
[
58-
'transferRateGraph',
58+
'transferBarGraph',
5959
graphContext.rate,
6060
graphContext.range,
6161
graphContext.resolution,
@@ -73,6 +73,8 @@ const TransferBarGraph = () => {
7373
}
7474
);
7575

76+
console.log(data);
77+
7678
return (
7779
<Bar
7880
data={data}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
'use client';
2+
3+
import OriginMetricPage from '@/components/graphs/OriginMetricPage';
4+
import { Suspense, useState, useEffect } from 'react';
5+
import { Skeleton } from '@mui/material';
6+
import { useSearchParams } from 'next/navigation';
7+
8+
const RemoteOriginPage = () => {
9+
const params = useSearchParams();
10+
const serverName = params.get('server_name') || undefined;
11+
12+
return <OriginMetricPage server_name={serverName} />;
13+
};
14+
15+
const Page = () => {
16+
return (
17+
<Suspense fallback={<Skeleton />}>
18+
<RemoteOriginPage />
19+
</Suspense>
20+
);
21+
};
22+
23+
export default Page;

web_ui/frontend/app/origin/metrics/components/CPUGraph.tsx

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import {
2323
GraphDispatchContext,
2424
} from '@/components/graphs/GraphContext';
2525
import {
26+
buildMetric,
2627
MatrixResponseData,
2728
query_raw,
2829
TimeDuration,
@@ -45,19 +46,21 @@ ChartJS.register(
4546
Filler
4647
);
4748

48-
const CPUGraph = () => {
49+
const CPUGraph = ({ server_name = undefined }: { server_name?: string }) => {
4950
const graphContext = useContext(GraphContext);
5051

5152
const { data: datasets } = useSWR<ChartDataset<any, any>>(
5253
[
5354
'cpuGraph',
55+
server_name,
5456
graphContext.rate,
5557
graphContext.range,
5658
graphContext.resolution,
5759
graphContext.time,
5860
],
5961
() =>
6062
getData(
63+
server_name,
6164
graphContext.rate,
6265
graphContext.range,
6366
graphContext.resolution,
@@ -114,12 +117,14 @@ const CPUGraph = () => {
114117
};
115118

116119
const getData = async (
120+
server_name: string | undefined,
117121
rate: TimeDuration,
118122
range: TimeDuration,
119123
resolution: TimeDuration,
120124
time: DateTime
121125
): Promise<ChartDataset<any, any>> => {
122-
const query = `avg by (instance) (irate(process_cpu_seconds_total[${rate}]))[${range}:${resolution}]`;
126+
const metric = buildMetric('process_cpu_seconds_total', { server_name });
127+
const query = `avg by (instance) (irate(${metric}[${rate}]))[${range}:${resolution}]`;
123128
const dataResponse = await query_raw<MatrixResponseData>(
124129
query,
125130
time.toSeconds()

web_ui/frontend/app/origin/metrics/components/MemoryGraph.tsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import {
2222
GraphDispatchContext,
2323
} from '@/components/graphs/GraphContext';
2424
import {
25+
buildMetric,
2526
MatrixResponseData,
2627
query_raw,
2728
TimeDuration,
@@ -43,7 +44,7 @@ ChartJS.register(
4344
Colors
4445
);
4546

46-
const MemoryGraph = () => {
47+
const MemoryGraph = ({ server_name }: { server_name?: string }) => {
4748
const graphContext = useContext(GraphContext);
4849

4950
const { data: datasets } = useSWR<ChartDataset<any, any>>(
@@ -56,6 +57,7 @@ const MemoryGraph = () => {
5657
],
5758
() =>
5859
getData(
60+
buildMetric('go_memstats_alloc_bytes', { server_name }),
5961
graphContext.rate,
6062
graphContext.range,
6163
graphContext.resolution,
@@ -112,12 +114,13 @@ const MemoryGraph = () => {
112114
};
113115

114116
const getData = async (
117+
metric: string,
115118
rate: TimeDuration,
116119
range: TimeDuration,
117120
resolution: TimeDuration,
118121
time: DateTime
119122
): Promise<ChartDataset<any, any>> => {
120-
const query = `(go_memstats_alloc_bytes / 1024 / 1024)[${range}:${resolution}]`;
123+
const query = `(${metric} / 1024 / 1024)[${range}:${resolution}]`;
121124
const dataResponse = await query_raw<MatrixResponseData>(
122125
query,
123126
time.toSeconds()

web_ui/frontend/app/origin/metrics/components/ProjectsTable.tsx

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import {
1010
TableRow,
1111
} from '@mui/material';
1212
import {
13+
buildMetric,
1314
MatrixResponseData,
1415
query_raw,
1516
TimeDuration,
@@ -27,12 +28,16 @@ interface ProjectData {
2728
bytesAccessed: string;
2829
}
2930

30-
export const ProjectTable = () => {
31+
export const ProjectTable = ({
32+
server_name = undefined,
33+
}: {
34+
server_name?: string;
35+
}) => {
3136
const { rate, time, range, resolution } = useContext(GraphContext);
3237

3338
const { data: projectData, error: projectError } = useSWR(
3439
['projectData', time, range],
35-
() => getProjectData(range, time)
40+
() => getProjectData(server_name, range, time)
3641
);
3742

3843
return (
@@ -66,11 +71,18 @@ export const ProjectTable = () => {
6671
};
6772

6873
const getProjectData = async (
74+
server_name: string | undefined,
6975
range: TimeDuration,
7076
time: DateTime
7177
): Promise<ProjectData[]> => {
78+
const metric = buildMetric('xrootd_transfer_bytes', {
79+
type: { comparator: '!=', value: 'value' },
80+
proj: { comparator: '!=', value: '' },
81+
server_name,
82+
});
83+
7284
const queryResponse = await query_raw<VectorResponseData>(
73-
`sum by (proj) (increase(xrootd_transfer_bytes{type!="write", proj!=""}[${range}]))`,
85+
`sum by (proj) (increase(${metric}[${range}]))`,
7486
time.toSeconds()
7587
);
7688
const result = queryResponse.data.result;

web_ui/frontend/app/origin/metrics/components/StorageGraph.tsx

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import { grey, blue } from '@mui/material/colors';
1515

1616
import { GraphContext } from '@/components/graphs/GraphContext';
1717
import {
18+
buildMetric,
1819
MatrixResponseData,
1920
query_raw,
2021
TimeDuration,
@@ -31,12 +32,16 @@ interface storageData {
3132
free: number;
3233
}
3334

34-
const StorageGraph = () => {
35+
const StorageGraph = ({
36+
server_name = undefined,
37+
}: {
38+
server_name?: string;
39+
}) => {
3540
const graphContext = useContext(GraphContext);
3641

3742
const { data } = useSWR<storageData>(
38-
['getStorageData', graphContext.time],
39-
() => getStorageData(graphContext.time.toSeconds())
43+
['getStorageData', graphContext.time, server_name],
44+
() => getStorageData(server_name, graphContext.time.toSeconds())
4045
);
4146

4247
const [usedBytes, freeBytes] = convertListBytes([
@@ -74,9 +79,14 @@ const StorageGraph = () => {
7479
};
7580

7681
const getStorageData = async (
82+
server_name: string | undefined,
7783
time: number = DateTime.now().toSeconds()
7884
): Promise<{ free: number; used: number }> => {
79-
const url = `sum by (type) (xrootd_storage_volume_bytes{server_type="origin"})`;
85+
const metric = buildMetric('xrootd_storage_volume_bytes', {
86+
server_type: 'origin',
87+
server_name,
88+
});
89+
const url = `sum by (type) (${metric})`;
8090
const response = await query_raw<VectorResponseData>(url, time);
8191

8292
const result = response.data.result;

web_ui/frontend/app/origin/metrics/components/TransferRateGraph.tsx

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import {
2424
GraphDispatchContext,
2525
} from '@/components/graphs/GraphContext';
2626
import {
27+
buildMetric,
2728
MatrixResponseData,
2829
query_raw,
2930
TimeDuration,
@@ -46,7 +47,11 @@ ChartJS.register(
4647
Colors
4748
);
4849

49-
const TransferRateGraph = () => {
50+
const TransferRateGraph = ({
51+
server_name = undefined,
52+
}: {
53+
server_name?: string;
54+
}) => {
5055
const graphContext = useContext(GraphContext);
5156
const dispatch = useContext(GraphDispatchContext);
5257

@@ -62,6 +67,7 @@ const TransferRateGraph = () => {
6267
],
6368
() =>
6469
getData(
70+
server_name,
6571
graphContext.rate,
6672
graphContext.range,
6773
graphContext.resolution,
@@ -174,12 +180,16 @@ const toBytesDataset = (
174180
};
175181

176182
const getData = async (
183+
server_name: string | undefined,
177184
rate: TimeDuration,
178185
range: TimeDuration,
179186
resolution: TimeDuration,
180187
time: DateTime
181188
): Promise<ChartDataset<'line', { x: number; y: number }[]>[]> => {
182-
const query = `sum by (path, type) (rate(xrootd_transfer_bytes[${rate}]))[${range}:${resolution}]`;
189+
const metric = buildMetric('xrootd_transfer_bytes', {
190+
server_name: server_name,
191+
});
192+
const query = `sum by (path, type) (rate(${metric}[${rate}]))[${range}:${resolution}]`;
183193
const dataResponse = await query_raw<MatrixResponseData>(
184194
query,
185195
time.toSeconds()

0 commit comments

Comments
 (0)