Split src/ into an api/cli/engine/config module hierarchy
- src/api/: HTTP router + DTOs + the MCP server (the HTTP/MCP-facing surface): mod.rs (formerly api.rs), dto.rs, mcp_server.rs. - src/cli/: argument parsing and process entry (formerly inline in main.rs) plus session registry: mod.rs, sessions.rs. main.rs is now a thin entry point that just declares modules and calls cli::run(). - src/engine/: the actor + everything it depends on to parse/index/ query log lines: mod.rs (formerly engine.rs), alerts.rs, promql.rs, rate.rs, ingest.rs, logfmt.rs, filter_parser.rs/.pest, filter_datetime.rs, index_key.rs, data_value.rs, metric_primitive.rs, timestamp.rs. - src/config/: persisted configuration: mod.rs (formerly settings.rs), profile.rs. - src/consts.rs stays at the crate root, used from every module above. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01A1ZJ3SrayzLzVndhVq9BmS
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
311713986a
commit
a810ecf396
@@ -0,0 +1,96 @@
|
||||
use crate::engine::metric_primitive::MetricPrimitive;
|
||||
use crate::engine::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<String>,
|
||||
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<String> {
|
||||
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::<serde_json::Value>(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<String, serde_json::Value>,
|
||||
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<String>,
|
||||
value_param: Option<String>,
|
||||
matched_labels: Option<BTreeMap<String, String>>,
|
||||
unmatched_labels: Option<BTreeMap<String, String>>,
|
||||
},
|
||||
BucketValue {
|
||||
values: Vec<(u64, Timestamp, MetricPrimitive)>,
|
||||
},
|
||||
LastEventTimestamp {
|
||||
timestamp: Timestamp,
|
||||
},
|
||||
}
|
||||
Reference in New Issue
Block a user