This commit is contained in:
Mateusz Gruszczyński committed 2026-11-04 21:16:25 +01:00
1 parent 677a0e4d2c
commit c85c9fc144
4 files changed
+31 -7

No files matched your search

+1 -1
View File
@@ -1 +1 @@
0.3.0 0.3.3
+21 -5
View File
@@ -52,15 +52,31 @@ func main() {
func collect(ctx context.Context, cfg config.Config, tq *ts3.Query, rm *rrd.Manager) { func collect(ctx context.Context, cfg config.Config, tq *ts3.Query, rm *rrd.Manager) {
run := func() { run := func() {
c, cancel := context.WithTimeout(ctx, cfg.TSQueryTimeout) c, cancel := context.WithTimeout(ctx, cfg.TSQueryTimeout)
defer cancel()
n, err := tq.CountOnline(c) n, err := tq.CountOnline(c)
cancel()
if err != nil { if err != nil {
log.Printf("stats query failed: %v", err) log.Printf("stats query failed: %v", err)
return
} }
c2, cancel2 := context.WithTimeout(ctx, 5*time.Second) // Treat "query failed" and "query succeeded but nobody is online"
defer cancel2() // the same way: repeat the last known sample instead of writing 0.
if err := rm.Update(c2, n); err != nil { // This matches the original PHP app's collector exactly (it never
// distinguished the two cases either). At a 1-minute sampling
// interval a real but brief empty-server moment plots as a sharp
// spike down to 0 and back up, which reads as broken/jagged far
// more than it reads as useful information -- so, deliberately,
// a true "server went empty for a while" no longer shows as 0 in
// the graph, same trade-off the original app made.
if n == 0 {
c2, cancel2 := context.WithTimeout(ctx, 2*time.Second)
last, lastErr := rm.Last(c2)
cancel2()
if lastErr == nil {
n = last
}
}
c3, cancel3 := context.WithTimeout(ctx, 5*time.Second)
defer cancel3()
if err := rm.Update(c3, n); err != nil {
log.Printf("rrd update failed: %v", err) log.Printf("rrd update failed: %v", err)
} }
} }
+8
View File
@@ -134,6 +134,14 @@ func (m *Manager) Graph(ctx context.Context, key, theme string) (string, error)
"graph", out, "graph", out,
"--imgformat", "PNG", "--imgformat", "PNG",
"--start", rg.Start, "--end", "now", "--start", rg.Start, "--end", "now",
// By default rrdtool's --width/--height size only the plot canvas;
// the title, legend rows and axis-label margins then pad the final
// PNG to something larger and variable (depends on title/legend
// text length). --full-size-mode makes --width/--height the exact
// *total* image size instead, so the PNG is always precisely
// 1200x320 -- matching the CSS aspect-ratio on the <img> exactly,
// with no letterboxing from a size mismatch.
"--full-size-mode",
"--width", "1200", "--height", "320", "--width", "1200", "--height", "320",
"--lower-limit", "0", "--alt-autoscale-max", "--rigid", "--lower-limit", "0", "--alt-autoscale-max", "--rigid",
"--slope-mode", "--slope-mode",
+1 -1
View File
@@ -106,7 +106,7 @@ html[data-theme=light] .theme-toggle .ic-moon{display:block}
.graphs{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:14px} .graphs{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:14px}
.graph-image-button{display:block;width:100%;padding:0;border:0;background:var(--field);cursor:zoom-in;overflow:hidden} .graph-image-button{display:block;width:100%;padding:0;border:0;background:var(--field);cursor:zoom-in;overflow:hidden}
.graph-image-button img{display:block;width:100%;height:auto;aspect-ratio:3.56/1;object-fit:contain;transition:transform .18s ease,opacity .18s ease} .graph-image-button img{display:block;width:100%;height:auto;aspect-ratio:1200/320;object-fit:contain;transition:transform .18s ease,opacity .18s ease}
.graph-image-button:hover img{transform:scale(1.012);opacity:.96} .graph-image-button:hover img{transform:scale(1.012);opacity:.96}
.lightbox[hidden]{display:none} .lightbox[hidden]{display:none}