Skip to main content

SpanRecord

Struct SpanRecord 

Source
pub struct SpanRecord {
Show 15 fields pub trace_id: [u8; 16], pub span_id: [u8; 8], pub parent_span_id: Option<[u8; 8]>, pub span_name: String, pub span_kind: SpanKind, pub start_time_nanos: u64, pub end_time_nanos: u64, pub duration_nanos: u64, pub logical_clock: u64, pub status_code: StatusCode, pub status_message: String, pub attributes_json: String, pub resource_json: String, pub process_id: u32, pub thread_id: u64,
}
Expand description

Span record compatible with trueno-db Parquet storage

This is the canonical schema for all spans recorded by renacer. Each span represents a single operation (syscall, function call, GPU kernel, etc.) with complete metadata for causal analysis.

§Example

use renacer::span_record::{SpanRecord, SpanKind, StatusCode};
use std::collections::HashMap;

let span = SpanRecord {
    trace_id: [0x4b, 0xf9, 0x2f, 0x3c, 0x7b, 0x64, 0x4b, 0xf9,
               0x2f, 0x3c, 0x7b, 0x64, 0x4b, 0xf9, 0x2f, 0x3c],
    span_id: [0x00, 0xf0, 0x67, 0xaa, 0x0b, 0xa9, 0x02, 0xb7],
    parent_span_id: None,
    span_name: "read".to_string(),
    span_kind: SpanKind::Internal,
    start_time_nanos: 1700000000000000000,
    end_time_nanos: 1700000000000050000,
    duration_nanos: 50000,
    logical_clock: 42,
    status_code: StatusCode::Ok,
    status_message: String::new(),
    attributes_json: r#"{"syscall.name":"read","syscall.fd":3,"syscall.bytes":1024}"#.to_string(),
    resource_json: r#"{"service.name":"renacer","process.pid":1234}"#.to_string(),
    process_id: 1234,
    thread_id: 1234,
};

Fields§

§trace_id: [u8; 16]

W3C Trace Context trace ID (128-bit / 16 bytes)

Format: 32 hex characters (e.g., 4bf92f3c7b644bf92f3c7b644bf92f3c)

This is the “golden thread” that links all operations across the entire pipeline (Rust binary → transpilation → syscalls).

§span_id: [u8; 8]

W3C Trace Context span ID (64-bit / 8 bytes)

Format: 16 hex characters (e.g., 00f067aa0ba902b7)

Uniquely identifies this span within the trace.

§parent_span_id: Option<[u8; 8]>

Parent span ID (if this span has a parent)

  • None indicates this is a root span
  • Some(id) indicates this span is a child of another span
§span_name: String

Human-readable span name (e.g., “read”, “write”, “GPU kernel”, “HTTP GET”)

Should follow OpenTelemetry semantic conventions:

  • Syscalls: use syscall name (e.g., “read”, “write”)
  • Functions: use function name (e.g., “process_request”)
  • HTTP: use “HTTP {method}” (e.g., “HTTP GET”)
§span_kind: SpanKind

Span kind (internal, server, client, producer, consumer)

Indicates the role of this span in the request flow.

§start_time_nanos: u64

Start time in nanoseconds since UNIX epoch

This is the physical timestamp (subject to clock skew). Use logical_clock for causal ordering.

§end_time_nanos: u64

End time in nanoseconds since UNIX epoch

This is the physical timestamp (subject to clock skew). Use logical_clock for causal ordering.

§duration_nanos: u64

Span duration in nanoseconds (end_time - start_time)

This is a computed field for query convenience.

§logical_clock: u64

Lamport logical clock timestamp

This provides a mathematical guarantee of causal ordering: if event A → B (happens-before), then logical_clock(A) < logical_clock(B).

Use this for:

  • Critical path analysis (longest path in causal graph)
  • Detecting race conditions (concurrent events have incomparable clocks)
  • Cross-process ordering (even with clock skew)
§status_code: StatusCode

Span status code (unset, ok, error)

§status_message: String

Span status message (empty if OK, error message if ERROR)

§attributes_json: String

Span attributes as JSON string

This contains all key-value metadata about the span:

  • Syscall arguments: {"syscall.name":"read","syscall.fd":3,"syscall.bytes":1024}
  • File paths: {"file.path":"/etc/passwd","file.line":42}
  • HTTP: {"http.method":"GET","http.url":"https://example.com"}

Stored as JSON to maintain flat Parquet schema (no nested columns).

§resource_json: String

Resource attributes as JSON string

This contains metadata about the execution environment:

  • {"service.name":"renacer","process.pid":1234,"host.name":"server1"}

Stored as JSON to maintain flat Parquet schema.

§process_id: u32

Process ID (for filtering by process)

