logfire client for zig
at main 103 lines 2.5 kB view raw view rendered
1# logfire-zig 2 3zig 0.15+ SDK for pydantic logfire - OTLP HTTP/JSON export for traces, logs, metrics. 4 5## goal 6 7**full parity with logfire-rust client.** not simpler, not "good enough" - parity. 8 9## reference projects 10 11look at these for patterns, don't reinvent: 12 13- `~/tangled.sh/@zzstoatzz.io/prefect-server/` - zig 0.15 http server, json handling 14- `~/tangled.sh/@zzstoatzz.io/zat/` - zig 0.15 AT Protocol client 15- `~/tangled.sh/@zzstoatzz.io/leaflet-search/` - zig backend patterns 16- `~/tangled.sh/@zzstoatzz.io/notes/languages/ziglang/0.15/` - zig 0.15 syntax notes 17 18## zig 0.15 patterns 19 20### JSON serialization - use std.json.Stringify 21 22**DO NOT manually concatenate JSON strings.** use the stdlib: 23 24```zig 25const json = std.json; 26 27fn buildJson(alloc: std.mem.Allocator, data: MyData) ![]u8 { 28 var output: std.Io.Writer.Allocating = .init(alloc); 29 var jw: json.Stringify = .{ .writer = &output.writer }; 30 31 try jw.beginObject(); 32 try jw.objectField("name"); 33 try jw.write(data.name); 34 try jw.objectField("count"); 35 try jw.write(data.count); 36 try jw.endObject(); 37 38 return output.toOwnedSlice(); 39} 40``` 41 42for raw JSON passthrough: 43```zig 44try jw.beginWriteRaw(); 45try jw.writer.writeAll(raw_json_string); 46jw.endWriteRaw(); 47``` 48 49### ArrayList (unmanaged in 0.15) 50 51pass allocator to each method: 52 53```zig 54var buf: std.ArrayList(u8) = .empty; 55defer buf.deinit(alloc); 56 57try buf.appendSlice(alloc, data); 58try buf.print(alloc, "{d}", .{value}); 59 60// borrow: buf.items (don't hold after deinit) 61// transfer ownership: buf.toOwnedSlice(alloc) 62``` 63 64### HTTP client 65 66```zig 67var client = std.http.Client{ .allocator = allocator }; 68defer client.deinit(); 69 70var aw: std.Io.Writer.Allocating = .init(allocator); 71defer aw.deinit(); 72 73const result = client.fetch(.{ 74 .location = .{ .url = url }, 75 .response_writer = &aw.writer, 76 .method = .POST, 77 .payload = body, 78 .headers = .{ 79 .content_type = .{ .override = "application/json" }, 80 .accept_encoding = .{ .override = "identity" }, // disable gzip (bug in 0.15) 81 }, 82}) catch return error.RequestFailed; 83``` 84 85### env vars 86 87```zig 88const token = std.posix.getenv("LOGFIRE_WRITE_TOKEN") orelse 89 std.posix.getenv("LOGFIRE_TOKEN"); 90``` 91 92## testing 93 94```bash 95zig build test # run tests 96zig build example # run examples/basic.zig 97``` 98 99test with real export requires LOGFIRE_WRITE_TOKEN in .env 100 101## rust client reference 102 103`gh api repos/pydantic/logfire-rust/contents/src` - check metrics.rs for API parity