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)
|
||||
- [Emby / Jellyfin](#emby--jellyfin)
|
||||
- [FreshRSS](#freshrss)
|
||||
- [Gatus](#gatus)
|
||||
- [Gitea / Forgejo](#gitea--forgejo)
|
||||
- [Glances](#glances)
|
||||
- [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
|
||||
```
|
||||
|
||||
## 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
|
||||
|
||||
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