use crate::metric_primitive::MetricPrimitive; use crate::timestamp::Timestamp; use serde::{Deserialize, Serialize}; use std::collections::BTreeMap; #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct ParamDeclaration { pub name: String, pub message_match_regex: String, pub capture_group: String, #[serde(default)] pub json_field_path: Option, pub kind: MetricPrimitiveKind, #[serde(default)] pub elapsed_since_last: bool, #[serde(default)] pub auto_derived: bool, #[serde(default)] pub log_stream_gated: bool, } pub fn extract_json_field(text: &str, field_path: &str) -> Option { let root: serde_json::Value = serde_json::from_str(text).ok()?; let mut current = root.as_object()?; let mut segments = field_path.split('.').peekable(); loop { let segment = segments.next()?; let next_value = current.get(segment)?; if segments.peek().is_none() { return match next_value { serde_json::Value::String(s) => Some(s.clone()), serde_json::Value::Number(n) => Some(n.to_string()), serde_json::Value::Bool(b) => Some(b.to_string()), _ => None, }; } current = next_value.as_object()?; } } pub fn flatten_json_object(text: &str) -> Vec<(String, String)> { let Ok(serde_json::Value::Object(root)) = serde_json::from_str::(text) else { return Vec::new(); }; let mut results = Vec::new(); flatten_json_object_into(&root, "", &mut results); results } fn flatten_json_object_into( object: &serde_json::Map, prefix: &str, results: &mut Vec<(String, String)>, ) { for (key, value) in object { let path = if prefix.is_empty() { key.clone() } else { format!("{prefix}.{key}") }; match value { serde_json::Value::String(s) => results.push((path, s.clone())), serde_json::Value::Number(n) => results.push((path, n.to_string())), serde_json::Value::Bool(b) => results.push((path, b.to_string())), serde_json::Value::Object(nested) => flatten_json_object_into(nested, &path, results), serde_json::Value::Null | serde_json::Value::Array(_) => {} } } } #[allow(dead_code)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] #[serde(rename_all = "lowercase")] pub enum MetricPrimitiveKind { String, Number, Timestamp, Duration, Boolean, } #[allow(dead_code)] #[derive(Debug, Clone, Serialize)] pub enum DataValue { LogLiteral { text: String }, ParamDeclaration(ParamDeclaration), MetricDeclaration { message_match_regex: String, label_params: Vec, value_param: Option, matched_labels: Option>, unmatched_labels: Option>, }, BucketValue { values: Vec<(u64, Timestamp, MetricPrimitive)>, }, LastEventTimestamp { timestamp: Timestamp, }, }