mirror of
https://github.com/yusing/godoxy.git
synced 2026-03-29 13:21:55 +02:00
354 lines
8.8 KiB
Markdown
354 lines
8.8 KiB
Markdown
# 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 monitoring
|
|
- `internal/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`)
|
|
|
|
```go
|
|
func HTTP(
|
|
url *url.URL,
|
|
method string,
|
|
path string,
|
|
timeout time.Duration,
|
|
) (types.HealthCheckResult, error)
|
|
```
|
|
|
|
### H2C Health Check (`http.go`)
|
|
|
|
```go
|
|
func H2C(
|
|
ctx context.Context,
|
|
url *url.URL,
|
|
method string,
|
|
path string,
|
|
timeout time.Duration,
|
|
) (types.HealthCheckResult, error)
|
|
```
|
|
|
|
### Docker Health Check (`docker.go`)
|
|
|
|
```go
|
|
func Docker(
|
|
ctx context.Context,
|
|
containerID string,
|
|
) (types.HealthCheckResult, error)
|
|
```
|
|
|
|
### FileServer Health Check (`fileserver.go`)
|
|
|
|
```go
|
|
func FileServer(
|
|
url *url.URL,
|
|
) (types.HealthCheckResult, error)
|
|
```
|
|
|
|
### Stream Health Check (`stream.go`)
|
|
|
|
```go
|
|
func Stream(
|
|
url *url.URL,
|
|
) (types.HealthCheckResult, error)
|
|
```
|
|
|
|
### Common Types (`internal/types/`)
|
|
|
|
```go
|
|
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
|
|
|
|
```mermaid
|
|
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
|
|
|
|
```mermaid
|
|
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
|
|
|
|
```mermaid
|
|
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
|
|
|
|
```mermaid
|
|
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
|
|
|
|
```mermaid
|
|
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.8`
|
|
- `Accept-Encoding: identity`
|
|
- `Cache-Control: no-cache`
|
|
- `Pragma: no-cache`
|
|
|
|
## Dependency and Integration Map
|
|
|
|
### External Dependencies
|
|
|
|
- `github.com/valyala/fasthttp` - High-performance HTTP client
|
|
- `golang.org/x/net/http2` - HTTP/2 transport
|
|
- Docker socket (for Docker health check)
|
|
|
|
### Internal Dependencies
|
|
|
|
- `internal/types/` - Health check result types
|
|
- `goutils/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
|
|
|
|
```go
|
|
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
|
|
|
|
```go
|
|
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
|
|
|
|
```go
|
|
ctx := context.Background()
|
|
result, err := healthcheck.Docker(ctx, "abc123def456")
|
|
```
|
|
|
|
### FileServer Health Check
|
|
|
|
```go
|
|
url, _ := url.Parse("file:///var/www/html")
|
|
result, err := healthcheck.FileServer(url)
|
|
```
|
|
|
|
### Stream Health Check
|
|
|
|
```go
|
|
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
|