mirror of
https://github.com/hibiken/asynqmon.git
synced 2025-09-21 22:36:33 +08:00
(ui): Add QueueSizeMetricsChart component
This commit is contained in:
@@ -23,7 +23,7 @@ func newGetMetricsHandlerFunc(client *http.Client) http.HandlerFunc {
|
||||
const (
|
||||
baseAddr = "http://localhost:9090"
|
||||
apiPath = "/api/v1/query_range"
|
||||
promQL = "asynq_tasks_enqueued_total"
|
||||
promQL = "asynq_queue_size"
|
||||
)
|
||||
var b strings.Builder
|
||||
v := url.Values{}
|
||||
|
@@ -32,7 +32,6 @@ export function getMetricsAsync() {
|
||||
dispatch({ type: GET_METRICS_BEGIN });
|
||||
try {
|
||||
const response = await getMetrics();
|
||||
console.log("DEBUG: got metrics: ", response);
|
||||
dispatch({ type: GET_METRICS_SUCCESS, payload: response });
|
||||
} catch (error) {
|
||||
console.error(`getMetricsAsync: ${toErrorStringWithHttpStatus(error)}`);
|
||||
|
@@ -86,7 +86,7 @@ export interface MetricsResult {
|
||||
|
||||
export interface Metrics {
|
||||
metric: MetricsInfo;
|
||||
values: [number, string]; // [unixtime, value]
|
||||
values: [number, string][]; // [unixtime, value]
|
||||
}
|
||||
|
||||
export interface MetricsInfo {
|
||||
|
84
ui/src/components/QueueSizeMetricsChart.tsx
Normal file
84
ui/src/components/QueueSizeMetricsChart.tsx
Normal file
@@ -0,0 +1,84 @@
|
||||
import React from "react";
|
||||
import {
|
||||
LineChart,
|
||||
Line,
|
||||
XAxis,
|
||||
YAxis,
|
||||
CartesianGrid,
|
||||
Tooltip,
|
||||
Legend,
|
||||
ResponsiveContainer,
|
||||
} from "recharts";
|
||||
import { Metrics } from "../api";
|
||||
|
||||
interface Props {
|
||||
data: Metrics[];
|
||||
}
|
||||
|
||||
// interface that rechart understands.
|
||||
interface ChartData {
|
||||
timestamp: number;
|
||||
[qname: string]: number;
|
||||
}
|
||||
|
||||
function toChartData(metrics: Metrics[]): ChartData[] {
|
||||
if (metrics.length === 0) {
|
||||
return [];
|
||||
}
|
||||
let byTimestamp: { [key: number]: ChartData } = {};
|
||||
for (let x of metrics) {
|
||||
for (let [ts, val] of x.values) {
|
||||
if (!byTimestamp[ts]) {
|
||||
byTimestamp[ts] = { timestamp: ts };
|
||||
}
|
||||
byTimestamp[ts][x.metric.queue] = parseFloat(val);
|
||||
}
|
||||
}
|
||||
return Object.values(byTimestamp);
|
||||
}
|
||||
|
||||
const lineColors = [
|
||||
"#2085ec",
|
||||
"#72b4eb",
|
||||
"#0a417a",
|
||||
"#8464a0",
|
||||
"#cea9bc",
|
||||
"#323232",
|
||||
];
|
||||
|
||||
function QueueSizeMetricsChart(props: Props) {
|
||||
console.log("DEBUG: QueueSizeMetricsChart props:", props);
|
||||
console.log("DEBUG: chartData", toChartData(props.data));
|
||||
const data = toChartData(props.data);
|
||||
const keys = props.data.map((x) => x.metric.queue);
|
||||
return (
|
||||
<ResponsiveContainer maxHeight={260}>
|
||||
<LineChart data={data}>
|
||||
<CartesianGrid strokeDasharray="3 3" />
|
||||
<XAxis
|
||||
minTickGap={10}
|
||||
dataKey="timestamp"
|
||||
tickFormatter={(timestamp: number) =>
|
||||
new Date(timestamp * 1000).toLocaleTimeString()
|
||||
}
|
||||
/>
|
||||
<YAxis />
|
||||
<Tooltip
|
||||
labelFormatter={(timestamp: number) => {
|
||||
return new Date(timestamp * 1000).toLocaleTimeString();
|
||||
}}
|
||||
/>
|
||||
<Legend />
|
||||
{keys.map((key, idx) => (
|
||||
<Line
|
||||
type="monotone"
|
||||
dataKey={key}
|
||||
stroke={lineColors[idx % lineColors.length]}
|
||||
/>
|
||||
))}
|
||||
</LineChart>
|
||||
</ResponsiveContainer>
|
||||
);
|
||||
}
|
||||
|
||||
export default QueueSizeMetricsChart;
|
@@ -1,4 +1,4 @@
|
||||
import React, { useEffect } from "react";
|
||||
import React from "react";
|
||||
import { connect, ConnectedProps } from "react-redux";
|
||||
import { makeStyles } from "@material-ui/core/styles";
|
||||
import Container from "@material-ui/core/Container";
|
||||
@@ -6,6 +6,8 @@ import Grid from "@material-ui/core/Grid";
|
||||
import { getMetricsAsync } from "../actions/metricsActions";
|
||||
import { AppState } from "../store";
|
||||
import { usePolling } from "../hooks";
|
||||
import Typography from "@material-ui/core/Typography";
|
||||
import QueueSizeMetricsChart from "../components/QueueSizeMetricsChart";
|
||||
|
||||
const useStyles = makeStyles((theme) => ({
|
||||
container: {
|
||||
@@ -28,7 +30,7 @@ type Props = ConnectedProps<typeof connector>;
|
||||
|
||||
function MetricsView(props: Props) {
|
||||
const classes = useStyles();
|
||||
const { pollInterval, getMetricsAsync } = props;
|
||||
const { pollInterval, getMetricsAsync, data } = props;
|
||||
|
||||
usePolling(getMetricsAsync, pollInterval);
|
||||
|
||||
@@ -36,9 +38,14 @@ function MetricsView(props: Props) {
|
||||
<Container maxWidth="lg" className={classes.container}>
|
||||
<Grid container spacing={3}>
|
||||
<Grid item xs={12}>
|
||||
Hello Metrics
|
||||
<Typography>Queue Size</Typography>
|
||||
<QueueSizeMetricsChart data={data?.data.result || []} />
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Grid item xs={12}>
|
||||
<Typography>Queue Latency</Typography>
|
||||
<div>TODO: Queue latency chart here</div>
|
||||
</Grid>
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
|
Reference in New Issue
Block a user