Cross Compile Go / build (push) Canceled after 0s
- 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
75 lines
4.0 KiB
Go
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
|
|
}
|