Serve Prometheus metrics at /metrics behind basic auth (closes #94)
check / check (push) Successful in 3m17s
check / check (push) Successful in 3m17s
With METRICS_USERNAME and METRICS_PASSWORD both set, the backend records request metrics through go-http-metrics in a registry of its own, with Go's runtime and process metrics, and serves them at GET /metrics behind basic auth with those credentials; nginx passes /metrics to it. With neither set there is no such route; one alone stops the start with an error naming both. Only requests that reach the health check or POST /api/v1/reports are recorded, not every request as the conventions show: the labels are path and method, which clients can make up without end. So POST /api/v1/reports is registered by its full path, not inside a route group. Deviation: go get and go mod tidy ran directly; no entrypoint adds a Go dependency yet (#45). Model: opus-5-5
This commit is contained in:
@@ -44,6 +44,11 @@ var (
|
||||
errNotPort = errors.New("must be a port number, 1 to 65535")
|
||||
errNotBool = errors.New("must be true or false")
|
||||
errNotIP = errors.New("must be an IP address, or empty")
|
||||
|
||||
errMetricsCredentials = errors.New(
|
||||
"METRICS_USERNAME and METRICS_PASSWORD must be set together, " +
|
||||
"or neither",
|
||||
)
|
||||
)
|
||||
|
||||
// Params defines the dependencies for Config.
|
||||
@@ -178,6 +183,12 @@ func (s *Config) check() error {
|
||||
}
|
||||
}
|
||||
|
||||
// The server records and serves metrics only with both set, so
|
||||
// one alone is a mistake that would otherwise go unnoticed.
|
||||
if (s.MetricsUsername == "") != (s.MetricsPassword == "") {
|
||||
return errMetricsCredentials
|
||||
}
|
||||
|
||||
return checkOrigins(s.CORSAllowedOrigins)
|
||||
}
|
||||
|
||||
|
||||
@@ -103,6 +103,22 @@ func TestDataDirMaxBytesMustBeANumber(t *testing.T) {
|
||||
requireConfigError(t, "DATA_DIR_MAX_BYTES")
|
||||
}
|
||||
|
||||
// TestMetricsCredentialsGoTogether: with only one of the two set, the
|
||||
// server would quietly serve no metrics, so the start fails, naming
|
||||
// both.
|
||||
func TestMetricsCredentialsGoTogether(t *testing.T) {
|
||||
for _, set := range []string{"METRICS_USERNAME", "METRICS_PASSWORD"} {
|
||||
t.Run(set, func(t *testing.T) {
|
||||
t.Setenv("METRICS_USERNAME", "")
|
||||
t.Setenv("METRICS_PASSWORD", "")
|
||||
t.Setenv(set, "prometheus")
|
||||
|
||||
requireConfigError(t, "METRICS_USERNAME")
|
||||
requireConfigError(t, "METRICS_PASSWORD")
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// TestCORSAllowedOriginsMustBeOrigins: "*" would let every origin in,
|
||||
// and an entry that is not a plain origin would match no page.
|
||||
func TestCORSAllowedOriginsMustBeOrigins(t *testing.T) {
|
||||
|
||||
Reference in New Issue
Block a user