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

Configure Feed

Select the types of activity you want to include in your feed.

feat: add db query spans for observability

- db.query spans for Turso HTTP queries (with sql, args_count)
- db.batch spans for Turso batch queries
- db.local.query spans for local SQLite queries

queries now appear as children of HTTP handler spans

🤖 Generated with [Claude Code](https://claude.com/claude-code)

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

zzstoatzz 4443f90e 35f99151

+41 -6
+23 -4
backend/src/db/Client.zig
··· 6 6 const json = std.json; 7 7 const mem = std.mem; 8 8 const Allocator = mem.Allocator; 9 + const logfire = @import("logfire"); 9 10 10 11 const result = @import("result.zig"); 11 12 pub const Result = result.Result; ··· 116 117 } 117 118 118 119 fn executeRaw(self: *Client, sql: []const u8, args: []const []const u8) ![]const u8 { 120 + const span = logfire.span("db.query", .{ 121 + .sql = truncateSql(sql), 122 + .args_count = @as(i64, @intCast(args.len)), 123 + }); 124 + defer span.end(); 125 + 119 126 self.mutex.lock(); 120 127 defer self.mutex.unlock(); 121 128 ··· 143 150 .payload = body, 144 151 .response_writer = &response_body.writer, 145 152 }) catch |err| { 146 - std.debug.print("turso request failed: {}\n", .{err}); 153 + logfire.err("turso request failed: {}", .{err}); 147 154 return error.HttpError; 148 155 }; 149 156 150 157 if (res.status != .ok) { 151 - std.debug.print("turso error: {}\n", .{res.status}); 158 + logfire.err("turso error: {}", .{res.status}); 152 159 return error.TursoError; 153 160 } 154 161 ··· 156 163 } 157 164 158 165 fn executeBatchRaw(self: *Client, statements: []const Statement) ![]const u8 { 166 + const first_sql = if (statements.len > 0) truncateSql(statements[0].sql) else ""; 167 + const span = logfire.span("db.batch", .{ 168 + .statement_count = @as(i64, @intCast(statements.len)), 169 + .first_sql = first_sql, 170 + }); 171 + defer span.end(); 172 + 159 173 self.mutex.lock(); 160 174 defer self.mutex.unlock(); 161 175 ··· 183 197 .payload = body, 184 198 .response_writer = &response_body.writer, 185 199 }) catch |err| { 186 - std.debug.print("turso batch request failed: {}\n", .{err}); 200 + logfire.err("turso batch request failed: {}", .{err}); 187 201 return error.HttpError; 188 202 }; 189 203 190 204 if (res.status != .ok) { 191 - std.debug.print("turso batch error: {}\n", .{res.status}); 205 + logfire.err("turso batch error: {}", .{res.status}); 192 206 return error.TursoError; 193 207 } 194 208 ··· 284 298 285 299 return 0; 286 300 } 301 + 302 + fn truncateSql(sql: []const u8) []const u8 { 303 + const max_len = 100; 304 + return if (sql.len > max_len) sql[0..max_len] else sql; 305 + }
+18 -2
backend/src/db/LocalDb.zig
··· 5 5 const posix = std.posix; 6 6 const zqlite = @import("zqlite"); 7 7 const Allocator = std.mem.Allocator; 8 + const logfire = @import("logfire"); 8 9 9 10 const LocalDb = @This(); 10 11 ··· 256 257 257 258 /// Execute a SELECT query with comptime SQL, returns row iterator 258 259 pub fn query(self: *LocalDb, comptime sql: []const u8, args: anytype) !Rows { 260 + const span = logfire.span("db.local.query", .{ 261 + .sql = truncateSql(sql), 262 + }); 263 + defer span.end(); 264 + 259 265 self.mutex.lock(); 260 266 defer self.mutex.unlock(); 261 267 262 268 const c = self.conn orelse return error.NotOpen; 263 269 const rows = c.rows(sql, args) catch |e| { 264 - std.debug.print("local db query error: {}\n", .{e}); 270 + logfire.err("local db query error: {}", .{e}); 265 271 return e; 266 272 }; 267 273 return .{ .inner = rows }; ··· 269 275 270 276 /// Execute a SELECT query expecting single row 271 277 pub fn queryOne(self: *LocalDb, comptime sql: []const u8, args: anytype) !?Row { 278 + const span = logfire.span("db.local.query", .{ 279 + .sql = truncateSql(sql), 280 + }); 281 + defer span.end(); 282 + 272 283 self.mutex.lock(); 273 284 defer self.mutex.unlock(); 274 285 275 286 const c = self.conn orelse return error.NotOpen; 276 287 const row = c.row(sql, args) catch |e| { 277 - std.debug.print("local db queryOne error: {}\n", .{e}); 288 + logfire.err("local db queryOne error: {}", .{e}); 278 289 return e; 279 290 }; 280 291 if (row) |r| { ··· 309 320 pub fn unlock(self: *LocalDb) void { 310 321 self.mutex.unlock(); 311 322 } 323 + 324 + fn truncateSql(sql: []const u8) []const u8 { 325 + const max_len = 100; 326 + return if (sql.len > max_len) sql[0..max_len] else sql; 327 + }