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
use itertools::Itertools;
use std::{collections::VecDeque, sync::Once};
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt, EnvFilter};

const ENABLE_OPENTELEM_ENV_VAR: &str = "TEMPORAL_ENABLE_OPENTELEMETRY";
static TRACING_INIT: Once = Once::new();

/// Initialize tracing subscribers and output. Core will not call this itself, it exists here so
/// that consumers and tests have an easy way to initialize tracing.
pub fn tracing_init() {
    TRACING_INIT.call_once(|| {
        let opentelem_on = std::env::var(ENABLE_OPENTELEM_ENV_VAR).is_ok();

        let filter_layer = EnvFilter::try_from_default_env()
            .or_else(|_| EnvFilter::try_new("info"))
            .unwrap();

        if opentelem_on {
            // Not all low-down unit tests use Tokio
            #[cfg(test)]
            let tracer = opentelemetry_jaeger::new_pipeline()
                .with_service_name("coresdk")
                .install_simple()
                .unwrap();

            #[cfg(not(test))]
            let tracer = opentelemetry_jaeger::new_pipeline()
                .with_service_name("coresdk")
                .install_batch(opentelemetry::runtime::Tokio)
                .unwrap();

            let opentelemetry = tracing_opentelemetry::layer().with_tracer(tracer);

            tracing_subscriber::registry()
                .with(opentelemetry)
                .with(filter_layer)
                .with(tracing_subscriber::fmt::layer().with_target(false).pretty())
                .try_init()
                .unwrap();
        } else {
            // Because these types don't compose nicely we must repeat ourselves in these branches
            let reg = tracing_subscriber::registry()
                .with(filter_layer)
                .with(tracing_subscriber::fmt::layer().with_target(false).pretty());
            tracing::subscriber::set_global_default(reg).unwrap();
        };
    });
}

/// A trait for using [Display] on the contents of vecs, etc, which don't implement it.
///
/// Dislike this, but, there doesn't seem to be a great alternative. Calling itertools format
/// inline in an `event!` macro can panic because it gets evaluated twice somehow.
pub(crate) trait VecDisplayer {
    fn display(&self) -> String;
}

impl<T> VecDisplayer for Vec<T>
where
    T: std::fmt::Display,
{
    fn display(&self) -> String {
        format!("[{}]", self.iter().format(","))
    }
}

impl<T> VecDisplayer for VecDeque<T>
where
    T: std::fmt::Display,
{
    fn display(&self) -> String {
        format!("[{}]", self.iter().format(","))
    }
}