Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions runtime_tracing/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "runtime_tracing"
version = "0.14.1"
version = "0.14.2"
edition = "2024"
authors = ["Metacraft Labs Ltd"]
description = "A library for the schema and tracing helpers for the CodeTracer db trace format"
Expand All @@ -21,10 +21,15 @@ serde_json = "1.0"
serde_repr = "0.1"
schemars = "0.8.2"
capnp = "0.21.1"
zeekstd = "0.5.0"
cbor4ii = { version = "1.0.0", features = ["serde1", "use_std"] }
fscommon = "0.1.1"

[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
zeekstd = "0.6.0"

[target.'cfg(target_arch = "wasm32")'.dependencies]
ruzstd = "0.8.1"

[build-dependencies]
capnpc = "0.21.0"

Expand Down
1 change: 1 addition & 0 deletions runtime_tracing/src/cbor_zstd_reader.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use std::io::{self, BufRead, BufReader, Read, Seek, Write};

use fscommon::StreamSlice;

use zeekstd::Decoder;

use crate::{TraceLowLevelEvent, cbor_zstd_writer::HEADERV1};
Expand Down
39 changes: 39 additions & 0 deletions runtime_tracing/src/cbor_zstd_reader_wasm.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
use std::io::{self, BufRead, BufReader, Read, Seek, Write};

use fscommon::StreamSlice;

use ruzstd::decoding::StreamingDecoder;

use crate::{TraceLowLevelEvent, cbor_zstd_writer::HEADERV1};

fn is_at_eof<R: BufRead>(reader: &mut R) -> io::Result<bool> {
let buffer = reader.fill_buf()?;
Ok(buffer.is_empty())
}

pub fn read_trace(input: &mut (impl Read + Write + Seek)) -> Result<Vec<TraceLowLevelEvent>, Box<dyn std::error::Error>> {
let end_pos = input.seek(io::SeekFrom::End(0))?;
input.seek(io::SeekFrom::Start(0))?;

let mut header_buf = [0; 8];
let mut buf_reader = BufReader::new(&mut *input);
buf_reader.read_exact(&mut header_buf)?;
if header_buf != HEADERV1 {
panic!("Invalid file header (wrong file format or incompatible version)");
}

input.seek(io::SeekFrom::Start(0))?;
let input2 = StreamSlice::new(&mut *input, 8, end_pos)?;

let decoder = StreamingDecoder::new(input2)?;
let mut buf_reader = BufReader::new(decoder);

let mut result: Vec<TraceLowLevelEvent> = vec![];

while !is_at_eof(&mut buf_reader)? {
let obj = cbor4ii::serde::from_reader::<TraceLowLevelEvent, _>(&mut buf_reader)?;
result.push(obj);
}

Ok(result)
}
3 changes: 2 additions & 1 deletion runtime_tracing/src/cbor_zstd_writer.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
use std::{fs::File, io::Write, path::PathBuf};

use zeekstd::Encoder;

use crate::{
TraceLowLevelEvent,
abstract_trace_writer::{AbstractTraceWriter, AbstractTraceWriterData},
trace_writer::TraceWriter,
TraceLowLevelEvent,
};

/// The next 3 bytes are reserved/version info.
Expand Down
91 changes: 91 additions & 0 deletions runtime_tracing/src/cbor_zstd_writer_wasm.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
use std::{
fs::File,
io::{Cursor, Write},
path::PathBuf,
};

use ruzstd::encoding::{CompressionLevel, compress};

use crate::{
TraceLowLevelEvent,
abstract_trace_writer::{AbstractTraceWriter, AbstractTraceWriterData},
trace_writer::TraceWriter,
};

/// The next 3 bytes are reserved/version info.
/// The header is 8 bytes in size, ensuring 64-bit alignment for the rest of the file.
pub const HEADERV1: &[u8] = &[
0xC0, 0xDE, 0x72, 0xAC, 0xE2, // The first 5 bytes identify the file as a CodeTracer file (hex l33tsp33k - C0DE72ACE2 for "CodeTracer").
0x01, // Indicates version 1 of the file format
0x00, 0x00,
]; // Reserved, must be zero in this version.

pub struct CborZstdTraceWriter {
base: AbstractTraceWriterData,

trace_events_path: Option<PathBuf>,
trace_events_file: Option<File>,
uncompressed_buf: Vec<u8>,
}

impl CborZstdTraceWriter {
/// Create a new tracer instance for the given program and arguments.
pub fn new(program: &str, args: &[String]) -> Self {
CborZstdTraceWriter {
base: AbstractTraceWriterData::new(program, args),

trace_events_path: None,
trace_events_file: None,
uncompressed_buf: vec![],
}
}
}

impl AbstractTraceWriter for CborZstdTraceWriter {
fn get_data(&self) -> &AbstractTraceWriterData {
&self.base
}

fn get_mut_data(&mut self) -> &mut AbstractTraceWriterData {
&mut self.base
}

fn add_event(&mut self, event: TraceLowLevelEvent) {
let buf: Vec<u8> = Vec::new();
let q = cbor4ii::serde::to_vec(buf, &event).expect("CBOR encode failed");
self.uncompressed_buf.extend_from_slice(&q);
}

fn append_events(&mut self, events: &mut Vec<TraceLowLevelEvent>) {
for e in events.drain(..) {
<Self as AbstractTraceWriter>::add_event(self, e);
}
}
}

impl TraceWriter for CborZstdTraceWriter {
fn begin_writing_trace_events(&mut self, path: &std::path::Path) -> Result<(), Box<dyn std::error::Error>> {
let pb = path.to_path_buf();
self.trace_events_path = Some(pb.clone());

let mut file_output = std::fs::File::create(pb)?;
file_output.write_all(HEADERV1)?;
self.trace_events_file = Some(file_output);

Ok(())
}

fn finish_writing_trace_events(&mut self) -> Result<(), Box<dyn std::error::Error>> {
if let Some(mut file) = self.trace_events_file.take() {
let mut cursor = Cursor::new(&self.uncompressed_buf);
compress(&mut cursor, &mut file, CompressionLevel::Fastest);

file.flush()?;

self.uncompressed_buf.clear();
Ok(())
} else {
panic!("finish_writing_trace_events() called without previous call to begin_writing_trace_events()");
}
}
}
11 changes: 11 additions & 0 deletions runtime_tracing/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,19 @@
mod abstract_trace_writer;
mod base64;
mod capnptrace;

#[cfg(target_arch = "wasm32")]
#[path = "./cbor_zstd_reader_wasm.rs"]
mod cbor_zstd_reader;
#[cfg(target_arch = "wasm32")]
#[path = "./cbor_zstd_writer_wasm.rs"]
mod cbor_zstd_writer;

#[cfg(not(target_arch = "wasm32"))]
mod cbor_zstd_reader;
#[cfg(not(target_arch = "wasm32"))]
mod cbor_zstd_writer;

mod non_streaming_trace_writer;
mod trace_readers;
mod trace_writer;
Expand Down