search for standard sites pub-search.waow.tech
search zig blog atproto

fix: add started_at to /stats JSON, add logging to stats cache refresh

The /stats endpoint was missing the started_at field entirely. Also
added diagnostic logging to refreshCachedStats so turso query failures
are visible instead of silently swallowed.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

+20 -5
+18 -5
backend/src/metrics/buffer.zig
··· 159 \\SELECT total_searches, total_errors, service_started_at, 160 \\ COALESCE(cache_hits, 0), COALESCE(cache_misses, 0) 161 \\FROM stats WHERE id = 1 162 - , &.{}) catch return; 163 defer res.deinit(); 164 165 - const row = res.first() orelse return; 166 - cached_base_searches.store(row.int(0), .release); 167 - cached_base_errors.store(row.int(1), .release); 168 - cached_started_at.store(row.int(2), .release); 169 cached_base_cache_hits.store(row.int(3), .release); 170 cached_base_cache_misses.store(row.int(4), .release); 171 cache_initialized.store(true, .release); 172 } 173
··· 159 \\SELECT total_searches, total_errors, service_started_at, 160 \\ COALESCE(cache_hits, 0), COALESCE(cache_misses, 0) 161 \\FROM stats WHERE id = 1 162 + , &.{}) catch |err| { 163 + logfire.warn("stats_buffer: refresh query failed: {}", .{err}); 164 + return; 165 + }; 166 defer res.deinit(); 167 168 + const row = res.first() orelse { 169 + logfire.warn("stats_buffer: stats table has no row with id=1", .{}); 170 + return; 171 + }; 172 + const searches = row.int(0); 173 + const errors = row.int(1); 174 + const started = row.int(2); 175 + cached_base_searches.store(searches, .release); 176 + cached_base_errors.store(errors, .release); 177 + cached_started_at.store(started, .release); 178 cached_base_cache_hits.store(row.int(3), .release); 179 cached_base_cache_misses.store(row.int(4), .release); 180 + 181 + if (!cache_initialized.load(.acquire)) { 182 + logfire.info("stats_buffer: cache initialized (searches={d}, started_at={d})", .{ searches, started }); 183 + } 184 cache_initialized.store(true, .release); 185 } 186
+2
backend/src/server.zig
··· 351 try jw.write(db_stats.searches); 352 try jw.objectField("errors"); 353 try jw.write(db_stats.errors); 354 try jw.objectField("cache_hits"); 355 try jw.write(db_stats.cache_hits); 356 try jw.objectField("cache_misses");
··· 351 try jw.write(db_stats.searches); 352 try jw.objectField("errors"); 353 try jw.write(db_stats.errors); 354 + try jw.objectField("started_at"); 355 + try jw.write(db_stats.started_at); 356 try jw.objectField("cache_hits"); 357 try jw.write(db_stats.cache_hits); 358 try jw.objectField("cache_misses");