lib/tracy/src/report.zig

daab053ee43316e1809a84551d573ddd1e5bf3d2

 1 const std = @import("std");
 2 const sys = @import("sys");
 3 
 4 pub fn writeFromJsonlPath(
 5     comptime Analyzer: type,
 6     comptime write: anytype,
 7     allocator: std.mem.Allocator,
 8     path: []const u8,
 9     writer: *std.Io.Writer,
10     options: anytype,
11 ) !void {
12     var analyzer = Analyzer.init(allocator);
13     defer analyzer.deinit();
14     try ingestJsonlPath(&analyzer, path);
15     try write(allocator, &analyzer, writer, options);
16 }
17 
18 pub fn ingestJsonlPath(analyzer: anytype, path: []const u8) !void {
19     var file = try sys.fs.cwd().openFile(sys.fs.debugIo(), path, .{});
20     defer file.close(sys.fs.debugIo());
21 
22     var buffer: [64 * 1024]u8 = undefined;
23     var reader = file.reader(sys.fs.debugIo(), &buffer);
24     while (true) {
25         const line = reader.interface.takeDelimiter('\n') catch |err| switch (err) {
26             error.ReadFailed => return reader.err.?,
27             else => return err,
28         };
29         const actual = line orelse break;
30         try analyzer.ingestJsonLine(actual);
31     }
32 }
33 
34 test "report ingests JSONL path and writes through analyzer" {
35     const allocator = std.testing.allocator;
36     var tmp = std.testing.tmpDir(.{});
37     defer tmp.cleanup();
38 
39     const root = try tmp.parent_dir.realPathFileAlloc(sys.fs.debugIo(), tmp.sub_path[0..], allocator);
40     defer allocator.free(root);
41     const path = try std.fs.path.join(allocator, &.{ root, "trace.jsonl" });
42     defer allocator.free(path);
43     try sys.fs.cwd().writeFile(sys.fs.debugIo(), .{ .sub_path = path, .data = "one\ntwo\n" });
44 
45     var out = std.Io.Writer.Allocating.init(allocator);
46     defer out.deinit();
47     try writeFromJsonlPath(TestAnalyzer, writeTestAnalyzer, allocator, path, &out.writer, {});
48     try std.testing.expectEqualStrings("lines=2 first=one", out.written());
49 }
50 
51 const TestAnalyzer = struct {
52     allocator: std.mem.Allocator,
53     lines: std.ArrayListUnmanaged([]u8) = .empty,
54 
55     pub fn init(allocator: std.mem.Allocator) TestAnalyzer {
56         return .{ .allocator = allocator };
57     }
58 
59     pub fn deinit(self: *TestAnalyzer) void {
60         for (self.lines.items) |line| self.allocator.free(line);
61         self.lines.deinit(self.allocator);
62     }
63 
64     pub fn ingestJsonLine(self: *TestAnalyzer, line: []const u8) !void {
65         try self.lines.append(self.allocator, try self.allocator.dupe(u8, line));
66     }
67 };
68 
69 fn writeTestAnalyzer(
70     allocator: std.mem.Allocator,
71     analyzer: *TestAnalyzer,
72     writer: *std.Io.Writer,
73     _: void,
74 ) !void {
75     _ = allocator;
76     try writer.print("lines={d} first={s}", .{ analyzer.lines.items.len, analyzer.lines.items[0] });
77 }