Something went wrong. Try again.
[READ-ONLY] Mirror of https://github.com/openstatusHQ/openstatus. ๐ซ Status page with uptime monitoring & API monitoring as code ๐ซ openstatus.dev
bun drizzle-orm monitoring monitoring-as-code nextjs observability on-call open-source shadcn-ui status-page statuspage synthetic-monitoring tinybird turso uptime uptime-checker uptime-monitor
Something went wrong. Try again.
4.1 kB ยท 155 lines
Go
at incident-api
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156package handlers
import ( "encoding/json" "fmt" "net/http" "time"
"github.com/cenkalti/backoff/v5" "github.com/gin-gonic/gin" "github.com/openstatushq/openstatus/apps/checker/checker" "github.com/openstatushq/openstatus/apps/checker/request" "github.com/rs/zerolog/log")
type PingResponse struct { Body string `json:"body,omitempty"` Headers string `json:"headers,omitempty"` Region string `json:"region"` Timing string `json:"timing,omitempty"` RequestId int64 `json:"requestId,omitempty"` WorkspaceId int64 `json:"workspaceId,omitempty"` Latency int64 `json:"latency"` Timestamp int64 `json:"timestamp"` StatusCode int `json:"statusCode,omitempty"`}
type Response struct { Headers map[string]string `json:"headers,omitempty"` Error string `json:"error,omitempty"` Body string `json:"body,omitempty"` Region string `json:"region"` Tags []string `json:"tags,omitempty"` RequestId int64 `json:"requestId,omitempty"` WorkspaceId int64 `json:"workspaceId,omitempty"` Latency int64 `json:"latency"` Timestamp int64 `json:"timestamp"` Timing checker.Timing `json:"timing"` Status int `json:"status,omitempty"`}
func (h Handler) PingRegionHandler(c *gin.Context) { ctx := c.Request.Context()
dataSourceName := "check_response_http__v0" region := c.Param("region")
if region == "" { c.String(http.StatusBadRequest, "region is required")
return }
fmt.Printf("Start of /ping/%s\n", region)
if c.GetHeader("Authorization") != fmt.Sprintf("Basic %s", h.Secret) { c.JSON(http.StatusUnauthorized, gin.H{"error": "unauthorized"})
return }
if h.CloudProvider == "fly" { if region != h.Region { c.Header("fly-replay", fmt.Sprintf("region=%s", region)) c.String(http.StatusAccepted, "Forwarding request to %s", region)
return } }
// We need a new client for each request to avoid connection reuse. requestClient := &http.Client{ Timeout: 45 * time.Second, }
defer requestClient.CloseIdleConnections()
var req request.PingRequest if err := c.ShouldBindJSON(&req); err != nil { log.Ctx(ctx).Error().Err(err).Msg("failed to decode checker request") c.JSON(http.StatusBadRequest, gin.H{"error": "invalid request"})
return }
var res checker.Response
op := func() (struct{}, error) {
headers := make([]struct { Key string `json:"key"` Value string `json:"value"` }, 0)
for key, value := range req.Headers { headers = append(headers, struct { Key string `json:"key"` Value string `json:"value"` }{Key: key, Value: value}) }
input := request.HttpCheckerRequest{ Headers: headers, URL: req.URL, Method: req.Method, Body: req.Body, }
r, err := checker.Http(c.Request.Context(), requestClient, input)
if err != nil { return struct{}{}, fmt.Errorf("unable to ping: %w", err) }
timingAsString, err := json.Marshal(r.Timing) if err != nil { return struct{}{}, fmt.Errorf("error while parsing timing data %s: %w", req.URL, err) }
headersAsString, err := json.Marshal(r.Headers) if err != nil { return struct{}{}, nil }
tbData := PingResponse{ RequestId: req.RequestId, WorkspaceId: req.WorkspaceId, StatusCode: r.Status, Latency: r.Latency, Body: r.Body, Headers: string(headersAsString), Timestamp: r.Timestamp, Timing: string(timingAsString), Region: h.Region, }
res = r res.Region = h.Region
if tbData.RequestId != 0 { if err := h.TbClient.SendEvent(ctx, tbData, dataSourceName); err != nil { log.Ctx(ctx).Error().Err(err).Msg("failed to send event to tinybird") } }
return struct{}{}, nil } if _, err := backoff.Retry(ctx, op, backoff.WithBackOff(backoff.NewExponentialBackOff()), backoff.WithMaxTries(3)); err != nil { c.JSON(http.StatusOK, gin.H{"message": "url not reachable"})
return }
c.JSON(http.StatusOK, res)}