lib/tracy/src/cli/args/flame.zig

daab053ee43316e1809a84551d573ddd1e5bf3d2

  1 const std = @import("std");
  2 const tracy = @import("../../root.zig");
  3 const scalar = @import("scalar.zig");
  4 const types = @import("types.zig");
  5 
  6 pub fn parse(args: []const []const u8) !types.FlameArgs {
  7     if (args.len == 0) return error.InvalidArguments;
  8     var parsed = types.FlameArgs{ .path = args[0] };
  9     var around_ns: ?u64 = null;
 10     var window_ns: ?u64 = null;
 11     var index: usize = 1;
 12     while (index < args.len) : (index += 1) {
 13         if (std.mem.eql(u8, args[index], "--format")) {
 14             index += 1;
 15             if (index >= args.len) return error.InvalidArguments;
 16             if (std.mem.eql(u8, args[index], "text")) {
 17                 parsed.format = .text;
 18             } else if (std.mem.eql(u8, args[index], "jsonl")) {
 19                 parsed.format = .jsonl;
 20             } else if (std.mem.eql(u8, args[index], "folded")) {
 21                 parsed.format = .folded;
 22             } else {
 23                 return error.UnsupportedFormat;
 24             }
 25         } else if (std.mem.eql(u8, args[index], "--top")) {
 26             index += 1;
 27             if (index >= args.len) return error.InvalidArguments;
 28             parsed.options.top = try scalar.parsePositiveUsize(args[index]);
 29         } else if (std.mem.eql(u8, args[index], "--sort")) {
 30             index += 1;
 31             if (index >= args.len) return error.InvalidArguments;
 32             parsed.options.sort = tracy.flame.Sort.fromName(args[index]) orelse return error.UnsupportedSort;
 33         } else if (std.mem.eql(u8, args[index], "--max-depth")) {
 34             index += 1;
 35             if (index >= args.len) return error.InvalidArguments;
 36             parsed.options.max_depth = try scalar.parseUsize(args[index]);
 37         } else if (std.mem.eql(u8, args[index], "--min-ns")) {
 38             index += 1;
 39             if (index >= args.len) return error.InvalidArguments;
 40             parsed.options.min_ns = try scalar.parseU64(args[index]);
 41         } else if (std.mem.eql(u8, args[index], "--thread")) {
 42             index += 1;
 43             if (index >= args.len) return error.InvalidArguments;
 44             parsed.options.thread = try scalar.parseU64(args[index]);
 45         } else if (std.mem.eql(u8, args[index], "--since-ns")) {
 46             index += 1;
 47             if (index >= args.len) return error.InvalidArguments;
 48             parsed.options.since_ns = try scalar.parseU64(args[index]);
 49         } else if (std.mem.eql(u8, args[index], "--until-ns")) {
 50             index += 1;
 51             if (index >= args.len) return error.InvalidArguments;
 52             parsed.options.until_ns = try scalar.parseU64(args[index]);
 53         } else if (std.mem.eql(u8, args[index], "--around-ns")) {
 54             index += 1;
 55             if (index >= args.len) return error.InvalidArguments;
 56             around_ns = try scalar.parseU64(args[index]);
 57         } else if (std.mem.eql(u8, args[index], "--window-ns")) {
 58             index += 1;
 59             if (index >= args.len) return error.InvalidArguments;
 60             window_ns = try scalar.parseU64(args[index]);
 61         } else if (std.mem.eql(u8, args[index], "--match")) {
 62             index += 1;
 63             if (index >= args.len) return error.InvalidArguments;
 64             parsed.options.match = args[index];
 65         } else {
 66             return error.UnknownArgument;
 67         }
 68     }
 69     if (around_ns) |center| {
 70         if (parsed.options.since_ns != null or parsed.options.until_ns != null) return error.InvalidArguments;
 71         const width = window_ns orelse 1_000_000;
 72         const half = width / 2;
 73         parsed.options.since_ns = if (center > half) center - half else 0;
 74         parsed.options.until_ns = center +| (width - half);
 75     } else if (window_ns != null) {
 76         return error.InvalidArguments;
 77     }
 78     if (parsed.options.since_ns != null and parsed.options.until_ns != null and parsed.options.since_ns.? > parsed.options.until_ns.?) {
 79         return error.InvalidArguments;
 80     }
 81     return parsed;
 82 }
 83 
 84 test "flame args parse filters window and folded format" {
 85     const parsed = try parse(&.{
 86         "events.jsonl",
 87         "--format",
 88         "folded",
 89         "--top",
 90         "12",
 91         "--sort",
 92         "name",
 93         "--max-depth",
 94         "4",
 95         "--min-ns",
 96         "50",
 97         "--thread",
 98         "7",
 99         "--around-ns",
100         "1000",
101         "--window-ns",
102         "200",
103         "--match",
104         "phase",
105     });
106     try std.testing.expectEqualStrings("events.jsonl", parsed.path);
107     try std.testing.expectEqual(types.FlameFormat.folded, parsed.format);
108     try std.testing.expectEqual(@as(usize, 12), parsed.options.top);
109     try std.testing.expectEqual(tracy.flame.Sort.name, parsed.options.sort);
110     try std.testing.expectEqual(@as(usize, 4), parsed.options.max_depth);
111     try std.testing.expectEqual(@as(u64, 50), parsed.options.min_ns);
112     try std.testing.expectEqual(@as(?u64, 7), parsed.options.thread);
113     try std.testing.expectEqual(@as(?u64, 900), parsed.options.since_ns);
114     try std.testing.expectEqual(@as(?u64, 1100), parsed.options.until_ns);
115     try std.testing.expectEqualStrings("phase", parsed.options.match.?);
116 }