mirror of
https://github.com/TwiN/gatus.git
synced 2024-11-07 08:34:15 +01:00
59842d5e88
* feat(alerting): add support for including endpoint errors in custom alerts - Updated `buildHTTPRequest` method in `AlertProvider` to accept a `result` parameter. - Added support for including `[ENDPOINT_ERRORS]` in both the request body and URL, which will be replaced by the errors from `Result.Errors[]`. - Adjusted `CreateExternalEndpointResult` to capture and store errors from query parameters. - This allows custom alerts to include detailed error information, enhancing the flexibility of alert notifications. * feat: add ENDPOINT_ERRORS example * feat: add tests * Refactor: code review feedback * delete unsed errors * Update README.md * Apply suggestions from code review --------- Co-authored-by: raojinlin <raojinlin302@gmail.com> Co-authored-by: TwiN <twin@linux.com>
71 lines
2.7 KiB
Go
71 lines
2.7 KiB
Go
package api
|
|
|
|
import (
|
|
"errors"
|
|
"log"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/TwiN/gatus/v5/config"
|
|
"github.com/TwiN/gatus/v5/config/endpoint"
|
|
"github.com/TwiN/gatus/v5/storage/store"
|
|
"github.com/TwiN/gatus/v5/storage/store/common"
|
|
"github.com/TwiN/gatus/v5/watchdog"
|
|
"github.com/gofiber/fiber/v2"
|
|
)
|
|
|
|
func CreateExternalEndpointResult(cfg *config.Config) fiber.Handler {
|
|
return func(c *fiber.Ctx) error {
|
|
// Check if the success query parameter is present
|
|
success, exists := c.Queries()["success"]
|
|
if !exists || (success != "true" && success != "false") {
|
|
return c.Status(400).SendString("missing or invalid success query parameter")
|
|
}
|
|
// Check if the authorization bearer token header is correct
|
|
authorizationHeader := string(c.Request().Header.Peek("Authorization"))
|
|
if !strings.HasPrefix(authorizationHeader, "Bearer ") {
|
|
return c.Status(401).SendString("invalid Authorization header")
|
|
}
|
|
token := strings.TrimSpace(strings.TrimPrefix(authorizationHeader, "Bearer "))
|
|
if len(token) == 0 {
|
|
return c.Status(401).SendString("bearer token must not be empty")
|
|
}
|
|
key := c.Params("key")
|
|
externalEndpoint := cfg.GetExternalEndpointByKey(key)
|
|
if externalEndpoint == nil {
|
|
log.Printf("[api.CreateExternalEndpointResult] External endpoint with key=%s not found", key)
|
|
return c.Status(404).SendString("not found")
|
|
}
|
|
if externalEndpoint.Token != token {
|
|
log.Printf("[api.CreateExternalEndpointResult] Invalid token for external endpoint with key=%s", key)
|
|
return c.Status(401).SendString("invalid token")
|
|
}
|
|
// Persist the result in the storage
|
|
result := &endpoint.Result{
|
|
Timestamp: time.Now(),
|
|
Success: c.QueryBool("success"),
|
|
Errors: []string{},
|
|
}
|
|
if !result.Success && c.Query("error") != "" {
|
|
result.Errors = append(result.Errors, c.Query("error"))
|
|
}
|
|
convertedEndpoint := externalEndpoint.ToEndpoint()
|
|
if err := store.Get().Insert(convertedEndpoint, result); err != nil {
|
|
if errors.Is(err, common.ErrEndpointNotFound) {
|
|
return c.Status(404).SendString(err.Error())
|
|
}
|
|
log.Printf("[api.CreateExternalEndpointResult] Failed to insert result in storage: %s", err.Error())
|
|
return c.Status(500).SendString(err.Error())
|
|
}
|
|
log.Printf("[api.CreateExternalEndpointResult] Successfully inserted result for external endpoint with key=%s and success=%s", c.Params("key"), success)
|
|
// Check if an alert should be triggered or resolved
|
|
if !cfg.Maintenance.IsUnderMaintenance() {
|
|
watchdog.HandleAlerting(convertedEndpoint, result, cfg.Alerting, cfg.Debug)
|
|
externalEndpoint.NumberOfSuccessesInARow = convertedEndpoint.NumberOfSuccessesInARow
|
|
externalEndpoint.NumberOfFailuresInARow = convertedEndpoint.NumberOfFailuresInARow
|
|
}
|
|
// Return the result
|
|
return c.Status(200).SendString("")
|
|
}
|
|
}
|