1use serde::{Deserialize, Serialize};
2use serde_json::Value;
3use std::collections::HashMap;
4use std::path::Path;
5use std::sync::Mutex;
6
7lazy_static::lazy_static! {
8 static ref REPLAY_CONTEXT: Mutex<Option<ReplayConfig>> = Mutex::new(None);
9}
10
11#[derive(Debug, Clone, Default, Serialize, Deserialize)]
12pub struct ReplayConfig {
13 pub mocked_spans: HashMap<String, Value>,
14 pub block_side_effects: bool,
15}
16
17impl ReplayConfig {
18 pub fn load_from_env() -> Option<Self> {
19 if let Ok(path_str) = std::env::var("TRACE_WEFT_REPLAY_FILE") {
20 let path = Path::new(&path_str);
21 if path.exists()
22 && let Ok(content) = std::fs::read_to_string(path)
23 {
24 if let Ok(config) = serde_json::from_str::<Self>(&content) {
25 tracing::info!("Loaded TraceWeft replay config from {}", path_str);
26 return Some(config);
27 } else {
28 tracing::error!("Failed to parse TraceWeft replay config at {}", path_str);
29 }
30 }
31 }
32 None
33 }
34}
35
36pub fn init_replay(config: ReplayConfig) {
37 if let Ok(mut ctx) = REPLAY_CONTEXT.lock() {
38 *ctx = Some(config);
39 }
40}
41
42pub fn get_mocked_output(span_name: &str) -> Option<Value> {
43 if let Ok(ctx) = REPLAY_CONTEXT.lock()
44 && let Some(config) = ctx.as_ref()
45 {
46 return config.mocked_spans.get(span_name).cloned();
47 }
48 None
49}