1use std::io::{self, Write};
2use tokio::io::{AsyncWrite, AsyncWriteExt};
3use tracing_subscriber::{fmt::format::FmtSpan, prelude::*, util::SubscriberInitExt, EnvFilter};
4
5use crate::environment::Environment;
6
7struct BlockingWrite<W: AsyncWrite>(W);
8
9impl<W: AsyncWrite + Unpin> Write for BlockingWrite<W> {
10 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
11 #[cfg(not(target_arch = "wasm32"))]
12 {
13 futures::executor::block_on(self.0.write(buf))
14 }
15
16 #[cfg(target_arch = "wasm32")]
19 {
20 use futures::FutureExt;
21
22 let _ = self.0.write_all(buf).boxed_local().poll_unpin(
23 &mut futures::task::Context::from_waker(&futures::task::noop_waker()),
24 );
25
26 Ok(buf.len())
27 }
28 }
29
30 fn flush(&mut self) -> io::Result<()> {
31 #[cfg(not(target_arch = "wasm32"))]
32 {
33 futures::executor::block_on(self.0.flush())
34 }
35
36 #[cfg(target_arch = "wasm32")]
39 {
40 use futures::FutureExt;
41
42 let _ =
43 self.0
44 .flush()
45 .boxed_local()
46 .poll_unpin(&mut futures::task::Context::from_waker(
47 &futures::task::noop_waker(),
48 ));
49
50 Ok(())
51 }
52 }
53}
54
55pub fn setup_stderr_logging(e: impl Environment, spans: bool, verbose: bool, colors: Option<bool>) {
56 let span_events = if spans {
57 FmtSpan::NEW | FmtSpan::CLOSE
58 } else {
59 FmtSpan::NONE
60 };
61
62 let registry = tracing_subscriber::registry();
63
64 let env_filter = match e.env_var("RUST_LOG") {
65 Some(log) => EnvFilter::new(log),
66 None => EnvFilter::default().add_directive(tracing::Level::INFO.into()),
67 };
68
69 if verbose {
70 registry
71 .with(env_filter)
72 .with(
73 tracing_subscriber::fmt::layer()
74 .with_ansi(match colors {
75 None => e.atty_stderr(),
76 Some(v) => v,
77 })
78 .with_span_events(span_events)
79 .event_format(tracing_subscriber::fmt::format().pretty().with_ansi(
80 match colors {
81 None => e.atty_stderr(),
82 Some(v) => v,
83 },
84 ))
85 .with_writer(move || BlockingWrite(e.stderr())),
86 )
87 .try_init()
88 .ok();
89 } else {
90 registry
91 .with(env_filter)
92 .with(
93 tracing_subscriber::fmt::layer()
94 .with_ansi(match colors {
95 None => e.atty_stderr(),
96 Some(v) => v,
97 })
98 .event_format(
99 tracing_subscriber::fmt::format()
100 .compact()
101 .with_source_location(false)
102 .with_target(false)
103 .without_time()
104 .with_ansi(match colors {
105 None => e.atty_stderr(),
106 Some(v) => v,
107 }),
108 )
109 .without_time()
110 .with_file(false)
111 .with_line_number(false)
112 .with_span_events(span_events)
113 .with_writer(move || BlockingWrite(e.stderr())),
114 )
115 .try_init()
116 .ok();
117 }
118}