mirror of
https://github.com/yusing/godoxy.git
synced 2026-03-13 13:45:21 +01:00
Add context parameter to TCP/UDP stream health checks and client constructors for proper cancellation and deadline propagation. Switch from encoding/json to sonic for faster JSON unmarshaling. Standardize HTTP client timeouts to 5 seconds across agent pool and health check.
Health Check Package
Low-level health check implementations for different protocols and services in GoDoxy.
Overview
Purpose
This package provides health check implementations for various protocols:
- HTTP/HTTPS - Standard HTTP health checks with fasthttp
- H2C - HTTP/2 cleartext health checks
- Docker - Container health status via Docker API
- FileServer - Directory accessibility checks
- Stream - Generic network connection checks
Primary Consumers
internal/health/monitor/- Route health monitoringinternal/metrics/uptime/- Uptime poller integration
Non-goals
- Complex health check logic (response body validation, etc.)
- Authentication/authorization in health checks
- Multi-step health checks (login then check)
Stability
Internal package. Public functions are stable but may be extended with new parameters.
Public API
HTTP Health Check (http.go)
func HTTP(
url *url.URL,
method string,
path string,
timeout time.Duration,
) (types.HealthCheckResult, error)
H2C Health Check (http.go)
func H2C(
ctx context.Context,
url *url.URL,
method string,
path string,
timeout time.Duration,
) (types.HealthCheckResult, error)
Docker Health Check (docker.go)
func Docker(
ctx context.Context,
containerID string,
) (types.HealthCheckResult, error)
FileServer Health Check (fileserver.go)
func FileServer(
url *url.URL,
) (types.HealthCheckResult, error)
Stream Health Check (stream.go)
func Stream(
url *url.URL,
) (types.HealthCheckResult, error)
Common Types (internal/types/)
type HealthCheckResult struct {
Healthy bool
Latency time.Duration
Detail string
}
type HealthStatus int
const (
StatusHealthy HealthStatus = 0
StatusUnhealthy HealthStatus = 1
StatusError HealthStatus = 2
)
Architecture
HTTP Health Check Flow
flowchart TD
A[HTTP Health Check] --> B[Create FastHTTP Request]
B --> C[Set Headers and Method]
C --> D[Execute Request with Timeout]
D --> E{Request Successful?}
E -->|no| F{Error Type}
F -->|TLS Error| G[Healthy: TLS Error Ignored]
F -->|Other Error| H[Unhealthy: Error Details]
E -->|yes| I{Status Code}
I -->|5xx| J[Unhealthy: Server Error]
I -->|Other| K[Healthy]
G --> L[Return Result with Latency]
H --> L
J --> L
K --> L
Docker Health Check Flow
flowchart TD
A[Docker Health Check] --> B{Docker Failures > Threshold?}
B -->|yes| C[Return Error: Too Many Failures]
B -->|no| D[Container Inspect API Call]
D --> E{Inspect Successful?}
E -->|no| F[Increment Failure Count]
E -->|yes| G[Parse Container State]
G --> H{Container Status}
H -->|dead/exited/paused/restarting/removing| I[Unhealthy: Container State]
H -->|created| J[Unhealthy: Not Started]
H -->|running| K{Health Check Configured?}
K -->|no| L[Return Error: No Health Check]
K -->|yes| M[Check Health Status]
M --> N{Health Status}
N -->|healthy| O[Healthy]
N -->|unhealthy| P[Unhealthy: Last Log Output]
I --> Q[Reset Failure Count]
J --> Q
O --> Q
P --> Q
H2C Health Check Flow
flowchart TD
A[H2C Health Check] --> B[Create HTTP/2 Transport]
B --> C[Set AllowHTTP: true]
C --> D[Create HTTP Request]
D --> E[Set Headers and Method]
E --> F[Execute Request with Timeout]
F --> G{Request Successful?}
G -->|no| H[Unhealthy: Error Details]
G -->|yes| I[Check Status Code]
I --> J{Status Code}
J -->|5xx| K[Unhealthy: Server Error]
J -->|Other| L[Healthy]
H --> M[Return Result with Latency]
K --> M
L --> M
FileServer Health Check Flow
flowchart TD
A[FileServer Health Check] --> B[Start Timer]
B --> C[Stat Directory Path]
C --> D{Directory Exists?}
D -->|no| E[Unhealthy: Path Not Found]
D -->|yes| F[Healthy: Directory Accessible]
D -->|error| G[Return Error]
E --> H[Return Result with Latency]
F --> H
G --> I[Return Error]
Stream Health Check Flow
flowchart TD
A[Stream Health Check] --> B[Create Dialer]
B --> C[Set Timeout and Fallback Delay]
C --> D[Start Timer]
D --> E[Dial Network Connection]
E --> F{Connection Successful?}
F -->|no| G{Error Type}
G -->|Connection Errors| H[Unhealthy: Connection Failed]
G -->|Other Error| I[Return Error]
F -->|yes| J[Close Connection]
J --> K[Healthy: Connection Established]
H --> L[Return Result with Latency]
K --> L
Configuration Surface
No explicit configuration per health check. Parameters are passed directly:
| Check Type | Parameters |
|---|---|
| HTTP | URL, Method, Path, Timeout |
| H2C | Context, URL, Method, Path, Timeout |
| Docker | Context, ContainerID |
| FileServer | URL (path component used) |
| Stream | URL (scheme, host, port used) |
HTTP Headers
All HTTP/H2C checks set:
User-Agent: GoDoxy/<version>Accept: text/plain,text/html,*/*;q=0.8Accept-Encoding: identityCache-Control: no-cachePragma: no-cache
Dependency and Integration Map
External Dependencies
github.com/valyala/fasthttp- High-performance HTTP clientgolang.org/x/net/http2- HTTP/2 transport- Docker socket (for Docker health check)
Internal Dependencies
internal/types/- Health check result typesgoutils/version/- User-Agent version
Observability
Logs
No direct logging in health check implementations. Errors are returned as part of HealthCheckResult.Detail.
Metrics
- Check latency (returned in result)
- Success/failure rates (tracked by caller)
Security Considerations
- TLS certificate verification skipped (
InsecureSkipVerify: true) - Docker socket access required for Docker health check
- No authentication in health check requests
- User-Agent identifies GoDoxy for server-side filtering
Failure Modes and Recovery
HTTP/H2C
| Failure Mode | Result | Notes |
|---|---|---|
| Connection timeout | Unhealthy | Detail: timeout message |
| TLS certificate error | Healthy | Handled gracefully |
| 5xx response | Unhealthy | Detail: status text |
| 4xx response | Healthy | Client error considered healthy |
Docker
| Failure Mode | Result | Notes |
|---|---|---|
| API call failure | Error | Throws error to caller |
| Container not running | Unhealthy | State: "Not Started" |
| Container dead/exited | Unhealthy | State logged |
| No health check configured | Error | Requires health check in image |
FileServer
| Failure Mode | Result | Notes |
|---|---|---|
| Path not found | Unhealthy | Detail: "path not found" |
| Permission denied | Error | Returned to caller |
| Other OS error | Error | Returned to caller |
Stream
| Failure Mode | Result | Notes |
|---|---|---|
| Connection refused | Unhealthy | Detail: error message |
| Network unreachable | Unhealthy | Detail: error message |
| DNS resolution failure | Unhealthy | Detail: error message |
| Context deadline | Unhealthy | Detail: timeout |
Usage Examples
HTTP Health Check
url, _ := url.Parse("http://localhost:8080/health")
result, err := healthcheck.HTTP(url, "GET", "/health", 10*time.Second)
if err != nil {
fmt.Printf("Error: %v\n", err)
}
fmt.Printf("Healthy: %v, Latency: %v, Detail: %s\n",
result.Healthy, result.Latency, result.Detail)
H2C Health Check
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
url, _ := url.Parse("h2c://localhost:8080")
result, err := healthcheck.H2C(ctx, url, "GET", "/health", 10*time.Second)
Docker Health Check
ctx := context.Background()
result, err := healthcheck.Docker(ctx, "abc123def456")
FileServer Health Check
url, _ := url.Parse("file:///var/www/html")
result, err := healthcheck.FileServer(url)
Stream Health Check
url, _ := url.Parse("tcp://localhost:5432")
result, err := healthcheck.Stream(url)
Testing Notes
- Unit tests for each health check type
- Mock Docker server for Docker health check tests
- Integration tests require running services
- Timeout handling tests