(ui): Add QueueSizeMetricsChart component

This commit is contained in:
Ken Hibino
2021-11-27 08:03:26 -08:00
parent d60905334f
commit d7ac077083
5 changed files with 96 additions and 6 deletions

View File

@@ -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{}

View File

@@ -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)}`);

View File

@@ -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 {

View 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;

View File

@@ -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>
);
}