diff --git a/src/main.zig b/src/main.zig index 047bbf9..1d19b7a 100644 --- a/src/main.zig +++ b/src/main.zig @@ -155,7 +155,10 @@ pub fn main() !void { } while (true) { - iperf3_log.info("waiting for connection", .{}); + iperf3_log.info("starting new iperf3", .{}); + + var arena = std.heap.ArenaAllocator.init(allocator); + defer arena.deinit(); var c = std.process.Child.init( &[_][]const u8{ @@ -166,33 +169,61 @@ pub fn main() !void { "--json", "--one-off", }, - allocator, + arena.child_allocator, ); c.stdin_behavior = .Ignore; c.stdout_behavior = .Pipe; - c.stderr_behavior = .Ignore; + c.stderr_behavior = .Pipe; try c.spawn(); - var reader = c.stdout.?.reader(); - var token_reader = std.json.reader(allocator, reader); + var stdout = std.ArrayList(u8).init(arena.child_allocator); + var stderr = std.ArrayList(u8).init(arena.child_allocator); - var obj = try std.json.parseFromTokenSource( + iperf3_log.info("waiting for data", .{}); + + try c.collectOutput(&stdout, &stderr, 16384); + + var filename_buf: [std.fs.MAX_PATH_BYTES]u8 = undefined; + var filename: []u8 = undefined; + var timestamp = std.time.nanoTimestamp(); + + filename = try std.fmt.bufPrint(&filename_buf, "/tmp/{d}-stdout.json", .{timestamp}); + try std.fs.cwd().writeFile(filename, stdout.items); + + filename = try std.fmt.bufPrint(&filename_buf, "/tmp/{d}-stderr.json", .{timestamp}); + try std.fs.cwd().writeFile(filename, stderr.items); + + // var token_reader = std.json.reader(allocator, reader); + + var obj_or_err = std.json.parseFromSliceLeaky( iperf3.IPerfReturn, - allocator, - &token_reader, + arena.child_allocator, + stdout.items, .{}, ); - defer obj.deinit(); - var line = std.ArrayList(u8).init(allocator); - try std.json.stringify( - obj.value, - .{ - .emit_null_optional_fields = false, - }, - line.writer(), - ); - defer line.deinit(); + var level = loki.LogLevel.info; + if (obj_or_err) |obj| { + iperf3_log.info("successfully parsed json {d}", .{timestamp}); + if (obj.@"error") |err| { + iperf3_log.err("error from iperf3: {s}", .{err}); + level = loki.LogLevel.@"error"; + } + } else |err| switch (err) { + error.UnknownField => iperf3_log.err("unknown field parsing json {d}", .{timestamp}), + error.UnexpectedEndOfInput => iperf3_log.err("unexpected end of input parsing json {d}", .{timestamp}), + else => iperf3_log.err("other error while parsing json {} {d}", .{ err, timestamp }), + } + + // var line = std.ArrayList(u8).init(allocator); + // try std.json.stringify( + // obj.value, + // .{ + // .emit_null_optional_fields = false, + // }, + // line.writer(), + // ); + // defer line.deinit(); const streams = loki.LokiStreams{ .streams = &[_]loki.LokiStream{ @@ -200,12 +231,12 @@ pub fn main() !void { .stream = .{ .job = "iperf3", .server = hostname, - .level = if (obj.value.@"error" == null) .info else .@"error", + .level = level, }, .values = &[_]loki.LokiValue{ .{ - .ts = std.time.nanoTimestamp(), - .line = line.items, + .ts = timestamp, + .line = stdout.items, }, }, }, @@ -238,13 +269,31 @@ pub fn main() !void { var req = try client.request(.POST, uri, headers, .{}); defer req.deinit(); + iperf3_log.info("sending stream to loki", .{}); + try req.start(); try req.writeAll(data.items); try req.finish(); try req.wait(); - iperf3_log.info("{}\n", .{req.response.status}); + if (req.response.status == .no_content) { + iperf3_log.info("successfully sent stream to loki", .{}); + } else { + iperf3_log.info("response from loki: {}\n", .{req.response.status}); + } + const term = try c.wait(); - _ = try c.wait(); + switch (term) { + .Exited => |value| { + if (value == 0) { + iperf3_log.info("iperf3 competed successfully", .{}); + } else { + iperf3_log.info("iperf3 exited with error {d}", .{value}); + } + }, + else => { + iperf3_log.info("iperf3 terminated: {}", .{term}); + }, + } } }