Line data Source code
1 : use std::collections::HashMap;
2 : use tracing::info;
3 : use tracing_subscriber::layer::SubscriberExt;
4 : use tracing_subscriber::prelude::*;
5 :
6 : /// Initialize logging to stderr, and OpenTelemetry tracing and exporter.
7 : ///
8 : /// Logging is configured using either `default_log_level` or
9 : /// `RUST_LOG` environment variable as default log level.
10 : ///
11 : /// OpenTelemetry is configured with OTLP/HTTP exporter. It picks up
12 : /// configuration from environment variables. For example, to change the destination,
13 : /// set `OTEL_EXPORTER_OTLP_ENDPOINT=http://jaeger:4318`. See
14 : /// `tracing-utils` package description.
15 : ///
16 0 : pub async fn init_tracing_and_logging(default_log_level: &str) -> anyhow::Result<()> {
17 0 : // Initialize Logging
18 0 : let env_filter = tracing_subscriber::EnvFilter::try_from_default_env()
19 0 : .unwrap_or_else(|_| tracing_subscriber::EnvFilter::new(default_log_level));
20 0 :
21 0 : let fmt_layer = tracing_subscriber::fmt::layer()
22 0 : .with_ansi(false)
23 0 : .with_target(false)
24 0 : .with_writer(std::io::stderr);
25 :
26 : // Initialize OpenTelemetry
27 0 : let otlp_layer =
28 0 : tracing_utils::init_tracing("compute_ctl", tracing_utils::ExportConfig::default()).await;
29 :
30 : // Put it all together
31 0 : tracing_subscriber::registry()
32 0 : .with(env_filter)
33 0 : .with(otlp_layer)
34 0 : .with(fmt_layer)
35 0 : .init();
36 0 : tracing::info!("logging and tracing started");
37 :
38 0 : utils::logging::replace_panic_hook_with_tracing_panic_hook().forget();
39 0 :
40 0 : Ok(())
41 0 : }
42 :
43 : /// Replace all newline characters with a special character to make it
44 : /// easier to grep for log messages.
45 0 : pub fn inlinify(s: &str) -> String {
46 0 : s.replace('\n', "\u{200B}")
47 0 : }
48 :
49 0 : pub fn startup_context_from_env() -> Option<opentelemetry::Context> {
50 0 : // Extract OpenTelemetry context for the startup actions from the
51 0 : // TRACEPARENT and TRACESTATE env variables, and attach it to the current
52 0 : // tracing context.
53 0 : //
54 0 : // This is used to propagate the context for the 'start_compute' operation
55 0 : // from the neon control plane. This allows linking together the wider
56 0 : // 'start_compute' operation that creates the compute container, with the
57 0 : // startup actions here within the container.
58 0 : //
59 0 : // There is no standard for passing context in env variables, but a lot of
60 0 : // tools use TRACEPARENT/TRACESTATE, so we use that convention too. See
61 0 : // https://github.com/open-telemetry/opentelemetry-specification/issues/740
62 0 : //
63 0 : // Switch to the startup context here, and exit it once the startup has
64 0 : // completed and Postgres is up and running.
65 0 : //
66 0 : // If this pod is pre-created without binding it to any particular endpoint
67 0 : // yet, this isn't the right place to enter the startup context. In that
68 0 : // case, the control plane should pass the tracing context as part of the
69 0 : // /configure API call.
70 0 : //
71 0 : // NOTE: This is supposed to only cover the *startup* actions. Once
72 0 : // postgres is configured and up-and-running, we exit this span. Any other
73 0 : // actions that are performed on incoming HTTP requests, for example, are
74 0 : // performed in separate spans.
75 0 : //
76 0 : // XXX: If the pod is restarted, we perform the startup actions in the same
77 0 : // context as the original startup actions, which probably doesn't make
78 0 : // sense.
79 0 : let mut startup_tracing_carrier: HashMap<String, String> = HashMap::new();
80 0 : if let Ok(val) = std::env::var("TRACEPARENT") {
81 0 : startup_tracing_carrier.insert("traceparent".to_string(), val);
82 0 : }
83 0 : if let Ok(val) = std::env::var("TRACESTATE") {
84 0 : startup_tracing_carrier.insert("tracestate".to_string(), val);
85 0 : }
86 0 : if !startup_tracing_carrier.is_empty() {
87 : use opentelemetry::propagation::TextMapPropagator;
88 : use opentelemetry_sdk::propagation::TraceContextPropagator;
89 0 : info!("got startup tracing context from env variables");
90 0 : Some(TraceContextPropagator::new().extract(&startup_tracing_carrier))
91 : } else {
92 0 : None
93 : }
94 0 : }
|