1use std::{cell::RefCell, env, path::PathBuf};
30
31use anyhow::anyhow;
32use napi::bindgen_prelude::{External, Status};
33use tracing_chrome::{ChromeLayerBuilder, FlushGuard};
34use tracing_subscriber::{Layer, filter, layer::SubscriberExt, util::SubscriberInitExt};
35
36#[napi]
37pub fn get_target_triple() -> &'static str {
38 env!("VERGEN_CARGO_TARGET_TRIPLE")
39}
40
41pub trait MapErr<T>: Into<Result<T, anyhow::Error>> {
42 fn convert_err(self) -> napi::Result<T> {
43 self.into()
44 .map_err(|err| napi::Error::new(Status::GenericFailure, format!("{err:?}")))
45 }
46}
47
48impl<T> MapErr<T> for Result<T, anyhow::Error> {}
49
50#[cfg(any(feature = "__internal_dhat-heap", feature = "__internal_dhat-ad-hoc"))]
53#[non_exhaustive]
54pub struct DhatProfilerGuard(dhat::Profiler);
55
56#[cfg(not(any(feature = "__internal_dhat-heap", feature = "__internal_dhat-ad-hoc")))]
61#[non_exhaustive]
62pub struct DhatProfilerGuard;
63
64impl DhatProfilerGuard {
65 pub fn try_init() -> Option<Self> {
67 #[cfg(feature = "__internal_dhat-heap")]
68 {
69 println!("[dhat-heap]: Initializing heap profiler");
70 Some(Self(dhat::Profiler::new_heap()))
71 }
72 #[cfg(feature = "__internal_dhat-ad-hoc")]
73 {
74 println!("[dhat-ad-hoc]: Initializing ad-hoc profiler");
75 Some(Self(dhat::Profiler::new_ad_hoc()))
76 }
77 #[cfg(not(any(feature = "__internal_dhat-heap", feature = "__internal_dhat-ad-hoc")))]
78 {
79 None
80 }
81 }
82}
83
84impl Drop for DhatProfilerGuard {
85 fn drop(&mut self) {
86 #[cfg(any(feature = "__internal_dhat-heap", feature = "__internal_dhat-ad-hoc"))]
87 println!("[dhat]: Teardown profiler");
88 }
89}
90
91#[napi]
94pub fn init_custom_trace_subscriber(
95 trace_out_file_path: Option<String>,
96) -> napi::Result<External<RefCell<Option<FlushGuard>>>> {
97 let trace_out_file_path = trace_out_file_path.map(PathBuf::from);
98
99 let mut layer = ChromeLayerBuilder::new().include_args(true);
100 if let Some(trace_out_file) = trace_out_file_path {
101 let dir = trace_out_file
102 .parent()
103 .ok_or_else(|| anyhow!("Not able to find path to the trace output"))
104 .convert_err()?;
105 std::fs::create_dir_all(dir)?;
106
107 layer = layer.file(trace_out_file);
108 }
109
110 let (chrome_layer, guard) = layer.build();
111 tracing_subscriber::registry()
112 .with(chrome_layer.with_filter(filter::filter_fn(|metadata| {
113 !metadata.target().contains("cranelift") && !metadata.name().contains("log ")
114 })))
115 .try_init()
116 .expect("Failed to register tracing subscriber");
117
118 let guard_cell = RefCell::new(Some(guard));
119 Ok(External::new(guard_cell))
120}
121
122#[napi]
126pub fn teardown_trace_subscriber(guard_external: External<RefCell<Option<FlushGuard>>>) {
127 let guard_cell = &*guard_external;
128
129 if let Some(guard) = guard_cell.take() {
130 drop(guard);
131 }
132}