mirror of
https://github.com/hibiken/asynqmon.git
synced 2025-09-22 06:46:34 +08:00
(ui): Add QueueSizeMetricsChart component
This commit is contained in:
@@ -23,7 +23,7 @@ func newGetMetricsHandlerFunc(client *http.Client) http.HandlerFunc {
|
|||||||
const (
|
const (
|
||||||
baseAddr = "http://localhost:9090"
|
baseAddr = "http://localhost:9090"
|
||||||
apiPath = "/api/v1/query_range"
|
apiPath = "/api/v1/query_range"
|
||||||
promQL = "asynq_tasks_enqueued_total"
|
promQL = "asynq_queue_size"
|
||||||
)
|
)
|
||||||
var b strings.Builder
|
var b strings.Builder
|
||||||
v := url.Values{}
|
v := url.Values{}
|
||||||
|
@@ -32,7 +32,6 @@ export function getMetricsAsync() {
|
|||||||
dispatch({ type: GET_METRICS_BEGIN });
|
dispatch({ type: GET_METRICS_BEGIN });
|
||||||
try {
|
try {
|
||||||
const response = await getMetrics();
|
const response = await getMetrics();
|
||||||
console.log("DEBUG: got metrics: ", response);
|
|
||||||
dispatch({ type: GET_METRICS_SUCCESS, payload: response });
|
dispatch({ type: GET_METRICS_SUCCESS, payload: response });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(`getMetricsAsync: ${toErrorStringWithHttpStatus(error)}`);
|
console.error(`getMetricsAsync: ${toErrorStringWithHttpStatus(error)}`);
|
||||||
|
@@ -86,7 +86,7 @@ export interface MetricsResult {
|
|||||||
|
|
||||||
export interface Metrics {
|
export interface Metrics {
|
||||||
metric: MetricsInfo;
|
metric: MetricsInfo;
|
||||||
values: [number, string]; // [unixtime, value]
|
values: [number, string][]; // [unixtime, value]
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface MetricsInfo {
|
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 { connect, ConnectedProps } from "react-redux";
|
||||||
import { makeStyles } from "@material-ui/core/styles";
|
import { makeStyles } from "@material-ui/core/styles";
|
||||||
import Container from "@material-ui/core/Container";
|
import Container from "@material-ui/core/Container";
|
||||||
@@ -6,6 +6,8 @@ import Grid from "@material-ui/core/Grid";
|
|||||||
import { getMetricsAsync } from "../actions/metricsActions";
|
import { getMetricsAsync } from "../actions/metricsActions";
|
||||||
import { AppState } from "../store";
|
import { AppState } from "../store";
|
||||||
import { usePolling } from "../hooks";
|
import { usePolling } from "../hooks";
|
||||||
|
import Typography from "@material-ui/core/Typography";
|
||||||
|
import QueueSizeMetricsChart from "../components/QueueSizeMetricsChart";
|
||||||
|
|
||||||
const useStyles = makeStyles((theme) => ({
|
const useStyles = makeStyles((theme) => ({
|
||||||
container: {
|
container: {
|
||||||
@@ -28,7 +30,7 @@ type Props = ConnectedProps<typeof connector>;
|
|||||||
|
|
||||||
function MetricsView(props: Props) {
|
function MetricsView(props: Props) {
|
||||||
const classes = useStyles();
|
const classes = useStyles();
|
||||||
const { pollInterval, getMetricsAsync } = props;
|
const { pollInterval, getMetricsAsync, data } = props;
|
||||||
|
|
||||||
usePolling(getMetricsAsync, pollInterval);
|
usePolling(getMetricsAsync, pollInterval);
|
||||||
|
|
||||||
@@ -36,9 +38,14 @@ function MetricsView(props: Props) {
|
|||||||
<Container maxWidth="lg" className={classes.container}>
|
<Container maxWidth="lg" className={classes.container}>
|
||||||
<Grid container spacing={3}>
|
<Grid container spacing={3}>
|
||||||
<Grid item xs={12}>
|
<Grid item xs={12}>
|
||||||
Hello Metrics
|
<Typography>Queue Size</Typography>
|
||||||
|
<QueueSizeMetricsChart data={data?.data.result || []} />
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
<Grid item xs={12}>
|
||||||
|
<Typography>Queue Latency</Typography>
|
||||||
|
<div>TODO: Queue latency chart here</div>
|
||||||
|
</Grid>
|
||||||
</Container>
|
</Container>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user