mirror of https://github.com/bastienwirtz/homer
Merge 9bf75f98ab
into c230392da8
commit
7bbecc3ca5
|
@ -18,6 +18,7 @@ within Homer:
|
||||||
- [Docker Socket Proxy](#docker-socket-proxy)
|
- [Docker Socket Proxy](#docker-socket-proxy)
|
||||||
- [Emby / Jellyfin](#emby--jellyfin)
|
- [Emby / Jellyfin](#emby--jellyfin)
|
||||||
- [FreshRSS](#freshrss)
|
- [FreshRSS](#freshrss)
|
||||||
|
- [Gatus](#gatus)
|
||||||
- [Gitea / Forgejo](#gitea--forgejo)
|
- [Gitea / Forgejo](#gitea--forgejo)
|
||||||
- [Glances](#glances)
|
- [Glances](#glances)
|
||||||
- [Gotify](#gotify)
|
- [Gotify](#gotify)
|
||||||
|
@ -154,6 +155,32 @@ The FreshRSS service displays unread and subscriptions counts from your FreshRSS
|
||||||
updateInterval: 5000 # (Optional) Interval (in ms) for updating the stats
|
updateInterval: 5000 # (Optional) Interval (in ms) for updating the stats
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Gatus
|
||||||
|
|
||||||
|
The Gatus service displays information about the configured services from the defined Gatus server.
|
||||||
|
Two lines are needed in the config.yml :
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
type: "Gatus"
|
||||||
|
url: "http://192.168.0.151/gatus"
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
Optionally, the results can be filtered to only include jobs in the defined groups:
|
||||||
|
```yaml
|
||||||
|
groups: [Services, External]
|
||||||
|
```
|
||||||
|
|
||||||
|
The status can be checked regularly by defining an update Interval in ms:
|
||||||
|
```yaml
|
||||||
|
updateInterval: 5000
|
||||||
|
```
|
||||||
|
|
||||||
|
The average times can be hidden (saves their calculation also) by setting the following:
|
||||||
|
```yaml
|
||||||
|
hideaverages: true
|
||||||
|
```
|
||||||
|
|
||||||
## Gitea / Forgejo
|
## Gitea / Forgejo
|
||||||
|
|
||||||
This service displays a version string instead of a subtitle. Example configuration:
|
This service displays a version string instead of a subtitle. Example configuration:
|
||||||
|
|
|
@ -0,0 +1,211 @@
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"name": "Gateway",
|
||||||
|
"group": "Services",
|
||||||
|
"key": "services_gateway",
|
||||||
|
"results": [
|
||||||
|
{
|
||||||
|
"status": 200,
|
||||||
|
"hostname": "gateway.example.com",
|
||||||
|
"duration": 10000,
|
||||||
|
"conditionResults": [
|
||||||
|
{
|
||||||
|
"condition": "[STATUS] == 200",
|
||||||
|
"success": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"condition": "[RESPONSE_TIME] < 500",
|
||||||
|
"success": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"success": true,
|
||||||
|
"timestamp": "2025-05-26T07:35:41.784208588Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"status": 200,
|
||||||
|
"hostname": "gateway.example.com",
|
||||||
|
"duration": 10000,
|
||||||
|
"conditionResults": [
|
||||||
|
{
|
||||||
|
"condition": "[STATUS] == 200",
|
||||||
|
"success": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"condition": "[RESPONSE_TIME] < 500",
|
||||||
|
"success": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"success": true,
|
||||||
|
"timestamp": "2025-05-26T07:40:41.804489793Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"status": 200,
|
||||||
|
"hostname": "gateway.example.com",
|
||||||
|
"duration": 10000,
|
||||||
|
"conditionResults": [
|
||||||
|
{
|
||||||
|
"condition": "[STATUS] == 200",
|
||||||
|
"success": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"condition": "[RESPONSE_TIME] < 500",
|
||||||
|
"success": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"success": true,
|
||||||
|
"timestamp": "2025-05-26T07:45:41.837925713Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"status": 200,
|
||||||
|
"hostname": "gateway.example.com",
|
||||||
|
"duration": 10000,
|
||||||
|
"conditionResults": [
|
||||||
|
{
|
||||||
|
"condition": "[STATUS] == 200",
|
||||||
|
"success": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"condition": "[RESPONSE_TIME] < 500",
|
||||||
|
"success": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"success": true,
|
||||||
|
"timestamp": "2025-05-26T07:50:41.848391366Z"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Website",
|
||||||
|
"group": "External",
|
||||||
|
"key": "external_website",
|
||||||
|
"results": [
|
||||||
|
{
|
||||||
|
"status": 200,
|
||||||
|
"hostname": "www.example.com",
|
||||||
|
"duration": 10000,
|
||||||
|
"conditionResults": [
|
||||||
|
{
|
||||||
|
"condition": "[STATUS] == 200",
|
||||||
|
"success": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"condition": "[RESPONSE_TIME] < 500",
|
||||||
|
"success": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"success": false,
|
||||||
|
"timestamp": "2025-05-26T07:35:41.784208588Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"status": 200,
|
||||||
|
"hostname": "gateway.example.com",
|
||||||
|
"duration": 10000,
|
||||||
|
"conditionResults": [
|
||||||
|
{
|
||||||
|
"condition": "[STATUS] == 200",
|
||||||
|
"success": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"condition": "[RESPONSE_TIME] < 500",
|
||||||
|
"success": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"success": false,
|
||||||
|
"timestamp": "2025-05-26T07:40:41.804489793Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"status": 200,
|
||||||
|
"hostname": "gateway.example.com",
|
||||||
|
"duration": 10000,
|
||||||
|
"conditionResults": [
|
||||||
|
{
|
||||||
|
"condition": "[STATUS] == 200",
|
||||||
|
"success": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"condition": "[RESPONSE_TIME] < 500",
|
||||||
|
"success": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"success": true,
|
||||||
|
"timestamp": "2025-05-26T07:45:41.837925713Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"status": 200,
|
||||||
|
"hostname": "gateway.example.com",
|
||||||
|
"duration": 10000,
|
||||||
|
"conditionResults": [
|
||||||
|
{
|
||||||
|
"condition": "[STATUS] == 200",
|
||||||
|
"success": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"condition": "[RESPONSE_TIME] < 500",
|
||||||
|
"success": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"success": true,
|
||||||
|
"timestamp": "2025-05-26T07:50:41.848391366Z"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "DNS",
|
||||||
|
"group": "Services",
|
||||||
|
"key": "services_dns",
|
||||||
|
"results": [
|
||||||
|
{
|
||||||
|
"status": 200,
|
||||||
|
"hostname": "ns1.example",
|
||||||
|
"duration": 20000,
|
||||||
|
"conditionResults": [
|
||||||
|
{
|
||||||
|
"condition": "[STATUS] == 200",
|
||||||
|
"success": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"success": false,
|
||||||
|
"timestamp": "2025-05-26T07:35:41.784208588Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"status": 200,
|
||||||
|
"hostname": "ns1.example.com",
|
||||||
|
"duration": 20000,
|
||||||
|
"conditionResults": [
|
||||||
|
{
|
||||||
|
"condition": "[STATUS] == 200",
|
||||||
|
"success": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"success": false,
|
||||||
|
"timestamp": "2025-05-26T07:40:41.804489793Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"status": 200,
|
||||||
|
"hostname": "ns1.example.com",
|
||||||
|
"duration": 20000,
|
||||||
|
"conditionResults": [
|
||||||
|
{
|
||||||
|
"condition": "[STATUS] == 200",
|
||||||
|
"success": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"success": false,
|
||||||
|
"timestamp": "2025-05-26T07:45:41.837925713Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"status": 200,
|
||||||
|
"hostname": "ns1.example.com",
|
||||||
|
"duration": 20000,
|
||||||
|
"conditionResults": [
|
||||||
|
{
|
||||||
|
"condition": "[STATUS] == 200",
|
||||||
|
"success": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"success": false,
|
||||||
|
"timestamp": "2025-05-26T07:50:41.848391366Z"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
|
@ -0,0 +1,153 @@
|
||||||
|
<template>
|
||||||
|
<Generic :item="item">
|
||||||
|
<template #content>
|
||||||
|
<p class="title is-4">{{ item.name }}</p>
|
||||||
|
<p class="subtitle is-6">
|
||||||
|
<template v-if="item.subtitle">
|
||||||
|
{{ item.subtitle }}
|
||||||
|
</template>
|
||||||
|
<i class="fa-solid fa-signal"></i> {{ up }}/{{ total }}
|
||||||
|
<template v-if="avgRespTime > 0">
|
||||||
|
<span class="separator"> | </span>
|
||||||
|
<i class="fa-solid fa-stopwatch"></i> {{ avgRespTime }} ms avg.
|
||||||
|
</template>
|
||||||
|
</p>
|
||||||
|
</template>
|
||||||
|
<template #indicator>
|
||||||
|
<div v-if="status !== false" class="status" :class="status">
|
||||||
|
{{ percentageGood }}%
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</Generic>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import service from "@/mixins/service.js";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "Gatus",
|
||||||
|
mixins: [service],
|
||||||
|
props: {
|
||||||
|
item: Object,
|
||||||
|
},
|
||||||
|
data: () => ({
|
||||||
|
up: 0,
|
||||||
|
down: 0,
|
||||||
|
total: 0,
|
||||||
|
avgRespTime: NaN,
|
||||||
|
percentageGood: NaN,
|
||||||
|
status: false,
|
||||||
|
statusMessage: false
|
||||||
|
}),
|
||||||
|
created() {
|
||||||
|
const updateInterval = parseInt(this.item.updateInterval, 10) || 0;
|
||||||
|
if (updateInterval > 0) {
|
||||||
|
setInterval(() => this.fetchStatus(), updateInterval);
|
||||||
|
}
|
||||||
|
this.fetchStatus();
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
fetchStatus: async function () {
|
||||||
|
this.fetch("/api/v1/endpoints/statuses", { method: "GET", cache: "no-cache" })
|
||||||
|
.then((response) => {
|
||||||
|
// Apply filtering by groups, if defined
|
||||||
|
if (this.item.groups) {
|
||||||
|
response = response?.filter((job) => {
|
||||||
|
return this.item.groups.includes(job.group) === true;
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialise counts, avg times
|
||||||
|
this.total = response.length;
|
||||||
|
this.up = 0;
|
||||||
|
|
||||||
|
let totalrestime = 0;
|
||||||
|
let totalresults = 0;
|
||||||
|
|
||||||
|
response.forEach((job) => {
|
||||||
|
if (job.results[job.results.length - 1].success === true) {
|
||||||
|
this.up++;
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!this.item.hideaverages) {
|
||||||
|
// Update array of average times
|
||||||
|
let totalduration = 0;
|
||||||
|
let rescounter = 0;
|
||||||
|
job.results.forEach((res) => {
|
||||||
|
totalduration += parseInt(res.duration, 10) / 1000;
|
||||||
|
rescounter++;
|
||||||
|
})
|
||||||
|
|
||||||
|
totalrestime += totalduration;
|
||||||
|
totalresults += rescounter;
|
||||||
|
} else {
|
||||||
|
totalrestime = 0;
|
||||||
|
totalresults = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
// Rest are down
|
||||||
|
this.down = this.total - this.up;
|
||||||
|
|
||||||
|
// Calculate overall average response time
|
||||||
|
this.avgRespTime = (totalrestime / totalresults).toFixed(2);
|
||||||
|
|
||||||
|
// Update representations
|
||||||
|
if (this.up == 0 || this.total == 0) {
|
||||||
|
this.percentageGood = 0;
|
||||||
|
} else {
|
||||||
|
this.percentageGood = Math.round((this.up / this.total) * 100);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Status flag
|
||||||
|
if (this.up == 0 && this.down == 0) {
|
||||||
|
this.status = false;
|
||||||
|
} else if (this.down == this.total) {
|
||||||
|
this.status = "bad";
|
||||||
|
} else if (this.up == this.total) {
|
||||||
|
this.status = "good";
|
||||||
|
} else {
|
||||||
|
this.status = "warn";
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((e) => {
|
||||||
|
console.error(e);
|
||||||
|
});
|
||||||
|
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.status {
|
||||||
|
font-size: 0.8rem;
|
||||||
|
color: var(--text-title);
|
||||||
|
&.good:before {
|
||||||
|
background-color: #94e185;
|
||||||
|
border-color: #78d965;
|
||||||
|
box-shadow: 0 0 5px 1px #94e185;
|
||||||
|
}
|
||||||
|
&.warn:before {
|
||||||
|
background-color: #f8a306;
|
||||||
|
border-color: #e1b35e;
|
||||||
|
box-shadow: 0 0 5px 1px #f8a306;
|
||||||
|
}
|
||||||
|
&.bad:before {
|
||||||
|
background-color: #c9404d;
|
||||||
|
border-color: #c42c3b;
|
||||||
|
box-shadow: 0 0 5px 1px #c9404d;
|
||||||
|
}
|
||||||
|
&:before {
|
||||||
|
content: " ";
|
||||||
|
display: inline-block;
|
||||||
|
width: 7px;
|
||||||
|
height: 7px;
|
||||||
|
margin-right: 10px;
|
||||||
|
border: 1px solid #000;
|
||||||
|
border-radius: 7px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
Loading…
Reference in New Issue