1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
use serde::Deserialize; use thiserror::Error; pub mod record; #[cfg(feature = "asm")] #[cfg_attr(target_os = "linux", path = "empty.rs")] #[cfg_attr(target_os = "macos", path = "linker.rs")] #[cfg_attr( all(not(target_os = "macos"), not(target_os = "linux")), path = "no-linker.rs" )] mod internal; #[cfg(not(feature = "asm"))] #[cfg(path = "empty.rs")] mod internal; /// Register an application's probe points with DTrace. /// /// This function collects information about the probe points defined in an application and ensures /// that they are registered with the DTrace kernel module. It is critical to note that if this /// method is not called (at some point in an application), _no probes will be visible_ via the /// `dtrace(1)` command line tool. /// /// NOTE: This method presents a quandary for library developers, as consumers of their library may /// forget to (or choose not to) call this function. There are potential workarounds for this /// problem, but each comes with significant tradeoffs. Library developers are encouraged to /// re-export this function and document to their users that this function should be called to /// guarantee that the library's probes are registered. pub fn register_probes() -> Result<(), Error> { crate::internal::register_probes() } /// Errors related to building DTrace probes into Rust code #[derive(Error, Debug)] pub enum Error { /// Error during parsing of DTrace provider source #[error(transparent)] ParseError(#[from] dtrace_parser::DTraceError), /// Error reading or writing files, or registering DTrace probes #[error(transparent)] IO(#[from] std::io::Error), /// Error related to environment variables, e.g., while running a build script #[error(transparent)] Env(#[from] std::env::VarError), /// An error occurred extracting probe information from the encoded object file sections #[error("The file is not a valid object file")] InvalidFile, } #[derive(Default, Debug, Deserialize)] pub struct CompileProvidersConfig { pub format: Option<String>, } fn format_probe( format: &Option<String>, provider_name: &str, probe_name: &str, ) -> proc_macro2::Ident { if let Some(fmt) = format { quote::format_ident!( "{}", fmt.replace("{provider}", provider_name) .replace("{probe}", probe_name) ) } else { quote::format_ident!("{}_{}", provider_name, probe_name) } } // Compile DTrace provider source code into Rust. // // This function parses a provider definition, and, for each probe, a corresponding Rust macro is // returned. This macro may be called throughout Rust code to fire the corresponding DTrace probe // (if it's enabled). See [probe_test_macro] for a detailed example. // // [probe_test_macro]: https://github.com/oxidecomputer/usdt/tree/master/probe-test-macro pub fn compile_providers( source: &str, config: &CompileProvidersConfig, ) -> Result<proc_macro2::TokenStream, Error> { crate::internal::compile_providers(source, config) }