mirror of
https://github.com/hibiken/asynqmon.git
synced 2025-01-19 03:05:53 +08:00
Add content to RedisInfoView
This commit is contained in:
parent
0c3cd80728
commit
14dc7de869
@ -15,8 +15,9 @@ import (
|
|||||||
// ****************************************************************************
|
// ****************************************************************************
|
||||||
|
|
||||||
type RedisInfoResponse struct {
|
type RedisInfoResponse struct {
|
||||||
Addr string `json:"address"`
|
Addr string `json:"address"`
|
||||||
Info map[string]string `json:"info"`
|
Info map[string]string `json:"info"`
|
||||||
|
RawInfo string `json:"raw_info"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func newRedisInfoHandlerFunc(rdb *redis.Client) http.HandlerFunc {
|
func newRedisInfoHandlerFunc(rdb *redis.Client) http.HandlerFunc {
|
||||||
@ -29,8 +30,9 @@ func newRedisInfoHandlerFunc(rdb *redis.Client) http.HandlerFunc {
|
|||||||
}
|
}
|
||||||
info := parseRedisInfo(res)
|
info := parseRedisInfo(res)
|
||||||
resp := RedisInfoResponse{
|
resp := RedisInfoResponse{
|
||||||
Addr: redisAddr,
|
Addr: redisAddr,
|
||||||
Info: info,
|
Info: info,
|
||||||
|
RawInfo: res,
|
||||||
}
|
}
|
||||||
if err := json.NewEncoder(w).Encode(resp); err != nil {
|
if err := json.NewEncoder(w).Encode(resp); err != nil {
|
||||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
|
@ -71,6 +71,7 @@ export interface ListQueueStatsResponse {
|
|||||||
export interface RedisInfoResponse {
|
export interface RedisInfoResponse {
|
||||||
address: string;
|
address: string;
|
||||||
info: RedisInfo;
|
info: RedisInfo;
|
||||||
|
raw_info: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return value from redis INFO command.
|
// Return value from redis INFO command.
|
||||||
|
@ -10,12 +10,14 @@ interface RedisInfoState {
|
|||||||
loading: boolean;
|
loading: boolean;
|
||||||
address: string;
|
address: string;
|
||||||
data: RedisInfo | null;
|
data: RedisInfo | null;
|
||||||
|
rawData: string | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const initialState: RedisInfoState = {
|
const initialState: RedisInfoState = {
|
||||||
loading: false,
|
loading: false,
|
||||||
address: "",
|
address: "",
|
||||||
data: null,
|
data: null,
|
||||||
|
rawData: null,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function redisInfoReducer(
|
export default function redisInfoReducer(
|
||||||
@ -40,6 +42,7 @@ export default function redisInfoReducer(
|
|||||||
loading: false,
|
loading: false,
|
||||||
address: action.payload.address,
|
address: action.payload.address,
|
||||||
data: action.payload.info,
|
data: action.payload.info,
|
||||||
|
rawData: action.payload.raw_info,
|
||||||
};
|
};
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -37,13 +37,18 @@ export function durationBefore(timestamp: string): string {
|
|||||||
|
|
||||||
export function timeAgo(timestamp: string): string {
|
export function timeAgo(timestamp: string): string {
|
||||||
try {
|
try {
|
||||||
const duration = durationBetween(Date.now(), Date.parse(timestamp));
|
return timeAgoUnix(Date.parse(timestamp) / 1000);
|
||||||
return stringifyDuration(duration) + " ago";
|
} catch (error) {
|
||||||
} catch {
|
console.error("Could not parse timestamp: ", timestamp, error);
|
||||||
return "-";
|
return "-";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function timeAgoUnix(unixtime: number) {
|
||||||
|
const duration = durationBetween(Date.now(), unixtime * 1000);
|
||||||
|
return stringifyDuration(duration) + " ago";
|
||||||
|
}
|
||||||
|
|
||||||
export function getCurrentUTCDate(): string {
|
export function getCurrentUTCDate(): string {
|
||||||
const today = new Date();
|
const today = new Date();
|
||||||
const dd = today.getUTCDate().toString().padStart(2, "0");
|
const dd = today.getUTCDate().toString().padStart(2, "0");
|
||||||
|
@ -4,9 +4,14 @@ import Container from "@material-ui/core/Container";
|
|||||||
import { makeStyles } from "@material-ui/core/styles";
|
import { makeStyles } from "@material-ui/core/styles";
|
||||||
import Grid from "@material-ui/core/Grid";
|
import Grid from "@material-ui/core/Grid";
|
||||||
import Typography from "@material-ui/core/Typography";
|
import Typography from "@material-ui/core/Typography";
|
||||||
|
import Card from "@material-ui/core/Card";
|
||||||
|
import CardContent from "@material-ui/core/CardContent";
|
||||||
|
import SyntaxHighlighter from "react-syntax-highlighter";
|
||||||
|
import syntaxHighlightStyle from "react-syntax-highlighter/dist/esm/styles/hljs/github";
|
||||||
import { getRedisInfoAsync } from "../actions/redisInfoActions";
|
import { getRedisInfoAsync } from "../actions/redisInfoActions";
|
||||||
import { usePolling } from "../hooks";
|
import { usePolling } from "../hooks";
|
||||||
import { AppState } from "../store";
|
import { AppState } from "../store";
|
||||||
|
import { timeAgoUnix } from "../utils";
|
||||||
|
|
||||||
const useStyles = makeStyles((theme) => ({
|
const useStyles = makeStyles((theme) => ({
|
||||||
container: {
|
container: {
|
||||||
@ -26,6 +31,7 @@ function mapStateToProps(state: AppState) {
|
|||||||
loading: state.redis.loading,
|
loading: state.redis.loading,
|
||||||
redisInfo: state.redis.data,
|
redisInfo: state.redis.data,
|
||||||
redisAddress: state.redis.address,
|
redisAddress: state.redis.address,
|
||||||
|
redisInfoRaw: state.redis.rawData,
|
||||||
pollInterval: state.settings.pollInterval,
|
pollInterval: state.settings.pollInterval,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -35,12 +41,10 @@ type Props = ConnectedProps<typeof connector>;
|
|||||||
|
|
||||||
function RedisInfoView(props: Props) {
|
function RedisInfoView(props: Props) {
|
||||||
const classes = useStyles();
|
const classes = useStyles();
|
||||||
const { pollInterval, getRedisInfoAsync } = props;
|
const { pollInterval, getRedisInfoAsync, redisInfo, redisInfoRaw } = props;
|
||||||
|
|
||||||
usePolling(getRedisInfoAsync, pollInterval);
|
usePolling(getRedisInfoAsync, pollInterval);
|
||||||
|
|
||||||
console.log("DEBUG: redisInfo", props.redisInfo);
|
|
||||||
|
|
||||||
// Metrics to show
|
// Metrics to show
|
||||||
// - Used Memory
|
// - Used Memory
|
||||||
// - Memory Fragmentation Ratio
|
// - Memory Fragmentation Ratio
|
||||||
@ -58,9 +62,125 @@ function RedisInfoView(props: Props) {
|
|||||||
Connected to: {props.redisAddress}
|
Connected to: {props.redisAddress}
|
||||||
</Typography>
|
</Typography>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
{redisInfo !== null && (
|
||||||
|
<>
|
||||||
|
<Grid item xs={12}>
|
||||||
|
<Typography variant="h6" color="textSecondary">
|
||||||
|
Server
|
||||||
|
</Typography>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={3}>
|
||||||
|
<MetricCard title="Version" content={redisInfo.redis_version} />
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={3}>
|
||||||
|
<MetricCard
|
||||||
|
title="Uptime"
|
||||||
|
content={`${redisInfo.uptime_in_days} days`}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={6} />
|
||||||
|
<Grid item xs={12}>
|
||||||
|
<Typography variant="h6" color="textSecondary">
|
||||||
|
Memory
|
||||||
|
</Typography>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={3}>
|
||||||
|
<MetricCard
|
||||||
|
title="Used Memory"
|
||||||
|
content={redisInfo.used_memory_human}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={3}>
|
||||||
|
<MetricCard
|
||||||
|
title="Peak Memory Used"
|
||||||
|
content={redisInfo.used_memory_peak_human}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={3}>
|
||||||
|
<MetricCard
|
||||||
|
title="Memory Fragmentation Ratio"
|
||||||
|
content={redisInfo.mem_fragmentation_ratio}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={3} />
|
||||||
|
<Grid item xs={12}>
|
||||||
|
<Typography variant="h6" color="textSecondary">
|
||||||
|
Connections
|
||||||
|
</Typography>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={3}>
|
||||||
|
<MetricCard
|
||||||
|
title="Connected Clients"
|
||||||
|
content={redisInfo.connected_clients}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={3}>
|
||||||
|
<MetricCard
|
||||||
|
title="Connected Replicas"
|
||||||
|
content={redisInfo.connected_slaves}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={6} />
|
||||||
|
<Grid item xs={12}>
|
||||||
|
<Typography variant="h6" color="textSecondary">
|
||||||
|
Persistence
|
||||||
|
</Typography>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={3}>
|
||||||
|
<MetricCard
|
||||||
|
title="Last Save to Disk"
|
||||||
|
content={timeAgoUnix(parseInt(redisInfo.rdb_last_save_time))}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={3}>
|
||||||
|
<MetricCard
|
||||||
|
title="Number of Changes Since Last Dump"
|
||||||
|
content={redisInfo.rdb_changes_since_last_save}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={6} />
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
{redisInfoRaw !== null && (
|
||||||
|
<>
|
||||||
|
<Grid item xs={6}>
|
||||||
|
<Typography variant="h6" color="textSecondary">
|
||||||
|
INFO Command Output
|
||||||
|
</Typography>
|
||||||
|
<SyntaxHighlighter language="yaml" style={syntaxHighlightStyle}>
|
||||||
|
{redisInfoRaw}
|
||||||
|
</SyntaxHighlighter>
|
||||||
|
</Grid>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</Grid>
|
</Grid>
|
||||||
</Container>
|
</Container>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface MetricCardProps {
|
||||||
|
title: string;
|
||||||
|
content: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
function MetricCard(props: MetricCardProps) {
|
||||||
|
return (
|
||||||
|
<Card variant="outlined">
|
||||||
|
<CardContent>
|
||||||
|
<Typography
|
||||||
|
gutterBottom
|
||||||
|
color="textPrimary"
|
||||||
|
variant="h5"
|
||||||
|
align="center"
|
||||||
|
>
|
||||||
|
{props.content}
|
||||||
|
</Typography>
|
||||||
|
<Typography color="textSecondary" variant="subtitle2" align="center">
|
||||||
|
{props.title}
|
||||||
|
</Typography>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
export default connector(RedisInfoView);
|
export default connector(RedisInfoView);
|
||||||
|
Loading…
Reference in New Issue
Block a user