#![deny(missing_docs)]
#![warn(clippy::undocumented_unsafe_blocks)]
#![cfg_attr(
feature = "intrinsics",
allow(internal_features),
feature(core_intrinsics)
)]
pub mod data_source;
pub mod heap_buffer;
pub mod pb_decoder;
pub mod pb_msg;
pub mod pb_utils;
pub mod producer;
pub mod protos;
pub mod stream_writer;
pub mod tracing_session;
pub mod track_event;
const FNV64_OFFSET: u64 = 0xcbf29ce484222325;
const FNV64_PRIME: u64 = 0x00000100000001B3;
pub const fn fnv1a(bytes: &[u8]) -> u64 {
let mut hash = FNV64_OFFSET;
let mut i = 0;
while i < bytes.len() {
hash ^= bytes[i] as u64;
hash = hash.wrapping_mul(FNV64_PRIME);
i += 1;
}
hash
}
#[cfg(feature = "intrinsics")]
#[doc(hidden)]
#[macro_export]
macro_rules! __likely {
($e:expr) => {{ std::intrinsics::likely($e) }};
}
#[cfg(not(feature = "intrinsics"))]
#[doc(hidden)]
#[macro_export]
macro_rules! __likely {
($e:expr) => {{ $e }};
}
#[cfg(feature = "intrinsics")]
#[doc(hidden)]
#[macro_export]
macro_rules! __unlikely {
($e:expr) => {{ std::intrinsics::unlikely($e) }};
}
#[cfg(not(feature = "intrinsics"))]
#[doc(hidden)]
#[macro_export]
macro_rules! __unlikely {
($e:expr) => {{ $e }};
}
#[doc(hidden)]
pub fn __box_as_mut_ptr<T: ?Sized>(b: &mut Box<T>) -> *mut T {
&raw mut **b
}
#[cfg(test)]
mod tests {
use super::*;
use crate::producer::{Backends, Producer, ProducerInitArgsBuilder};
use crate::tracing_session::*;
use std::sync::{Mutex, MutexGuard, Once};
static INIT_TEST_ENVIRONMENT: Once = Once::new();
static TEST_ENVIRONMENT_MUTEX: Mutex<()> = Mutex::new(());
pub(crate) const PRODUCER_SHMEM_SIZE_HINT_KB: u32 = 64;
pub(crate) fn acquire_test_environment() -> MutexGuard<'static, ()> {
INIT_TEST_ENVIRONMENT.call_once(|| {
let producer_args = ProducerInitArgsBuilder::new()
.backends(Backends::IN_PROCESS)
.shmem_size_hint_kb(PRODUCER_SHMEM_SIZE_HINT_KB);
Producer::init(producer_args.build());
});
TEST_ENVIRONMENT_MUTEX.lock().unwrap()
}
#[derive(Default)]
#[must_use = "This is a builder; remember to call `.build()` (or keep chaining)."]
pub(crate) struct TracingSessionBuilder {
data_source_name: String,
enabled_categories: Vec<String>,
disabled_categories: Vec<String>,
}
impl TracingSessionBuilder {
pub fn new() -> Self {
Self::default()
}
#[must_use = "Builder methods return an updated builder; use the returned value or keep chaining."]
pub fn set_data_source_name(mut self, name: impl Into<String>) -> Self {
self.data_source_name = name.into();
self
}
#[must_use = "Builder methods return an updated builder; use the returned value or keep chaining."]
pub fn add_enabled_category(mut self, category: impl Into<String>) -> Self {
self.enabled_categories.push(category.into());
self
}
#[must_use = "Builder methods return an updated builder; use the returned value or keep chaining."]
pub fn add_disabled_category(mut self, category: impl Into<String>) -> Self {
self.disabled_categories.push(category.into());
self
}
fn build_proto_config(&self) -> Vec<u8> {
use crate::{
heap_buffer::HeapBuffer,
pb_msg::{PbMsg, PbMsgWriter},
protos::config::{
data_source_config::DataSourceConfig,
trace_config::{BufferConfig, DataSource, TraceConfig},
track_event::track_event_config::TrackEventConfig,
},
};
let writer = PbMsgWriter::new();
let hb = HeapBuffer::new(&writer.writer);
let mut msg = PbMsg::new(&writer).unwrap();
{
let mut cfg = TraceConfig { msg: &mut msg };
cfg.set_buffers(|buf_cfg: &mut BufferConfig| {
buf_cfg.set_size_kb(1024);
});
cfg.set_data_sources(|data_sources: &mut DataSource| {
data_sources.set_config(|ds_cfg: &mut DataSourceConfig| {
ds_cfg.set_name(&self.data_source_name);
if !self.enabled_categories.is_empty()
|| !self.disabled_categories.is_empty()
{
ds_cfg.set_track_event_config(|te_cfg: &mut TrackEventConfig| {
for enabled_catagory in &self.enabled_categories {
te_cfg.set_enabled_categories(enabled_catagory);
}
for disabled_catagory in &self.disabled_categories {
te_cfg.set_disabled_categories(disabled_catagory);
}
});
}
});
});
}
msg.finalize();
let cfg_size = writer.writer.get_written_size();
let mut cfg_buffer: Vec<u8> = vec![0u8; cfg_size];
hb.copy_into(&mut cfg_buffer);
cfg_buffer
}
pub fn build(&self) -> Result<TracingSession, TracingSessionError> {
let config = self.build_proto_config();
let mut ts = TracingSession::in_process()?;
ts.setup(&config);
Ok(ts)
}
}
#[test]
fn fnv1a_hash() {
assert_eq!(fnv1a("mytrack".as_bytes()), 9332035348890697650);
}
#[test]
fn unlikely_conditional() {
if __unlikely!(fnv1a("mystring".as_bytes()) == 0) {
unreachable!();
}
}
}