Status: latency the panel can actually show
PocketBase and the Web App share a Docker network and answer a health probe in well under a millisecond. Milliseconds() truncated that to 0, and omitempty on an int64 dropped the zero from the JSON, so the panel saw no latencyMs at all and rendered an em dash. Latency is now a *float64 rounded to one decimal, computed from Microseconds(). The pointer keeps an absent measurement — the API Server row, which probes nothing — distinct from a genuinely fast one. pbProbe follows suit, since it copies straight off svcHealth. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
f08849e50c
commit
3c4eba87c8
@@ -18,7 +18,7 @@ import (
|
|||||||
type pbProbe struct {
|
type pbProbe struct {
|
||||||
Reachable bool `json:"reachable"`
|
Reachable bool `json:"reachable"`
|
||||||
HTTPStatus int `json:"httpStatus,omitempty"`
|
HTTPStatus int `json:"httpStatus,omitempty"`
|
||||||
LatencyMs int64 `json:"latencyMs,omitempty"`
|
LatencyMs *float64 `json:"latencyMs,omitempty"`
|
||||||
Superuser bool `json:"superuser"`
|
Superuser bool `json:"superuser"`
|
||||||
Detail string `json:"detail,omitempty"`
|
Detail string `json:"detail,omitempty"`
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package api
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"io"
|
"io"
|
||||||
|
"math"
|
||||||
"net/http"
|
"net/http"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
@@ -11,12 +12,21 @@ import (
|
|||||||
// svcHealth is the health of one upstream service, as shown on the panel.
|
// svcHealth is the health of one upstream service, as shown on the panel.
|
||||||
type svcHealth struct {
|
type svcHealth struct {
|
||||||
Status string `json:"status"` // "ok" | "down"
|
Status string `json:"status"` // "ok" | "down"
|
||||||
LatencyMs int64 `json:"latencyMs,omitempty"`
|
|
||||||
HTTPStatus int `json:"httpStatus,omitempty"`
|
HTTPStatus int `json:"httpStatus,omitempty"`
|
||||||
URL string `json:"url,omitempty"`
|
URL string `json:"url,omitempty"`
|
||||||
|
// Fractional, and a pointer so an absent measurement (this process) stays
|
||||||
|
// distinguishable from a genuinely fast one: neighbours sharing a Docker
|
||||||
|
// network answer in well under a millisecond.
|
||||||
|
LatencyMs *float64 `json:"latencyMs,omitempty"`
|
||||||
Error string `json:"error,omitempty"`
|
Error string `json:"error,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// latencyMs is elapsed time in milliseconds, kept to one decimal.
|
||||||
|
func latencyMs(d time.Duration) *float64 {
|
||||||
|
ms := math.Round(float64(d.Microseconds())/100) / 10
|
||||||
|
return &ms
|
||||||
|
}
|
||||||
|
|
||||||
// healthClient is a short-timeout client for probing upstreams so a hung
|
// healthClient is a short-timeout client for probing upstreams so a hung
|
||||||
// dependency can't stall the status endpoint.
|
// dependency can't stall the status endpoint.
|
||||||
var healthClient = &http.Client{Timeout: 4 * time.Second}
|
var healthClient = &http.Client{Timeout: 4 * time.Second}
|
||||||
@@ -29,7 +39,7 @@ func probe(ctx context.Context, url string) svcHealth {
|
|||||||
return svcHealth{Status: "down", URL: url, Error: err.Error()}
|
return svcHealth{Status: "down", URL: url, Error: err.Error()}
|
||||||
}
|
}
|
||||||
resp, err := healthClient.Do(req)
|
resp, err := healthClient.Do(req)
|
||||||
lat := time.Since(start).Milliseconds()
|
lat := latencyMs(time.Since(start))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return svcHealth{Status: "down", URL: url, LatencyMs: lat, Error: err.Error()}
|
return svcHealth{Status: "down", URL: url, LatencyMs: lat, Error: err.Error()}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user