mirror of
https://github.com/hibiken/asynqmon.git
synced 2025-09-23 23:36:33 +08:00
Use dynamic step when fetching metrics from Prometheus server
This commit is contained in:
@@ -80,12 +80,34 @@ func buildPrometheusURL(baseAddr, promQL string, opts *metricsFetchOptions) stri
|
||||
v.Add("query", promQL)
|
||||
v.Add("start", unixTimeString(opts.endTime.Add(-opts.duration)))
|
||||
v.Add("end", unixTimeString(opts.endTime))
|
||||
v.Add("step", (1 * time.Minute).String())
|
||||
v.Add("step", strconv.Itoa(int(step(opts).Seconds())))
|
||||
b.WriteString("?")
|
||||
b.WriteString(v.Encode())
|
||||
return b.String()
|
||||
}
|
||||
|
||||
// Returns step to use given the fetch options.
|
||||
// In general, the longer the duration, longer the each step.
|
||||
func step(opts *metricsFetchOptions) time.Duration {
|
||||
if opts.duration <= 6*time.Hour {
|
||||
// maximum number of data points to return: 6h / 10s = 2160
|
||||
return 10 * time.Second
|
||||
}
|
||||
if opts.duration <= 24*time.Hour {
|
||||
// maximum number of data points to return: 24h / 1m = 1440
|
||||
return 1 * time.Minute
|
||||
}
|
||||
if opts.duration <= 8*24*time.Hour {
|
||||
// maximum number of data points to return: (8*24)h / 3m = 3840
|
||||
return 3 * time.Minute
|
||||
}
|
||||
if opts.duration <= 30*24*time.Hour {
|
||||
// maximum number of data points to return: (30*24)h / 10m = 4320
|
||||
return 10 * time.Minute
|
||||
}
|
||||
return opts.duration / 3000
|
||||
}
|
||||
|
||||
func unixTimeString(t time.Time) string {
|
||||
return strconv.Itoa(int(t.Unix()))
|
||||
}
|
||||
|
@@ -68,13 +68,25 @@ function MetricsView(props: Props) {
|
||||
);
|
||||
|
||||
const [endTimeOption, setEndTimeOption] = React.useState("real_time");
|
||||
const [endTimeSec, setEndTimeSec] = React.useState(currentUnixtime());
|
||||
const [durationOption, setDurationOption] = React.useState("1h");
|
||||
const [durationSec, setDurationSec] = React.useState(60 * 60); // 1h
|
||||
|
||||
const handleEndTimeOptionChange = (
|
||||
event: React.ChangeEvent<HTMLInputElement>
|
||||
) => {
|
||||
setEndTimeOption((event.target as HTMLInputElement).value);
|
||||
const selected = (event.target as HTMLInputElement).value;
|
||||
setEndTimeOption(selected);
|
||||
switch (selected) {
|
||||
case "real_time":
|
||||
setEndTimeSec(currentUnixtime());
|
||||
break;
|
||||
case "freeze_at_now":
|
||||
setEndTimeSec(currentUnixtime());
|
||||
break;
|
||||
case "custom":
|
||||
// TODO:
|
||||
}
|
||||
};
|
||||
|
||||
const handleDurationOptionChange = (
|
||||
@@ -115,14 +127,15 @@ function MetricsView(props: Props) {
|
||||
const id = open ? "control-popover" : undefined;
|
||||
|
||||
React.useEffect(() => {
|
||||
console.log("DEBUG: GETTING metrics", currentUnixtime(), durationSec);
|
||||
getMetricsAsync(currentUnixtime(), durationSec);
|
||||
const id = setInterval(() => {
|
||||
console.log("DEBUG: GETTING metrics", currentUnixtime(), durationSec);
|
||||
getMetricsAsync(currentUnixtime(), durationSec);
|
||||
}, pollInterval * 1000);
|
||||
return () => clearInterval(id);
|
||||
}, [pollInterval, getMetricsAsync, durationSec]);
|
||||
getMetricsAsync(endTimeSec, durationSec);
|
||||
// Only set up polling if end_time option is "real_time"
|
||||
if (endTimeOption === "real_time") {
|
||||
const id = setInterval(() => {
|
||||
getMetricsAsync(currentUnixtime(), durationSec);
|
||||
}, pollInterval * 1000);
|
||||
return () => clearInterval(id);
|
||||
}
|
||||
}, [pollInterval, getMetricsAsync, durationSec, endTimeSec, endTimeOption]);
|
||||
|
||||
return (
|
||||
<Container maxWidth="lg" className={classes.container}>
|
||||
@@ -136,7 +149,8 @@ function MetricsView(props: Props) {
|
||||
color="primary"
|
||||
onClick={handleClick}
|
||||
>
|
||||
Realtime: {durationOption}
|
||||
{endTimeOption === "real_time" ? "Realtime" : "Historical"}:{" "}
|
||||
{durationOption}
|
||||
</Button>
|
||||
<Popover
|
||||
id={id}
|
||||
|
Reference in New Issue
Block a user