§thread_id: u64

Thread ID (for filtering by thread)

Implementations§

Source§

impl SpanRecord

Source

pub fn new( trace_id: [u8; 16], span_id: [u8; 8], parent_span_id: Option<[u8; 8]>, span_name: String, span_kind: SpanKind, start_time_nanos: u64, end_time_nanos: u64, logical_clock: u64, status_code: StatusCode, status_message: String, attributes: HashMap<String, String>, resource: HashMap<String, String>, process_id: u32, thread_id: u64, ) -> Self

Create a new SpanRecord with computed duration

§Arguments
  • trace_id - W3C Trace Context trace ID (16 bytes)
  • span_id - W3C Trace Context span ID (8 bytes)
  • parent_span_id - Parent span ID (None for root spans)
  • span_name - Human-readable span name
  • span_kind - Span kind (internal, server, client, etc.)
  • start_time_nanos - Start time in nanoseconds since UNIX epoch
  • end_time_nanos - End time in nanoseconds since UNIX epoch
  • logical_clock - Lamport logical clock timestamp
  • status_code - Span status code
  • status_message - Span status message
  • attributes - Span attributes (will be serialized to JSON)
  • resource - Resource attributes (will be serialized to JSON)
  • process_id - Process ID
  • thread_id - Thread ID
§Example
use renacer::span_record::{SpanRecord, SpanKind, StatusCode};
use std::collections::HashMap;

let mut attributes = HashMap::new();
attributes.insert("syscall.name".to_string(), "read".to_string());
attributes.insert("syscall.fd".to_string(), "3".to_string());

let mut resource = HashMap::new();
resource.insert("service.name".to_string(), "renacer".to_string());

let span = SpanRecord::new(
    [0x4b, 0xf9, 0x2f, 0x3c, 0x7b, 0x64, 0x4b, 0xf9,
     0x2f, 0x3c, 0x7b, 0x64, 0x4b, 0xf9, 0x2f, 0x3c],
    [0x00, 0xf0, 0x67, 0xaa, 0x0b, 0xa9, 0x02, 0xb7],
    None,
    "read".to_string(),
    SpanKind::Internal,
    1700000000000000000,
    1700000000000050000,
    42,
    StatusCode::Ok,
    String::new(),
    attributes,
    resource,
    1234,
    1234,
);

assert_eq!(span.duration_nanos, 50000);
Source

pub fn parse_attributes(&self) -> HashMap<String, String>

Parse attributes from JSON string

§Returns

HashMap of attribute key-value pairs, or empty map if parse fails.

Source

pub fn parse_resource(&self) -> HashMap<String, String>

Parse resource attributes from JSON string

§Returns

HashMap of resource key-value pairs, or empty map if parse fails.

Source

pub fn trace_id_hex(&self) -> String

Get trace ID as hex string (W3C Trace Context format)

§Example
use renacer::span_record::{SpanRecord, SpanKind, StatusCode};
use std::collections::HashMap;

let span = SpanRecord::new(
    [0x4b, 0xf9, 0x2f, 0x3c, 0x7b, 0x64, 0x4b, 0xf9,
     0x2f, 0x3c, 0x7b, 0x64, 0x4b, 0xf9, 0x2f, 0x3c],
    [0x00, 0xf0, 0x67, 0xaa, 0x0b, 0xa9, 0x02, 0xb7],
    None,
    "test".to_string(),
    SpanKind::Internal,
    0, 0, 0,
    StatusCode::Ok,
    String::new(),
    HashMap::new(),
    HashMap::new(),
    0, 0,
);

assert_eq!(span.trace_id_hex(), "4bf92f3c7b644bf92f3c7b644bf92f3c");
Source

pub fn span_id_hex(&self) -> String

Get span ID as hex string (W3C Trace Context format)

Source

pub fn parent_span_id_hex(&self) -> Option<String>

Get parent span ID as hex string (W3C Trace Context format)

Source

pub fn is_root(&self) -> bool

Check if this is a root span (no parent)

Source

pub fn is_error(&self) -> bool

Check if this span represents an error

Trait Implementations§

Source§

impl Clone for SpanRecord

Source§

fn clone(&self) -> SpanRecord

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for SpanRecord

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<'de> Deserialize<'de> for SpanRecord

Source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
Source§

impl PartialEq for SpanRecord

Source§

fn eq(&self, other: &SpanRecord) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl Serialize for SpanRecord

Source§

fn serialize<__S>(&self, __serializer: __S) -> Result<__S::Ok, __S::Error>
where __S: Serializer,

Serialize this value into the given Serde serializer. Read more
Source§

impl StructuralPartialEq for SpanRecord

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> DeserializeOwned for T
where T: for<'de> Deserialize<'de>,