mirror of
https://github.com/TwiN/gatus.git
synced 2024-11-24 17:04:42 +01:00
feat: shields.io endpoint badge (#652)
* feat: shields.io endpoint badge Signed-off-by: Steven Kreitzer <skre@skre.me> * chore: update readme to include new shields.io badge Signed-off-by: Steven Kreitzer <skre@skre.me> --------- Signed-off-by: Steven Kreitzer <skre@skre.me> Co-authored-by: TwiN <twin@linux.com>
This commit is contained in:
parent
1a7aeb5b35
commit
6cbc59b0e8
20
README.md
20
README.md
@ -107,6 +107,7 @@ Have any feedback or questions? [Create a discussion](https://github.com/TwiN/ga
|
|||||||
- [Badges](#badges)
|
- [Badges](#badges)
|
||||||
- [Uptime](#uptime)
|
- [Uptime](#uptime)
|
||||||
- [Health](#health)
|
- [Health](#health)
|
||||||
|
- [Health (Shields.io)](#health-shieldsio)
|
||||||
- [Response time](#response-time)
|
- [Response time](#response-time)
|
||||||
- [How to change the color thresholds of the response time badge](#how-to-change-the-color-thresholds-of-the-response-time-badge)
|
- [How to change the color thresholds of the response time badge](#how-to-change-the-color-thresholds-of-the-response-time-badge)
|
||||||
- [API](#api)
|
- [API](#api)
|
||||||
@ -1958,6 +1959,25 @@ https://example.com/api/v1/endpoints/core_frontend/health/badge.svg
|
|||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
#### Health (Shields.io)
|
||||||
|
![Health](https://img.shields.io/endpoint?url=https%3A%2F%2Fstatus.twin.sh%2Fapi%2Fv1%2Fendpoints%2Fcore_blog-external%2Fhealth%2Fbadge.shields)
|
||||||
|
|
||||||
|
The path to generate a badge is the following:
|
||||||
|
```
|
||||||
|
/api/v1/endpoints/{key}/health/badge.shields
|
||||||
|
```
|
||||||
|
Where:
|
||||||
|
- `{key}` has the pattern `<GROUP_NAME>_<ENDPOINT_NAME>` in which both variables have ` `, `/`, `_`, `,` and `.` replaced by `-`.
|
||||||
|
|
||||||
|
For instance, if you want the current status of the endpoint `frontend` in the group `core`,
|
||||||
|
the URL would look like this:
|
||||||
|
```
|
||||||
|
https://example.com/api/v1/endpoints/core_frontend/health/badge.shields
|
||||||
|
```
|
||||||
|
|
||||||
|
See more information about the Shields.io badge endpoint [here](https://shields.io/badges/endpoint-badge).
|
||||||
|
|
||||||
|
|
||||||
#### Response time
|
#### Response time
|
||||||
![Response time 1h](https://status.twin.sh/api/v1/endpoints/core_blog-external/response-times/1h/badge.svg)
|
![Response time 1h](https://status.twin.sh/api/v1/endpoints/core_blog-external/response-times/1h/badge.svg)
|
||||||
![Response time 24h](https://status.twin.sh/api/v1/endpoints/core_blog-external/response-times/24h/badge.svg)
|
![Response time 24h](https://status.twin.sh/api/v1/endpoints/core_blog-external/response-times/24h/badge.svg)
|
||||||
|
@ -66,6 +66,7 @@ func (a *API) createRouter(cfg *config.Config) *fiber.App {
|
|||||||
unprotectedAPIRouter := apiRouter.Group("/")
|
unprotectedAPIRouter := apiRouter.Group("/")
|
||||||
unprotectedAPIRouter.Get("/v1/config", ConfigHandler{securityConfig: cfg.Security}.GetConfig)
|
unprotectedAPIRouter.Get("/v1/config", ConfigHandler{securityConfig: cfg.Security}.GetConfig)
|
||||||
unprotectedAPIRouter.Get("/v1/endpoints/:key/health/badge.svg", HealthBadge)
|
unprotectedAPIRouter.Get("/v1/endpoints/:key/health/badge.svg", HealthBadge)
|
||||||
|
unprotectedAPIRouter.Get("/v1/endpoints/:key/health/badge.shields", HealthBadgeShields)
|
||||||
unprotectedAPIRouter.Get("/v1/endpoints/:key/uptimes/:duration/badge.svg", UptimeBadge)
|
unprotectedAPIRouter.Get("/v1/endpoints/:key/uptimes/:duration/badge.svg", UptimeBadge)
|
||||||
unprotectedAPIRouter.Get("/v1/endpoints/:key/response-times/:duration/badge.svg", ResponseTimeBadge(cfg))
|
unprotectedAPIRouter.Get("/v1/endpoints/:key/response-times/:duration/badge.svg", ResponseTimeBadge(cfg))
|
||||||
unprotectedAPIRouter.Get("/v1/endpoints/:key/response-times/:duration/chart.svg", ResponseTimeChart)
|
unprotectedAPIRouter.Get("/v1/endpoints/:key/response-times/:duration/chart.svg", ResponseTimeChart)
|
||||||
|
51
api/badge.go
51
api/badge.go
@ -1,6 +1,7 @@
|
|||||||
package api
|
package api
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
@ -125,6 +126,36 @@ func HealthBadge(c *fiber.Ctx) error {
|
|||||||
return c.Status(200).Send(generateHealthBadgeSVG(healthStatus))
|
return c.Status(200).Send(generateHealthBadgeSVG(healthStatus))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func HealthBadgeShields(c *fiber.Ctx) error {
|
||||||
|
key := c.Params("key")
|
||||||
|
pagingConfig := paging.NewEndpointStatusParams()
|
||||||
|
status, err := store.Get().GetEndpointStatusByKey(key, pagingConfig.WithResults(1, 1))
|
||||||
|
if err != nil {
|
||||||
|
if err == common.ErrEndpointNotFound {
|
||||||
|
return c.Status(404).SendString(err.Error())
|
||||||
|
} else if err == common.ErrInvalidTimeRange {
|
||||||
|
return c.Status(400).SendString(err.Error())
|
||||||
|
}
|
||||||
|
return c.Status(500).SendString(err.Error())
|
||||||
|
}
|
||||||
|
healthStatus := HealthStatusUnknown
|
||||||
|
if len(status.Results) > 0 {
|
||||||
|
if status.Results[0].Success {
|
||||||
|
healthStatus = HealthStatusUp
|
||||||
|
} else {
|
||||||
|
healthStatus = HealthStatusDown
|
||||||
|
}
|
||||||
|
}
|
||||||
|
c.Set("Content-Type", "application/json")
|
||||||
|
c.Set("Cache-Control", "no-cache, no-store, must-revalidate")
|
||||||
|
c.Set("Expires", "0")
|
||||||
|
jsonData, err := generateHealthBadgeShields(healthStatus)
|
||||||
|
if err != nil {
|
||||||
|
return c.Status(500).SendString(err.Error())
|
||||||
|
}
|
||||||
|
return c.Status(200).Send(jsonData)
|
||||||
|
}
|
||||||
|
|
||||||
func generateUptimeBadgeSVG(duration string, uptime float64) []byte {
|
func generateUptimeBadgeSVG(duration string, uptime float64) []byte {
|
||||||
var labelWidth, valueWidth, valueWidthAdjustment int
|
var labelWidth, valueWidth, valueWidthAdjustment int
|
||||||
switch duration {
|
switch duration {
|
||||||
@ -299,6 +330,17 @@ func generateHealthBadgeSVG(healthStatus string) []byte {
|
|||||||
return svg
|
return svg
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func generateHealthBadgeShields(healthStatus string) ([]byte, error) {
|
||||||
|
color := getBadgeShieldsColorFromHealth(healthStatus)
|
||||||
|
data := map[string]interface{}{
|
||||||
|
"schemaVersion": 1,
|
||||||
|
"label": "gatus",
|
||||||
|
"message": healthStatus,
|
||||||
|
"color": color,
|
||||||
|
}
|
||||||
|
return json.Marshal(data)
|
||||||
|
}
|
||||||
|
|
||||||
func getBadgeColorFromHealth(healthStatus string) string {
|
func getBadgeColorFromHealth(healthStatus string) string {
|
||||||
if healthStatus == HealthStatusUp {
|
if healthStatus == HealthStatusUp {
|
||||||
return badgeColorHexAwesome
|
return badgeColorHexAwesome
|
||||||
@ -307,3 +349,12 @@ func getBadgeColorFromHealth(healthStatus string) string {
|
|||||||
}
|
}
|
||||||
return badgeColorHexPassable
|
return badgeColorHexPassable
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getBadgeShieldsColorFromHealth(healthStatus string) string {
|
||||||
|
if healthStatus == HealthStatusUp {
|
||||||
|
return "brightgreen"
|
||||||
|
} else if healthStatus == HealthStatusDown {
|
||||||
|
return "red"
|
||||||
|
}
|
||||||
|
return "yellow"
|
||||||
|
}
|
||||||
|
@ -110,6 +110,21 @@ func TestBadge(t *testing.T) {
|
|||||||
Path: "/api/v1/endpoints/invalid_key/health/badge.svg",
|
Path: "/api/v1/endpoints/invalid_key/health/badge.svg",
|
||||||
ExpectedCode: http.StatusNotFound,
|
ExpectedCode: http.StatusNotFound,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
Name: "badge-shields-health-up",
|
||||||
|
Path: "/api/v1/endpoints/core_frontend/health/badge.shields",
|
||||||
|
ExpectedCode: http.StatusOK,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "badge-shields-health-down",
|
||||||
|
Path: "/api/v1/endpoints/core_backend/health/badge.shields",
|
||||||
|
ExpectedCode: http.StatusOK,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "badge-shields-health-for-invalid-key",
|
||||||
|
Path: "/api/v1/endpoints/invalid_key/health/badge.shields",
|
||||||
|
ExpectedCode: http.StatusNotFound,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
Name: "chart-response-time-24h",
|
Name: "chart-response-time-24h",
|
||||||
Path: "/api/v1/endpoints/core_backend/response-times/24h/chart.svg",
|
Path: "/api/v1/endpoints/core_backend/response-times/24h/chart.svg",
|
||||||
|
Loading…
Reference in New Issue
Block a user