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