use crate::TraceHeaders;
pub const TRACE_CONTEXT_VAR_NAME: &str = "TRACE_CONTEXT";
pub const RERUN_SESSION_VAR_NAME: &str = "RERUN_SESSION_ID";
pub fn get_trace_context_var(py: pyo3::Python<'_>) -> pyo3::PyResult<pyo3::Bound<'_, pyo3::PyAny>> {
use pyo3::prelude::*;
static CONTEXT_VAR: parking_lot::Mutex<Option<pyo3::Py<pyo3::PyAny>>> =
parking_lot::Mutex::new(None);
let mut guard = CONTEXT_VAR.lock();
if let Some(var) = guard.as_ref() {
return Ok(var.bind(py).clone());
}
let module = py.import("contextvars")?;
let contextvar_class = module.getattr("ContextVar")?;
let trace_ctx_var = contextvar_class.call1((TRACE_CONTEXT_VAR_NAME,))?;
let trace_ctx_unbound = trace_ctx_var.clone().unbind();
*guard = Some(trace_ctx_unbound);
Ok(trace_ctx_var)
}
pub fn extract_trace_context_from_contextvar(py: pyo3::Python<'_>) -> TraceHeaders {
use pyo3::prelude::*;
use pyo3::types::PyDict;
fn try_extract(py: pyo3::Python<'_>) -> PyResult<TraceHeaders> {
let context_var = get_trace_context_var(py)?;
match context_var.call_method0("get") {
Ok(trace_data) => {
if let Ok(dict) = trace_data.downcast::<PyDict>() {
let traceparent = dict
.get_item(TraceHeaders::TRACEPARENT_KEY)?
.and_then(|v| v.extract::<String>().ok())
.unwrap_or_default();
let tracestate = dict
.get_item(TraceHeaders::TRACESTATE_KEY)?
.and_then(|v| v.extract::<String>().ok());
let headers = TraceHeaders {
traceparent,
tracestate,
};
tracing::debug!("Trace headers: {:?}", headers);
Ok(headers)
} else {
Ok(TraceHeaders::empty())
}
}
Err(_) => Ok(TraceHeaders::empty()),
}
}
try_extract(py).unwrap_or_else(|err| {
tracing::debug!("Failed to extract trace context: {err}");
TraceHeaders::empty()
})
}
pub fn get_rerun_session_var(py: pyo3::Python<'_>) -> pyo3::PyResult<pyo3::Bound<'_, pyo3::PyAny>> {
use pyo3::prelude::*;
static CONTEXT_VAR: parking_lot::Mutex<Option<pyo3::Py<pyo3::PyAny>>> =
parking_lot::Mutex::new(None);
let mut guard = CONTEXT_VAR.lock();
if let Some(var) = guard.as_ref() {
return Ok(var.bind(py).clone());
}
let module = py.import("contextvars")?;
let contextvar_class = module.getattr("ContextVar")?;
let kwargs = pyo3::types::PyDict::new(py);
kwargs.set_item("default", py.None())?;
let var = contextvar_class.call((RERUN_SESSION_VAR_NAME,), Some(&kwargs))?;
*guard = Some(var.clone().unbind());
Ok(var)
}
pub fn current_rerun_session_id_from_contextvar(
py: pyo3::Python<'_>,
) -> Option<crate::RerunTracingSessionId> {
use pyo3::prelude::*;
let var = get_rerun_session_var(py).ok()?;
let value = var.call_method0("get").ok()?;
if value.is_none() {
return None;
}
let raw = value.extract::<String>().ok()?;
crate::RerunTracingSessionId::parse(&raw)
}