mirror of
https://github.com/TwiN/gatus.git
synced 2024-11-21 15:33:17 +01:00
Start working on replacing SSR chart by chart.js
This commit is contained in:
parent
c4ef56511d
commit
ed4fa94fc2
@ -1,6 +1,7 @@
|
|||||||
package handler
|
package handler
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
"log"
|
"log"
|
||||||
"math"
|
"math"
|
||||||
"net/http"
|
"net/http"
|
||||||
@ -117,3 +118,41 @@ func ResponseTimeChart(writer http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ResponseTime(writer http.ResponseWriter, r *http.Request) {
|
||||||
|
vars := mux.Vars(r)
|
||||||
|
duration := vars["duration"]
|
||||||
|
var from time.Time
|
||||||
|
switch duration {
|
||||||
|
case "7d":
|
||||||
|
from = time.Now().Truncate(time.Hour).Add(-24 * 7 * time.Hour)
|
||||||
|
case "24h":
|
||||||
|
from = time.Now().Truncate(time.Hour).Add(-24 * time.Hour)
|
||||||
|
default:
|
||||||
|
http.Error(writer, "Durations supported: 7d, 24h", http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
hourlyAverageResponseTime, err := store.Get().GetHourlyAverageResponseTimeByKey(vars["key"], from, time.Now())
|
||||||
|
if err != nil {
|
||||||
|
if err == common.ErrEndpointNotFound {
|
||||||
|
http.Error(writer, err.Error(), http.StatusNotFound)
|
||||||
|
} else if err == common.ErrInvalidTimeRange {
|
||||||
|
http.Error(writer, err.Error(), http.StatusBadRequest)
|
||||||
|
} else {
|
||||||
|
http.Error(writer, err.Error(), http.StatusInternalServerError)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if len(hourlyAverageResponseTime) == 0 {
|
||||||
|
http.Error(writer, "", http.StatusNoContent)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
data, err := json.Marshal(hourlyAverageResponseTime)
|
||||||
|
if err != nil {
|
||||||
|
http.Error(writer, err.Error(), http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
writer.Header().Add("Content-Type", "application/json")
|
||||||
|
writer.WriteHeader(http.StatusOK)
|
||||||
|
_, _ = writer.Write(data)
|
||||||
|
}
|
||||||
|
@ -23,6 +23,7 @@ func CreateRouter(staticFolder string, securityConfig *security.Config, uiConfig
|
|||||||
router.HandleFunc("/api/v1/endpoints/{key}/uptimes/{duration}/badge.svg", UptimeBadge).Methods("GET")
|
router.HandleFunc("/api/v1/endpoints/{key}/uptimes/{duration}/badge.svg", UptimeBadge).Methods("GET")
|
||||||
router.HandleFunc("/api/v1/endpoints/{key}/response-times/{duration}/badge.svg", ResponseTimeBadge).Methods("GET")
|
router.HandleFunc("/api/v1/endpoints/{key}/response-times/{duration}/badge.svg", ResponseTimeBadge).Methods("GET")
|
||||||
router.HandleFunc("/api/v1/endpoints/{key}/response-times/{duration}/chart.svg", ResponseTimeChart).Methods("GET")
|
router.HandleFunc("/api/v1/endpoints/{key}/response-times/{duration}/chart.svg", ResponseTimeChart).Methods("GET")
|
||||||
|
router.HandleFunc("/api/v1/endpoints/{key}/response-times/{duration}", ResponseTime).Methods("GET")
|
||||||
// XXX: Remove the lines between this and the next XXX comment in v4.0.0
|
// XXX: Remove the lines between this and the next XXX comment in v4.0.0
|
||||||
router.HandleFunc("/api/v1/services/statuses", secureIfNecessary(securityConfig, EndpointStatuses)).Methods("GET") // No GzipHandler for this one, because we cache the content as Gzipped already
|
router.HandleFunc("/api/v1/services/statuses", secureIfNecessary(securityConfig, EndpointStatuses)).Methods("GET") // No GzipHandler for this one, because we cache the content as Gzipped already
|
||||||
router.HandleFunc("/api/v1/services/{key}/statuses", secureIfNecessary(securityConfig, GzipHandlerFunc(EndpointStatus))).Methods("GET")
|
router.HandleFunc("/api/v1/services/{key}/statuses", secureIfNecessary(securityConfig, GzipHandlerFunc(EndpointStatus))).Methods("GET")
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"core-js": "^3.19.1",
|
"core-js": "^3.19.1",
|
||||||
"vue": "3.2.21",
|
"vue": "3.2.21",
|
||||||
|
"vue-chart-3": "^0.5.11",
|
||||||
"vue-router": "^4.0.11"
|
"vue-router": "^4.0.11"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
@ -37,6 +37,9 @@
|
|||||||
<div v-if="endpointStatus && endpointStatus.key" class="mt-12">
|
<div v-if="endpointStatus && endpointStatus.key" class="mt-12">
|
||||||
<h1 class="text-xl xl:text-3xl font-mono text-gray-400">RESPONSE TIME</h1>
|
<h1 class="text-xl xl:text-3xl font-mono text-gray-400">RESPONSE TIME</h1>
|
||||||
<hr/>
|
<hr/>
|
||||||
|
|
||||||
|
<LineChart :chartData="chartData" :options="chartOptions" />
|
||||||
|
|
||||||
<img :src="generateResponseTimeChartImageURL()" alt="response time chart" class="mt-6" />
|
<img :src="generateResponseTimeChartImageURL()" alt="response time chart" class="mt-6" />
|
||||||
<div class="flex space-x-4 text-center text-2xl mt-6 relative bottom-2 mb-10">
|
<div class="flex space-x-4 text-center text-2xl mt-6 relative bottom-2 mb-10">
|
||||||
<div class="flex-1">
|
<div class="flex-1">
|
||||||
@ -92,17 +95,24 @@ import {SERVER_URL} from "@/main.js";
|
|||||||
import {helper} from "@/mixins/helper.js";
|
import {helper} from "@/mixins/helper.js";
|
||||||
import Pagination from "@/components/Pagination";
|
import Pagination from "@/components/Pagination";
|
||||||
|
|
||||||
|
import { LineChart } from 'vue-chart-3';
|
||||||
|
import { Chart, CategoryScale, LineController, LinearScale, LineElement, PointElement, TimeScale, Title, Tooltip} from 'chart.js';
|
||||||
|
Chart.register(LineController, CategoryScale, LinearScale, LineElement, PointElement, TimeScale, Title, Tooltip);
|
||||||
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'Details',
|
name: 'Details',
|
||||||
components: {
|
components: {
|
||||||
Pagination,
|
Pagination,
|
||||||
Endpoint,
|
Endpoint,
|
||||||
Settings,
|
Settings,
|
||||||
|
LineChart,
|
||||||
},
|
},
|
||||||
emits: ['showTooltip'],
|
emits: ['showTooltip'],
|
||||||
mixins: [helper],
|
mixins: [helper],
|
||||||
methods: {
|
methods: {
|
||||||
fetchData() {
|
fetchData() {
|
||||||
|
// XXX: This should probably be called every 15 minutes or so
|
||||||
//console.log("[Details][fetchData] Fetching data");
|
//console.log("[Details][fetchData] Fetching data");
|
||||||
fetch(`${this.serverUrl}/api/v1/endpoints/${this.$route.params.key}/statuses?page=${this.currentPage}`)
|
fetch(`${this.serverUrl}/api/v1/endpoints/${this.$route.params.key}/statuses?page=${this.currentPage}`)
|
||||||
.then(response => response.json())
|
.then(response => response.json())
|
||||||
@ -140,8 +150,39 @@ export default {
|
|||||||
}
|
}
|
||||||
this.events = events;
|
this.events = events;
|
||||||
}
|
}
|
||||||
|
this.fetchUptimeChartData();
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
fetchUptimeChartData() {
|
||||||
|
fetch(`${this.serverUrl}/api/v1/endpoints/${this.$route.params.key}/response-times/24h`).then(response => {
|
||||||
|
response.json().then(data => {
|
||||||
|
let chart = {
|
||||||
|
labels: [],
|
||||||
|
datasets: [
|
||||||
|
{
|
||||||
|
label: 'Average response time (ms)',
|
||||||
|
data: [],
|
||||||
|
borderColor: 'rgb(75, 192, 192)',
|
||||||
|
},
|
||||||
|
]
|
||||||
|
};
|
||||||
|
let latest = null;
|
||||||
|
for (const [key] of Object.entries(data)) {
|
||||||
|
latest = key;
|
||||||
|
}
|
||||||
|
for (let i = 24; i >= 0; i--) {
|
||||||
|
let date = new Date((latest*1000)-(i*3600000));
|
||||||
|
chart.labels.push(date.toLocaleTimeString().replaceAll(":00", ""));
|
||||||
|
if (data[date.getTime()/1000]) {
|
||||||
|
chart.datasets[0].data.push(data[date.getTime()/1000]);
|
||||||
|
} else {
|
||||||
|
chart.datasets[0].data.push(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.chartData = chart;
|
||||||
|
})
|
||||||
|
});
|
||||||
|
},
|
||||||
generateUptimeBadgeImageURL(duration) {
|
generateUptimeBadgeImageURL(duration) {
|
||||||
return `${this.serverUrl}/api/v1/endpoints/${this.endpointStatus.key}/uptimes/${duration}/badge.svg`;
|
return `${this.serverUrl}/api/v1/endpoints/${this.endpointStatus.key}/uptimes/${duration}/badge.svg`;
|
||||||
},
|
},
|
||||||
@ -182,8 +223,18 @@ export default {
|
|||||||
serverUrl: SERVER_URL === '.' ? '..' : SERVER_URL,
|
serverUrl: SERVER_URL === '.' ? '..' : SERVER_URL,
|
||||||
currentPage: 1,
|
currentPage: 1,
|
||||||
showAverageResponseTime: true,
|
showAverageResponseTime: true,
|
||||||
chartLabels: [],
|
chartData: {labels: [], datasets: [{data: []}]},
|
||||||
chartValues: [],
|
chartOptions: {
|
||||||
|
scales: {
|
||||||
|
y: {
|
||||||
|
min: 0,
|
||||||
|
title: {
|
||||||
|
display: true,
|
||||||
|
text: 'Average response time (ms)'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
|
Loading…
Reference in New Issue
Block a user