Rename Service to Endpoint (#192)

* Add clarifications in comments

* #191: Rename Service to Endpoint
This commit is contained in:
TwiN
2021-10-23 16:47:12 -04:00
committed by GitHub
parent 634123d723
commit 6ed93d4b82
99 changed files with 2136 additions and 2006 deletions

View File

@ -1,8 +1,8 @@
<template>
<div class='service px-3 py-3 border-l border-r border-t rounded-none hover:bg-gray-100 dark:hover:bg-gray-700 dark:border-gray-500' v-if="data">
<div class='endpoint px-3 py-3 border-l border-r border-t rounded-none hover:bg-gray-100 dark:hover:bg-gray-700 dark:border-gray-500' v-if="data">
<div class='flex flex-wrap mb-2'>
<div class='w-3/4'>
<router-link :to="generatePath()" class="font-bold hover:text-blue-800 hover:underline dark:hover:text-blue-400" title="View detailed service health">
<router-link :to="generatePath()" class="font-bold hover:text-blue-800 hover:underline dark:hover:text-blue-400" title="View detailed endpoint health">
{{ data.name }}
</router-link>
<span v-if="data.results && data.results.length && data.results[data.results.length - 1].hostname" class='text-gray-500 font-light'> | {{ data.results[data.results.length - 1].hostname }}</span>
@ -60,7 +60,7 @@
import {helper} from "@/mixins/helper";
export default {
name: 'Service',
name: 'Endpoint',
props: {
maximumNumberOfResults: Number,
data: Object,
@ -97,7 +97,7 @@ export default {
if (!this.data) {
return '/';
}
return `/services/${this.data.key}`;
return `/endpoints/${this.data.key}`;
},
showTooltip(result, event) {
this.$emit('showTooltip', result, event);
@ -126,12 +126,12 @@ export default {
<style>
.service:first-child {
.endpoint:first-child {
border-top-left-radius: 3px;
border-top-right-radius: 3px;
}
.service:last-child {
.endpoint:last-child {
border-bottom-left-radius: 3px;
border-bottom-right-radius: 3px;
border-bottom-width: 3px;

View File

@ -1,21 +1,21 @@
<template>
<div :class="services.length === 0 ? 'mt-3' : 'mt-4'">
<div :class="endpoints.length === 0 ? 'mt-3' : 'mt-4'">
<slot v-if="name !== 'undefined'">
<div class="service-group pt-2 border dark:bg-gray-800 dark:border-gray-500" @click="toggleGroup">
<div class="endpoint-group pt-2 border dark:bg-gray-800 dark:border-gray-500" @click="toggleGroup">
<h5 class='font-mono text-gray-400 text-xl font-medium pb-2 px-3 dark:text-gray-200 dark:hover:text-gray-500 dark:border-gray-500'>
<span v-if="healthy" class='text-green-600'>&#10003;</span>
<span v-else class='text-yellow-400'>~</span>
{{ name }}
<span class='float-right service-group-arrow'>
<span class='float-right endpoint-group-arrow'>
{{ collapsed ? '&#9660;' : '&#9650;' }}
</span>
</h5>
</div>
</slot>
<div v-if="!collapsed" :class="name === 'undefined' ? '' : 'service-group-content'">
<slot v-for="service in services" :key="service">
<Service
:data="service"
<div v-if="!collapsed" :class="name === 'undefined' ? '' : 'endpoint-group-content'">
<slot v-for="(endpoint, idx) in endpoints" :key="idx">
<Endpoint
:data="endpoint"
:maximumNumberOfResults="20"
@showTooltip="showTooltip"
@toggleShowAverageResponseTime="toggleShowAverageResponseTime" :showAverageResponseTime="showAverageResponseTime"
@ -27,26 +27,26 @@
<script>
import Service from './Service.vue';
import Endpoint from './Endpoint.vue';
export default {
name: 'ServiceGroup',
name: 'EndpointGroup',
components: {
Service
Endpoint
},
props: {
name: String,
services: Array,
endpoints: Array,
showAverageResponseTime: Boolean
},
emits: ['showTooltip', 'toggleShowAverageResponseTime'],
methods: {
healthCheck() {
if (this.services) {
for (let i in this.services) {
for (let j in this.services[i].results) {
if (!this.services[i].results[j].success) {
// Set the service group to unhealthy (only if it's currently healthy)
if (this.endpoints) {
for (let i in this.endpoints) {
for (let j in this.endpoints[i].results) {
if (!this.endpoints[i].results[j].success) {
// Set the endpoint group to unhealthy (only if it's currently healthy)
if (this.healthy) {
this.healthy = false;
}
@ -55,14 +55,14 @@ export default {
}
}
}
// Set the service group to healthy (only if it's currently unhealthy)
// Set the endpoint group to healthy (only if it's currently unhealthy)
if (!this.healthy) {
this.healthy = true;
}
},
toggleGroup() {
this.collapsed = !this.collapsed;
sessionStorage.setItem(`gatus:service-group:${this.name}:collapsed`, this.collapsed);
sessionStorage.setItem(`gatus:endpoint-group:${this.name}:collapsed`, this.collapsed);
},
showTooltip(result, event) {
this.$emit('showTooltip', result, event);
@ -72,7 +72,7 @@ export default {
}
},
watch: {
services: function () {
endpoints: function () {
this.healthCheck();
}
},
@ -82,7 +82,7 @@ export default {
data() {
return {
healthy: true,
collapsed: sessionStorage.getItem(`gatus:service-group:${this.name}:collapsed`) === "true"
collapsed: sessionStorage.getItem(`gatus:endpoint-group:${this.name}:collapsed`) === "true"
}
}
}
@ -90,12 +90,12 @@ export default {
<style>
.service-group {
.endpoint-group {
cursor: pointer;
user-select: none;
}
.service-group h5:hover {
.endpoint-group h5:hover {
color: #1b1e21;
}
</style>

View File

@ -0,0 +1,74 @@
<template>
<div id="results">
<slot v-for="endpointGroup in endpointGroups" :key="endpointGroup">
<EndpointGroup :endpoints="endpointGroup.endpoints" :name="endpointGroup.name" @showTooltip="showTooltip" @toggleShowAverageResponseTime="toggleShowAverageResponseTime" :showAverageResponseTime="showAverageResponseTime" />
</slot>
</div>
</template>
<script>
import EndpointGroup from './EndpointGroup.vue';
export default {
name: 'Endpoints',
components: {
EndpointGroup
},
props: {
showStatusOnHover: Boolean,
endpointStatuses: Object,
showAverageResponseTime: Boolean
},
emits: ['showTooltip', 'toggleShowAverageResponseTime'],
methods: {
process() {
let outputByGroup = {};
for (let endpointStatusIndex in this.endpointStatuses) {
let endpointStatus = this.endpointStatuses[endpointStatusIndex];
// create an empty entry if this group is new
if (!outputByGroup[endpointStatus.group] || outputByGroup[endpointStatus.group].length === 0) {
outputByGroup[endpointStatus.group] = [];
}
outputByGroup[endpointStatus.group].push(endpointStatus);
}
let endpointGroups = [];
for (let name in outputByGroup) {
if (name !== 'undefined') {
endpointGroups.push({name: name, endpoints: outputByGroup[name]})
}
}
// Add all endpoints that don't have a group at the end
if (outputByGroup['undefined']) {
endpointGroups.push({name: 'undefined', endpoints: outputByGroup['undefined']})
}
this.endpointGroups = endpointGroups;
},
showTooltip(result, event) {
this.$emit('showTooltip', result, event);
},
toggleShowAverageResponseTime() {
this.$emit('toggleShowAverageResponseTime');
}
},
watch: {
endpointStatuses: function () {
this.process();
}
},
data() {
return {
userClickedStatus: false,
endpointGroups: []
}
}
}
</script>
<style>
.endpoint-group-content > div:nth-child(1) {
border-top-left-radius: 0;
border-top-right-radius: 0;
}
</style>

View File

@ -1,74 +0,0 @@
<template>
<div id="results">
<slot v-for="serviceGroup in serviceGroups" :key="serviceGroup">
<ServiceGroup :services="serviceGroup.services" :name="serviceGroup.name" @showTooltip="showTooltip" @toggleShowAverageResponseTime="toggleShowAverageResponseTime" :showAverageResponseTime="showAverageResponseTime" />
</slot>
</div>
</template>
<script>
import ServiceGroup from './ServiceGroup.vue';
export default {
name: 'Services',
components: {
ServiceGroup
},
props: {
showStatusOnHover: Boolean,
serviceStatuses: Object,
showAverageResponseTime: Boolean
},
emits: ['showTooltip', 'toggleShowAverageResponseTime'],
methods: {
process() {
let outputByGroup = {};
for (let serviceStatusIndex in this.serviceStatuses) {
let serviceStatus = this.serviceStatuses[serviceStatusIndex];
// create an empty entry if this group is new
if (!outputByGroup[serviceStatus.group] || outputByGroup[serviceStatus.group].length === 0) {
outputByGroup[serviceStatus.group] = [];
}
outputByGroup[serviceStatus.group].push(serviceStatus);
}
let serviceGroups = [];
for (let name in outputByGroup) {
if (name !== 'undefined') {
serviceGroups.push({name: name, services: outputByGroup[name]})
}
}
// Add all services that don't have a group at the end
if (outputByGroup['undefined']) {
serviceGroups.push({name: 'undefined', services: outputByGroup['undefined']})
}
this.serviceGroups = serviceGroups;
},
showTooltip(result, event) {
this.$emit('showTooltip', result, event);
},
toggleShowAverageResponseTime() {
this.$emit('toggleShowAverageResponseTime');
}
},
watch: {
serviceStatuses: function () {
this.process();
}
},
data() {
return {
userClickedStatus: false,
serviceGroups: []
}
}
}
</script>
<style>
.service-group-content > div:nth-child(1) {
border-top-left-radius: 0;
border-top-right-radius: 0;
}
</style>

View File

@ -26,7 +26,7 @@
<script>
export default {
name: 'Services',
name: 'Endpoints',
props: {
event: Event,
result: Object

View File

@ -3,21 +3,25 @@ import Home from '@/views/Home'
import Details from "@/views/Details";
const routes = [
{
path: '/',
name: 'Home',
component: Home
},
{
path: '/services/:key',
name: 'Details',
component: Details,
},
]
{
path: '/',
name: 'Home',
component: Home
},
{
path: '/endpoints/:key',
name: 'Details',
component: Details,
},
{ // XXX: Remove in v4.0.0
path: '/services/:key',
redirect: {name: 'Details'}
},
];
const router = createRouter({
history: createWebHistory(process.env.BASE_URL),
routes
})
history: createWebHistory(process.env.BASE_URL),
routes
});
export default router
export default router;

View File

@ -4,11 +4,11 @@
&larr;
</router-link>
<div>
<slot v-if="serviceStatus">
<slot v-if="endpointStatus">
<h1 class="text-xl xl:text-3xl font-mono text-gray-400">RECENT CHECKS</h1>
<hr class="mb-4"/>
<Service
:data="serviceStatus"
<Endpoint
:data="endpointStatus"
:maximumNumberOfResults="20"
@showTooltip="showTooltip"
@toggleShowAverageResponseTime="toggleShowAverageResponseTime"
@ -16,7 +16,7 @@
/>
<Pagination @page="changePage"/>
</slot>
<div v-if="serviceStatus && serviceStatus.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">UPTIME</h1>
<hr/>
<div class="flex space-x-4 text-center text-2xl mt-6 relative bottom-2 mb-10">
@ -34,7 +34,7 @@
</div>
</div>
</div>
<div v-if="serviceStatus && serviceStatus.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>
<hr/>
<img :src="generateResponseTimeChartImageURL()" alt="response time chart" class="mt-6" />
@ -53,7 +53,7 @@
</div>
</div>
</div>
<div v-if="serviceStatus && serviceStatus.key">
<div v-if="endpointStatus && endpointStatus.key">
<h1 class="text-xl xl:text-3xl font-mono text-gray-400 mt-4">EVENTS</h1>
<hr class="mb-4"/>
<div>
@ -87,7 +87,7 @@
<script>
import Settings from '@/components/Settings.vue'
import Service from '@/components/Service.vue';
import Endpoint from '@/components/Endpoint.vue';
import {SERVER_URL} from "@/main.js";
import {helper} from "@/mixins/helper.js";
import Pagination from "@/components/Pagination";
@ -96,7 +96,7 @@ export default {
name: 'Details',
components: {
Pagination,
Service,
Endpoint,
Settings,
},
emits: ['showTooltip'],
@ -104,32 +104,32 @@ export default {
methods: {
fetchData() {
//console.log("[Details][fetchData] Fetching data");
fetch(`${this.serverUrl}/api/v1/services/${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(data => {
if (JSON.stringify(this.serviceStatus) !== JSON.stringify(data)) {
this.serviceStatus = data;
if (JSON.stringify(this.endpointStatus) !== JSON.stringify(data)) {
this.endpointStatus = data;
this.uptime = data.uptime;
let events = [];
for (let i = data.events.length - 1; i >= 0; i--) {
let event = data.events[i];
if (i === data.events.length - 1) {
if (event.type === 'UNHEALTHY') {
event.fancyText = 'Service is unhealthy';
event.fancyText = 'Endpoint is unhealthy';
} else if (event.type === 'HEALTHY') {
event.fancyText = 'Service is healthy';
event.fancyText = 'Endpoint is healthy';
} else if (event.type === 'START') {
event.fancyText = 'Monitoring started';
}
} else {
let nextEvent = data.events[i + 1];
if (event.type === 'HEALTHY') {
event.fancyText = 'Service became healthy';
event.fancyText = 'Endpoint became healthy';
} else if (event.type === 'UNHEALTHY') {
if (nextEvent) {
event.fancyText = 'Service was unhealthy for ' + this.prettifyTimeDifference(nextEvent.timestamp, event.timestamp);
event.fancyText = 'Endpoint was unhealthy for ' + this.prettifyTimeDifference(nextEvent.timestamp, event.timestamp);
} else {
event.fancyText = 'Service became unhealthy';
event.fancyText = 'Endpoint became unhealthy';
}
} else if (event.type === 'START') {
event.fancyText = 'Monitoring started';
@ -143,13 +143,13 @@ export default {
});
},
generateUptimeBadgeImageURL(duration) {
return `${this.serverUrl}/api/v1/services/${this.serviceStatus.key}/uptimes/${duration}/badge.svg`;
return `${this.serverUrl}/api/v1/endpoints/${this.endpointStatus.key}/uptimes/${duration}/badge.svg`;
},
generateResponseTimeBadgeImageURL(duration) {
return `${this.serverUrl}/api/v1/services/${this.serviceStatus.key}/response-times/${duration}/badge.svg`;
return `${this.serverUrl}/api/v1/endpoints/${this.endpointStatus.key}/response-times/${duration}/badge.svg`;
},
generateResponseTimeChartImageURL() {
return `${this.serverUrl}/api/v1/services/${this.serviceStatus.key}/response-times/24h/chart.svg`;
return `${this.serverUrl}/api/v1/endpoints/${this.endpointStatus.key}/response-times/24h/chart.svg`;
},
prettifyUptime(uptime) {
if (!uptime) {
@ -174,7 +174,7 @@ export default {
},
data() {
return {
serviceStatus: {},
endpointStatus: {},
uptime: {},
events: [],
hourlyAverageResponseTime: {},
@ -193,7 +193,7 @@ export default {
</script>
<style scoped>
.service {
.endpoint {
border-radius: 3px;
border-bottom-width: 3px;
}

View File

@ -1,6 +1,6 @@
<template>
<Services
:serviceStatuses="serviceStatuses"
<Endpoints
:endpointStatuses="endpointStatuses"
:showStatusOnHover="true"
@showTooltip="showTooltip"
@toggleShowAverageResponseTime="toggleShowAverageResponseTime" :showAverageResponseTime="showAverageResponseTime"
@ -11,7 +11,7 @@
<script>
import Settings from '@/components/Settings.vue'
import Services from '@/components/Services.vue';
import Endpoints from '@/components/Endpoints.vue';
import Pagination from "@/components/Pagination";
import {SERVER_URL} from "@/main.js";
@ -19,18 +19,18 @@ export default {
name: 'Home',
components: {
Pagination,
Services,
Endpoints,
Settings,
},
emits: ['showTooltip', 'toggleShowAverageResponseTime'],
methods: {
fetchData() {
//console.log("[Home][fetchData] Fetching data");
fetch(`${SERVER_URL}/api/v1/services/statuses?page=${this.currentPage}`)
fetch(`${SERVER_URL}/api/v1/endpoints/statuses?page=${this.currentPage}`)
.then(response => response.json())
.then(data => {
if (JSON.stringify(this.serviceStatuses) !== JSON.stringify(data)) {
this.serviceStatuses = data;
if (JSON.stringify(this.endpointStatuses) !== JSON.stringify(data)) {
this.endpointStatuses = data;
}
});
},
@ -47,7 +47,7 @@ export default {
},
data() {
return {
serviceStatuses: [],
endpointStatuses: [],
currentPage: 1,
showAverageResponseTime: true
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long