Files
ilbinek 56d9e10621
Cross Compile Go / build (push) Canceled after 0s
admin dashboard, metrics and telemetry
- 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
2026-10-03 18:10:57 +02:00

75 lines
4.0 KiB
Go

package models
import "time"
// All timestamps in the metrics tables are int64 unix seconds (events: unix
// milliseconds) so range queries behave the same on SQLite and Postgres.
// MetricSeries identifies one time series: a metric name plus a fixed label set
// reported by one service instance.
type MetricSeries struct {
ID uint `gorm:"primaryKey" json:"id"`
Service string `gorm:"size:64;not null;uniqueIndex:ux_metric_series,priority:1" json:"service"`
Instance string `gorm:"size:128;not null;uniqueIndex:ux_metric_series,priority:2" json:"instance"`
Name string `gorm:"size:96;not null;uniqueIndex:ux_metric_series,priority:3;index" json:"name"`
Labels string `gorm:"size:512;not null;uniqueIndex:ux_metric_series,priority:4" json:"labels"` // canonical JSON object
Kind string `gorm:"size:16;not null" json:"kind"` // counter|gauge|summary|histogram
Bounds string `gorm:"type:text" json:"bounds"` // JSON []float64, histograms only
Help string `gorm:"size:256" json:"help"`
CreatedAt time.Time
LastSeen int64 `gorm:"index" json:"lastSeen"`
}
// MetricPoint is one aggregated bucket of a series. Resolution is the bucket
// width in seconds (60 = raw minute data, 3600 = hourly rollup).
type MetricPoint struct {
SeriesID uint `gorm:"primaryKey;autoIncrement:false"`
Resolution int `gorm:"primaryKey;autoIncrement:false;index:idx_metric_points_res_bucket,priority:1"`
Bucket int64 `gorm:"primaryKey;autoIncrement:false;index:idx_metric_points_res_bucket,priority:2"`
Count int64 `gorm:"not null;default:0"`
Sum float64 `gorm:"not null;default:0"`
Min float64 `gorm:"not null;default:0"`
Max float64 `gorm:"not null;default:0"`
Last float64 `gorm:"not null;default:0"`
Hist string `gorm:"type:text"` // JSON []uint64, histograms only
}
// ServiceInstance is one running process (indexer, scraper, the API itself)
// that reports telemetry. Every telemetry push counts as a heartbeat.
type ServiceInstance struct {
ID uint `gorm:"primaryKey" json:"id"`
Service string `gorm:"size:64;not null;uniqueIndex:ux_service_instance,priority:1" json:"service"`
Instance string `gorm:"size:128;not null;uniqueIndex:ux_service_instance,priority:2" json:"instance"`
Version string `gorm:"size:64" json:"version"`
Status string `gorm:"size:16" json:"status"` // self-reported: ok|degraded|error
StatusMessage string `gorm:"size:512" json:"statusMessage"`
StartedAt int64 `json:"startedAt"`
LastSeen int64 `gorm:"index" json:"lastSeen"`
HeartbeatIntervalSec int `json:"heartbeatIntervalSec"`
RemoteAddr string `gorm:"size:64" json:"remoteAddr"`
Meta string `gorm:"type:text" json:"meta"` // JSON object
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
}
// ServiceEvent is a log line reported by a service. Admin actions are recorded
// here too (service "main", fields.kind "audit").
type ServiceEvent struct {
ID uint `gorm:"primaryKey" json:"id"`
Service string `gorm:"size:64;index:idx_service_events_svc_ts,priority:1" json:"service"`
Instance string `gorm:"size:128" json:"instance"`
Level string `gorm:"size:8;index" json:"level"` // debug|info|warn|error
Message string `gorm:"size:1024" json:"message"`
Fields string `gorm:"type:text" json:"fields"` // JSON object
TS int64 `gorm:"index:idx_service_events_svc_ts,priority:2;index" json:"ts"` // unix ms
}
// DailyTopItem counts how often something was requested on one UTC day
// (Kind "addon": addon lookups, Kind "search": search queries).
type DailyTopItem struct {
Day string `gorm:"primaryKey;size:10"` // YYYY-MM-DD
Kind string `gorm:"primaryKey;size:16"`
Item string `gorm:"primaryKey;size:128"`
Count int64
}