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.

fix: logfire-zig integration fixes

- update to logfire-zig with auto-flush, proper trace_id per root span,
and delta temporality for metrics
- add UTF-8 sanitization in embedder to fix Voyage API JSON serialization
(invalid UTF-8 caused json.Stringify to output byte arrays)
- tone down debug logging (remove per-document logs, reduce tap message
count logging frequency)

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

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

zzstoatzz 23095848 158d25cf

+33 -11
+1 -1
backend/build.zig.zon
··· 22 22 }, 23 23 .logfire = .{ 24 24 .url = "https://tangled.sh/zzstoatzz.io/logfire-zig/archive/main", 25 - .hash = "logfire_zig-0.1.0-x2yDLlEIAQBy1OEtTaAKe1fwl2Mctxy3lmfmASj1I_Cv", 25 + .hash = "logfire_zig-0.1.0-x2yDLjkPAQDcug-Eg2QkCM-JphiYksSAWp-6_i5l31Xj", 26 26 }, 27 27 }, 28 28 .paths = .{
+29 -1
backend/src/embedder.zig
··· 51 51 52 52 if (processed > 0) { 53 53 consecutive_errors = 0; 54 - logfire.debug("embedder: processed {d} documents", .{processed}); 55 54 logfire.counter("embedder.documents_processed", @intCast(processed)); 56 55 // immediately check for more 57 56 continue; ··· 128 127 @memcpy(text[0..title.len], title); 129 128 text[title.len] = ' '; 130 129 @memcpy(text[title.len + 1 ..], truncated_content); 130 + 131 + // sanitize to valid UTF-8 (replace invalid bytes with space) 132 + // this ensures json.Stringify treats it as a string, not byte array 133 + sanitizeUtf8(text); 134 + 131 135 return text; 136 + } 137 + 138 + fn sanitizeUtf8(text: []u8) void { 139 + var i: usize = 0; 140 + while (i < text.len) { 141 + const len = std.unicode.utf8ByteSequenceLength(text[i]) catch { 142 + text[i] = ' '; // replace invalid start byte 143 + i += 1; 144 + continue; 145 + }; 146 + if (i + len > text.len) { 147 + // truncated sequence at end 148 + text[i] = ' '; 149 + i += 1; 150 + continue; 151 + } 152 + // validate the full sequence 153 + _ = std.unicode.utf8Decode(text[i..][0..len]) catch { 154 + text[i] = ' '; // replace invalid sequence start 155 + i += 1; 156 + continue; 157 + }; 158 + i += len; 159 + } 132 160 } 133 161 134 162 fn callVoyageApi(allocator: Allocator, api_key: []const u8, docs: []const DocToEmbed) ![][]f32 {
+3 -9
backend/src/tap.zig
··· 67 67 68 68 pub fn serverMessage(self: *Handler, data: []const u8) !void { 69 69 self.msg_count += 1; 70 - if (self.msg_count % 100 == 1) { 71 - logfire.debug("tap: received {d} messages", .{self.msg_count}); 70 + if (self.msg_count % 1000 == 0) { 71 + logfire.info("tap: processed {d} messages", .{self.msg_count}); 72 72 } 73 73 74 74 // extract message ID for ACK ··· 96 96 }; 97 97 } 98 98 99 - pub fn close(_: *Handler) void { 100 - logfire.debug("tap connection closed", .{}); 101 - } 99 + pub fn close(_: *Handler) void {} 102 100 }; 103 101 104 102 fn extractMessageId(allocator: Allocator, payload: []const u8) ?i64 { ··· 215 213 } else if (rec.isDelete()) { 216 214 if (isDocumentCollection(rec.collection)) { 217 215 indexer.deleteDocument(uri); 218 - logfire.debug("deleted document: {s}", .{uri}); 219 216 } else if (isPublicationCollection(rec.collection)) { 220 217 indexer.deletePublication(uri); 221 - logfire.debug("deleted publication: {s}", .{uri}); 222 218 } 223 219 } 224 220 } ··· 245 241 doc.source_collection, 246 242 doc.path, 247 243 ); 248 - logfire.debug("indexed document: {s} [{s}] ({d} chars, {d} tags)", .{ uri, doc.platformName(), doc.content.len, doc.tags.len }); 249 244 logfire.counter("tap.documents_indexed", 1); 250 245 } 251 246 ··· 262 257 stripUrlScheme(zat.json.getString(record_val, "url")); 263 258 264 259 try indexer.insertPublication(uri, did, rkey, name, description, base_path); 265 - logfire.debug("indexed publication: {s} (base_path: {s})", .{ uri, base_path orelse "none" }); 266 260 logfire.counter("tap.publications_indexed", 1); 267 261 } 268 262