logfire client for zig
at c7a46726fe7ff8bb65e4e72c985aa146fbf6d404 91 lines 2.4 kB view raw
1//! span tracking for distributed tracing 2//! 3//! spans measure the duration of operations. 4//! use defer to ensure spans are ended even on error paths. 5//! 6//! ## usage 7//! 8//! ```zig 9//! const s = logfire.span("db.query", .{}); 10//! defer s.end(); 11//! // ... do work 12//! ``` 13 14const std = @import("std"); 15const root = @import("root.zig"); 16const Attribute = @import("attribute.zig").Attribute; 17 18pub const Span = struct { 19 logfire: ?*root.Logfire, 20 data: Data, 21 active: bool, 22 23 pub const max_attributes = 32; 24 25 pub const Data = struct { 26 name: []const u8, 27 trace_id: [16]u8, 28 span_id: [8]u8, 29 parent_span_id: ?[8]u8 = null, 30 start_time_ns: i128, 31 end_time_ns: i128, 32 attributes: [max_attributes]Attribute = undefined, 33 attribute_count: usize = 0, 34 }; 35 36 /// create a span (called by Logfire.createSpan) 37 pub fn init(logfire: *root.Logfire, name: []const u8, span_id: [8]u8, trace_id: ?[16]u8, parent_span_id: ?[8]u8, attrs: anytype) Span { 38 var s = Span{ 39 .logfire = logfire, 40 .data = .{ 41 .name = name, 42 .trace_id = trace_id orelse [_]u8{0} ** 16, 43 .span_id = span_id, 44 .parent_span_id = parent_span_id, 45 .start_time_ns = std.time.nanoTimestamp(), 46 .end_time_ns = 0, 47 }, 48 .active = true, 49 }; 50 51 // store attributes 52 s.data.attribute_count = Attribute.fromStruct(attrs, &s.data.attributes); 53 54 return s; 55 } 56 57 /// create a no-op span (when logfire not configured) 58 pub fn noop() Span { 59 return .{ 60 .logfire = null, 61 .data = .{ 62 .name = "", 63 .trace_id = [_]u8{0} ** 16, 64 .span_id = [_]u8{0} ** 8, 65 .start_time_ns = 0, 66 .end_time_ns = 0, 67 }, 68 .active = false, 69 }; 70 } 71 72 /// end the span and record it 73 pub fn end(self: *const Span) void { 74 if (!self.active) return; 75 if (self.logfire) |lf| { 76 var data = self.data; 77 data.end_time_ns = std.time.nanoTimestamp(); 78 lf.recordSpanEnd(data); 79 lf.spanEnded(self.data.parent_span_id); 80 } 81 } 82}; 83 84// tests 85 86test "span lifecycle" { 87 const s = Span.noop(); 88 defer s.end(); 89 90 try std.testing.expect(!s.active); 91}