A lightweight, zero-dependency Go SDK for interacting with Gatus status page APIs.
Lost? The CLI can be found at gatus-cli, while the main Gatus project is at gatus.
go get github.com/TwiN/gatus-sdk
No additional dependencies required! This SDK uses only the Go standard library.
package main
import (
"context"
"fmt"
"log"
gatus "github.com/TwiN/gatus-sdk"
)
func main() {
// Create a new client
client := gatus.NewClient("https://status.example.org")
// Get all endpoint statuses
statuses, err := client.GetAllEndpointStatuses(context.Background())
if err != nil {
log.Fatal(err)
}
for _, status := range statuses {
fmt.Printf("Endpoint: %s (Group: %s) - Key: %s\n", status.Name, status.Group, status.Key)
if len(status.Results) > 0 {
lastResult := status.Results[0]
fmt.Printf(" Status: %d, Success: %v\n", lastResult.Status, lastResult.Success)
}
}
}
// Create client with default settings
client := gatus.NewClient("https://status.example.com")
// Create client with custom timeout
client := gatus.NewClient("https://status.example.com", gatus.WithTimeout(10 * time.Second))
// Create client with custom user agent
client := gatus.NewClient("https://status.example.com", gatus.WithUserAgent("MyApp/1.0"))
// Create client with custom HTTP client
httpClient := &http.Client{
Timeout: 15 * time.Second,
Transport: &http.Transport{
MaxIdleConns: 50,
},
}
client := gatus.NewClient("https://status.example.com", gatus.WithHTTPClient(httpClient))
The SDK provides a utility function to generate endpoint keys in the format expected by Gatus:
// Generate a key for an endpoint
key := gatus.GenerateEndpointKey("core", "blog-home")
fmt.Println(key) // Output: core_blog-home
// Special characters are replaced with hyphens
key = gatus.GenerateEndpointKey("api/v1", "health_check.test")
fmt.Println(key) // Output: api-v1_health-check-test
// Empty group is handled
key = gatus.GenerateEndpointKey("", "standalone")
fmt.Println(key) // Output: _standalone
ctx := context.Background()
// Get all endpoint statuses
statuses, err := client.GetAllEndpointStatuses(ctx)
if err != nil {
log.Fatal(err)
}
// Get status by key
status, err := client.GetEndpointStatusByKey(ctx, "core_blog-home")
if err != nil {
log.Fatal(err)
}
// Get status by group and name (key is generated automatically)
status, err := client.GetEndpointStatus(ctx, "core", "blog-home")
if err != nil {
log.Fatal(err)
}
// Check if endpoint is healthy
if len(status.Results) > 0 && status.Results[0].Success {
fmt.Println("Endpoint is healthy")
}
// Get uptime percentage
uptime, err := client.GetEndpointUptime(ctx, "core_blog-home", "24h")
if err != nil {
log.Fatal(err)
}
fmt.Printf("Uptime: %.2f%%\n", uptime)
// Get detailed uptime data
uptimeData, err := client.GetEndpointUptimeData(ctx, "core_blog-home", "7d")
if err != nil {
log.Fatal(err)
}
fmt.Printf("Uptime: %.2f%% over %s\n", uptimeData.Uptime, uptimeData.Duration)
// Valid durations: 1h, 24h, 7d, 30d
err = gatus.ValidateDuration("24h") // Returns nil
err = gatus.ValidateDuration("48h") // Returns validation error
// Get response time statistics
respTimes, err := client.GetEndpointResponseTimes(ctx, "core_blog-home", "24h")
if err != nil {
log.Fatal(err)
}
// Convert nanoseconds to milliseconds for display
fmt.Printf("Response Times:\n")
fmt.Printf(" Average: %dms\n", respTimes.Average/1000000)
fmt.Printf(" Min: %dms\n", respTimes.Min/1000000)
fmt.Printf(" Max: %dms\n", respTimes.Max/1000000)
Generate badge URLs for embedding in documentation or dashboards:
key := "core_blog-home"
// Get uptime badge URL
uptimeBadgeURL := client.GetEndpointUptimeBadgeURL(key, "24h")
fmt.Printf("\n", uptimeBadgeURL)
// Get health badge URL
healthBadgeURL := client.GetEndpointHealthBadgeURL(key)
fmt.Printf("\n", healthBadgeURL)
// Get response time badge URL
respTimeBadgeURL := client.GetEndpointResponseTimeBadgeURL(key, "24h")
fmt.Printf("\n", respTimeBadgeURL)
Push monitoring results from external systems to Gatus:
// Generate key from group and name
key := gatus.GenerateEndpointKey("core", "ext-ep-test")
// Push successful result
err := client.PushExternalEndpointResult(ctx, key, "token", true, "", "10s")
// Push failed result
err = client.PushExternalEndpointResult(ctx, key, "token", false, "Connection timeout", "30s")
Requires external endpoints configured in Gatus. See docs.
package main
import (
"context"
"fmt"
"log"
"time"
gatus "github.com/TwiN/gatus-sdk"
)
func main() {
client := gatus.NewClient("https://status.example.org", gatus.WithTimeout(5 * time.Second))
ctx := context.Background()
// Define endpoints to monitor
endpoints := []struct {
Group string
Name string
}{
{"core", "blog-home"},
{"services", "api"},
{"databases", "postgres"},
}
for _, ep := range endpoints {
key := gatus.GenerateEndpointKey(ep.Group, ep.Name)
// Get status
status, err := client.GetEndpointStatusByKey(ctx, key)
if err != nil {
log.Printf("Error getting status for %s: %v", key, err)
continue
}
// Get uptime
uptime, err := client.GetEndpointUptime(ctx, key, "24h")
if err != nil {
log.Printf("Error getting uptime for %s: %v", key, err)
continue
}
// Get response times
respTimes, err := client.GetEndpointResponseTimes(ctx, key, "24h")
if err != nil {
log.Printf("Error getting response times for %s: %v", key, err)
continue
}
fmt.Printf("\nEndpoint: %s/%s\n", ep.Group, ep.Name)
fmt.Printf(" Key: %s\n", key)
fmt.Printf(" Uptime (24h): %.2f%%\n", uptime)
fmt.Printf(" Avg Response: %dms\n", respTimes.Average/1000000)
if len(status.Results) > 0 {
lastResult := status.Results[0]
fmt.Printf(" Last Check: %s\n", lastResult.Timestamp.Format(time.RFC3339))
fmt.Printf(" Status: %d\n", lastResult.Status)
fmt.Printf(" Success: %v\n", lastResult.Success)
if len(lastResult.Errors) > 0 {
fmt.Printf(" Errors: %v\n", lastResult.Errors)
}
}
}
}
package main
import (
"context"
"fmt"
"log"
"strings"
"time"
gatus "github.com/TwiN/gatus-sdk"
)
func main() {
client := gatus.NewClient("https://status.example.org")
ctx := context.Background()
// Get all endpoints
statuses, err := client.GetAllEndpointStatuses(ctx)
if err != nil {
log.Fatal(err)
}
// Generate markdown report
var report strings.Builder
report.WriteString("# Status Report\n\n")
report.WriteString(fmt.Sprintf("Generated: %s\n\n", time.Now().Format(time.RFC3339)))
// Group endpoints by group
groups := make(map[string][]gatus.EndpointStatus)
for _, status := range statuses {
groups[status.Group] = append(groups[status.Group], status)
}
for group, endpoints := range groups {
if group == "" {
report.WriteString("## Ungrouped\n\n")
} else {
report.WriteString(fmt.Sprintf("## %s\n\n", group))
}
report.WriteString("| Endpoint | Status | Uptime (24h) | Health |\n")
report.WriteString("|----------|--------|--------------|--------|\n")
for _, ep := range endpoints {
// Get uptime
uptime, _ := client.GetEndpointUptime(ctx, ep.Key, "24h")
// Determine health status
health := "π΄ Down"
if len(ep.Results) > 0 && ep.Results[0].Success {
if uptime >= 99.9 {
health = "π’ Healthy"
} else if uptime >= 95.0 {
health = "π‘ Degraded"
} else {
health = "π Issues"
}
}
// Get badge URLs
healthBadge := client.GetEndpointHealthBadgeURL(ep.Key)
uptimeBadge := client.GetEndpointUptimeBadgeURL(ep.Key, "24h")
report.WriteString(fmt.Sprintf("| %s |  |  | %s |\n", ep.Name, healthBadge, uptimeBadge, health))
}
report.WriteString("\n")
}
fmt.Println(report.String())
}
package main
import (
"context"
"fmt"
"log"
"time"
gatus "github.com/TwiN/gatus-sdk"
)
func main() {
client := gatus.NewClient("https://status.example.org")
// Create context with 2 second timeout
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
defer cancel()
// This will timeout if the request takes more than 2 seconds
statuses, err := client.GetAllEndpointStatuses(ctx)
if err != nil {
if ctx.Err() == context.DeadlineExceeded {
log.Fatal("Request timed out")
}
log.Fatal(err)
}
fmt.Printf("Retrieved %d endpoint statuses\n", len(statuses))
}
package main
import (
"context"
"errors"
"fmt"
"log"
gatus "github.com/TwiN/gatus-sdk"
)
func main() {
client := gatus.NewClient("https://status.example.org")
ctx := context.Background()
// Try to get a non-existent endpoint
status, err := client.GetEndpointStatusByKey(ctx, "nonexistent_endpoint")
if err != nil {
// Check for specific error types
var apiErr *gatus.APIError
if errors.As(err, &apiErr) {
fmt.Printf("API Error: Status %d - %s\n", apiErr.StatusCode, apiErr.Message)
if apiErr.Body != "" {
fmt.Printf("Response body: %s\n", apiErr.Body)
}
return
}
var valErr *gatus.ValidationError
if errors.As(err, &valErr) {
fmt.Printf("Validation Error: Field '%s' - %s\n", valErr.Field, valErr.Message)
return
}
// Other error
log.Fatal(err)
}
fmt.Printf("Endpoint: %s\n", status.Name)
}
Run tests with coverage:
# Run all tests
go test ./...
# Run with coverage
go test -cover ./...
# Generate coverage report
go test -coverprofile=coverage.out ./...
go tool cover -html=coverage.out
# Run with race detection
go test -race ./...
# Run specific tests
go test -run TestGenerateEndpointKey ./...
# Verbose output
go test -v ./...