Building Robust Health Checks in Go
Health checks are crucial for modern applications, allowing monitoring systems to determine the operational status of a service. This challenge asks you to implement a simple HTTP health check endpoint in Go that verifies basic dependencies and returns appropriate status codes based on their availability. Successfully completing this challenge demonstrates understanding of HTTP handlers, error handling, and basic dependency checks.
Problem Description
You need to create a Go program that exposes an HTTP endpoint /health. This endpoint should perform the following checks:
- Database Connection: Attempt to connect to a database (simulated for this challenge - see "Notes" for details). Assume a database connection is successful if a connection can be established (even if no data is read).
- External Service Availability: Attempt to make a simple HTTP request to a predefined external service (simulated for this challenge - see "Notes" for details). Assume the external service is available if the HTTP request returns a status code in the 200-299 range.
- System Resources: Check if the system has at least 50% free disk space.
The /health endpoint should return the following HTTP status codes:
- 200 OK: All checks pass.
- 500 Internal Server Error: At least one check fails. The response body should contain a JSON object with a
messagefield describing the failure.
Examples
Example 1:
Input: All checks pass (database connection successful, external service available, sufficient disk space)
Output: HTTP 200 OK
Explanation: All dependencies are healthy, so the endpoint returns a success status.
Example 2:
Input: Database connection fails.
Output: HTTP 500 Internal Server Error
Response Body: {"message": "Database connection failed"}
Explanation: The database check failed, triggering a 500 error with a descriptive message.
Example 3:
Input: External service returns a 404 Not Found.
Output: HTTP 500 Internal Server Error
Response Body: {"message": "External service unavailable"}
Explanation: The external service check failed, triggering a 500 error.
Example 4:
Input: Disk space is below 50%.
Output: HTTP 500 Internal Server Error
Response Body: {"message": "Insufficient disk space"}
Explanation: The disk space check failed, triggering a 500 error.
Constraints
- The program must listen on port 8080.
- The external service URL is fixed:
https://httpstat.us/200(for success) andhttps://httpstat.us/404(for failure). You should use these URLs for simulation. - The database connection simulation should return an error if a connection cannot be established.
- Disk space check should use
os.Statandos.Statfsto determine free space. - The response body for 500 errors must be valid JSON.
- The program should handle potential errors gracefully and avoid panics.
Notes
- Database Connection Simulation: For simplicity, simulate the database connection by attempting to open a connection to a non-existent database. Return an error if the connection fails. You can use
database/sqlpackage but don't need to actually connect to a real database. The goal is to demonstrate error handling. - External Service Simulation: Use the
net/httppackage to make a GET request to the specified external service URL. Check the HTTP status code to determine availability. - Disk Space Check: Use the
ospackage to get disk space information. Calculate the percentage of free disk space and compare it to 50%. - JSON Encoding: Use the
encoding/jsonpackage to encode the error message into a JSON response. - Focus on clear error handling and informative error messages. The code should be readable and well-structured. No external dependencies beyond the Go standard library are allowed.