- embedded React admin UI at /admin/ui (go:embed), login with ADMIN_SECRET via signed HttpOnly session cookie, X-ADMIN-KEY still works for scripts - admin API: overview stats, indexing queue, addon management (priority, reindex, delete/restore/purge, bulk), whitelist CRUD, duplicate hashes, traffic, metrics explorer, services, events/audit log, system info - built-in metrics: request latency per route, visitors, top addons and searches, indexer/scraper counters; minute buckets in the DB with hourly rollups and retention; optional Prometheus /metrics (METRICS_TOKEN) - POST /back/telemetry for indexers/scrapers (metrics, events, heartbeat) and a stdlib-only Go client in telemetry/ - auth hardening: empty secrets no longer allow access, constant-time compare, CORS not applied to /admin and /back, TRUSTED_PROXIES setting - Dockerfile builds the UI and no longer bakes config.yaml into the image; CI builds the UI, runs tests and builds arm64 with CGO
This commit is contained in:
1 parent
0ef27b0072
commit
56d9e10621
79 files changed
+13146
-118
No files matched your search
@@ -0,0 +1,73 @@
|
||||
package telemetry
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"sync/atomic"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestFlushAndRetry(t *testing.T) {
|
||||
var fail atomic.Bool
|
||||
var got []batch
|
||||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.URL.Path != "/back/telemetry" || r.Header.Get("X-SECRET-KEY") != "k" {
|
||||
w.WriteHeader(http.StatusForbidden)
|
||||
return
|
||||
}
|
||||
if fail.Load() {
|
||||
w.WriteHeader(http.StatusServiceUnavailable)
|
||||
return
|
||||
}
|
||||
body, _ := io.ReadAll(r.Body)
|
||||
var b batch
|
||||
if err := json.Unmarshal(body, &b); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
got = append(got, b)
|
||||
w.Write([]byte(`{"accepted":1}`))
|
||||
}))
|
||||
defer srv.Close()
|
||||
|
||||
c := New(Config{BaseURL: srv.URL + "/", SecretKey: "k", Service: "indexer", Instance: "i1"})
|
||||
c.Counter("jobs_total", "result", "ok").Add(2)
|
||||
c.Gauge("queue").Set(7)
|
||||
c.Summary("took_seconds").Observe(1)
|
||||
c.Summary("took_seconds").Observe(3)
|
||||
c.Event(Warn, "hello", nil)
|
||||
|
||||
fail.Store(true)
|
||||
if err := c.Flush(context.Background()); err == nil {
|
||||
t.Fatal("expected an error while the server fails")
|
||||
}
|
||||
c.Counter("jobs_total", "result", "ok").Add(1)
|
||||
|
||||
fail.Store(false)
|
||||
if err := c.Flush(context.Background()); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(got) != 2 {
|
||||
t.Fatalf("got %d batches, want the retried one plus the new one", len(got))
|
||||
}
|
||||
first := got[0]
|
||||
if first.Service != "indexer" || first.Instance != "i1" || len(first.Events) != 1 {
|
||||
t.Fatalf("unexpected first batch %+v", first)
|
||||
}
|
||||
var sum float64
|
||||
for _, b := range got {
|
||||
for _, m := range b.Metrics {
|
||||
if m.Name == "jobs_total" {
|
||||
sum += m.Value
|
||||
}
|
||||
if m.Name == "took_seconds" && (m.Count != 2 || m.Min != 1 || m.Max != 3) {
|
||||
t.Fatalf("bad summary %+v", m)
|
||||
}
|
||||
}
|
||||
}
|
||||
if sum != 3 {
|
||||
t.Fatalf("counter total = %v, want 3", sum)
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user