solar_cli/
utils.rs

1//! Utility functions used by the Solar CLI.
2
3use solar_interface::diagnostics::DiagCtxt;
4
5#[cfg(all(feature = "jemalloc", unix))]
6use tikv_jemallocator as _;
7
8// We use jemalloc for performance reasons.
9// Except in tests, where we spawn a ton of processes and jemalloc has a higher startup cost.
10cfg_if::cfg_if! {
11    if #[cfg(all(feature = "jemalloc", unix, not(debug_assertions)))] {
12        type AllocatorInner = tikv_jemallocator::Jemalloc;
13    } else {
14        type AllocatorInner = std::alloc::System;
15    }
16}
17
18cfg_if::cfg_if! {
19    if #[cfg(feature = "tracy-allocator")] {
20        pub(super) type WrappedAllocator = tracing_tracy::client::ProfiledAllocator<AllocatorInner>;
21        pub(super) const fn new_wrapped_allocator() -> WrappedAllocator {
22            Allocator::new(AllocatorInner {}, 100)
23        }
24    } else {
25        pub(super) type WrappedAllocator = AllocatorInner;
26        pub(super) const fn new_wrapped_allocator() -> WrappedAllocator {
27            AllocatorInner {}
28        }
29    }
30}
31
32/// The global allocator used by the compiler.
33pub type Allocator = WrappedAllocator;
34
35/// Create a new instance of the global allocator.
36pub const fn new_allocator() -> Allocator {
37    new_wrapped_allocator()
38}
39
40/// Initialize the tracing logger.
41#[must_use]
42pub fn init_logger() -> impl Sized {
43    #[cfg(not(feature = "tracing"))]
44    {
45        if std::env::var_os("RUST_LOG").is_some() {
46            let msg = "`RUST_LOG` is set, but \"tracing\" support was not enabled at compile time";
47            DiagCtxt::new_early().warn(msg).emit();
48        }
49        if std::env::var_os("SOLAR_PROFILE").is_some() {
50            let msg =
51                "`SOLAR_PROFILE` is set, but \"tracing\" support was not enabled at compile time";
52            DiagCtxt::new_early().warn(msg).emit();
53        }
54    }
55
56    #[cfg(feature = "tracing")]
57    match try_init_logger() {
58        Ok(guard) => guard,
59        Err(e) => DiagCtxt::new_early().fatal(e).emit(),
60    }
61}
62
63#[cfg(feature = "tracing")]
64fn try_init_logger() -> Result<impl Sized, String> {
65    use tracing_subscriber::prelude::*;
66
67    let (profile_layer, guard) = match std::env::var("SOLAR_PROFILE").as_deref() {
68        Ok("chrome") => {
69            if !cfg!(feature = "tracing-chrome") {
70                return Err("chrome profiler support is not compiled in".to_string());
71            }
72            let (layer, guard) = chrome_layer();
73            (Some(layer.boxed()), Some(guard))
74        }
75        Ok("tracy") => {
76            if !cfg!(feature = "tracy") {
77                return Err("tracy profiler support is not compiled in".to_string());
78            }
79            (Some(tracy_layer().boxed()), Default::default())
80        }
81        Ok(s) => return Err(format!("unknown profiler '{s}'; valid values: 'chrome', 'tracy'")),
82        Err(_) => Default::default(),
83    };
84    tracing_subscriber::Registry::default()
85        .with(tracing_subscriber::EnvFilter::from_default_env())
86        .with(profile_layer)
87        .with(tracing_subscriber::fmt::layer())
88        .try_init()
89        .map(|()| guard)
90        .map_err(|e| e.to_string())
91}
92
93#[cfg(feature = "tracing")]
94#[cfg(feature = "tracy")]
95fn tracy_layer() -> tracing_tracy::TracyLayer<impl tracing_tracy::Config> {
96    struct Config(tracing_subscriber::fmt::format::DefaultFields);
97    impl tracing_tracy::Config for Config {
98        type Formatter = tracing_subscriber::fmt::format::DefaultFields;
99        fn formatter(&self) -> &Self::Formatter {
100            &self.0
101        }
102        fn format_fields_in_zone_name(&self) -> bool {
103            false
104        }
105    }
106
107    tracing_tracy::client::register_demangler!();
108
109    tracing_tracy::TracyLayer::new(Config(Default::default()))
110}
111
112#[cfg(feature = "tracing")]
113#[cfg(not(feature = "tracy"))]
114fn tracy_layer() -> tracing_subscriber::layer::Identity {
115    tracing_subscriber::layer::Identity::new()
116}
117
118#[cfg(feature = "tracing")]
119#[cfg(feature = "tracing-chrome")]
120fn chrome_layer<S>() -> (tracing_chrome::ChromeLayer<S>, tracing_chrome::FlushGuard)
121where
122    S: tracing::Subscriber
123        + for<'span> tracing_subscriber::registry::LookupSpan<'span>
124        + Send
125        + Sync,
126{
127    tracing_chrome::ChromeLayerBuilder::new().include_args(true).build()
128}
129
130#[cfg(feature = "tracing")]
131#[cfg(not(feature = "tracing-chrome"))]
132fn chrome_layer() -> (tracing_subscriber::layer::Identity, ()) {
133    (tracing_subscriber::layer::Identity::new(), ())
134}
135
136/*
137pub(crate) fn env_to_bool(value: Option<&std::ffi::OsStr>) -> bool {
138    value.is_some_and(|value| value == "1" || value == "true")
139}
140*/