use std::time::Instant;
use crate::config::{OmHintPolicy, RETRIEVAL_BACKEND_MEMORY, RETRIEVAL_BACKEND_POLICY_MEMORY_ONLY};
use crate::error::AxiomError;
use crate::models::{FindResult, SearchBudget};
use super::OmSearchMetrics;
use super::result::{append_query_plan_note, budget_to_json};
#[derive(Debug, Clone)]
pub(super) struct SearchRequestLogInput<'a> {
pub(super) query: &'a str,
pub(super) requested_limit: usize,
pub(super) session: Option<&'a str>,
pub(super) budget: Option<&'a SearchBudget>,
pub(super) score_threshold: Option<f32>,
pub(super) min_match_tokens: Option<usize>,
pub(super) metrics: OmSearchMetrics,
pub(super) hint_policy: OmHintPolicy,
pub(super) typed_edge_enrichment: bool,
pub(super) result_count: Option<usize>,
}
#[derive(Debug)]
pub(super) struct SearchRequestLogEvent<'a> {
pub(super) request_id: &'a str,
pub(super) started: Instant,
pub(super) target_uri: Option<&'a str>,
pub(super) trace_id: Option<&'a str>,
pub(super) status: &'static str,
pub(super) error: Option<&'a AxiomError>,
pub(super) details: serde_json::Value,
}
pub(super) fn annotate_om_query_plan_visibility(
result: &mut FindResult,
metrics: &OmSearchMetrics,
policy: OmHintPolicy,
) {
if metrics.observer_trigger_count == 0
&& metrics.reflector_trigger_count == 0
&& metrics.session_recent_hint_count == 0
&& metrics.session_hint_count_final == 0
&& metrics.om_filtered_message_count == 0
&& !metrics.om_hint_reader_snapshot_v2
{
return;
}
if metrics.om_hint_reader_snapshot_v2 {
append_query_plan_note(result, "om_hint_reader:snapshot_v2");
append_query_plan_note(
result,
&format!(
"om_snapshot_buffered_chunks:{}",
metrics.om_snapshot_buffered_chunk_count
),
);
if metrics.om_hint_compaction_priority_v2 {
append_query_plan_note(result, "om_hint_compaction:priority_v2");
append_query_plan_note(
result,
&format!(
"om_hint_high_priority_selected:{}",
metrics.om_hint_high_priority_selected_count
),
);
append_query_plan_note(
result,
&format!(
"om_hint_current_task_reserved:{}",
u8::from(metrics.om_hint_current_task_reserved)
),
);
if !metrics.om_snapshot_visible_entry_ids.is_empty() {
append_query_plan_note(
result,
&format!(
"om_snapshot_visible_entries:{}",
metrics.om_snapshot_visible_entry_ids.join(",")
),
);
}
if !metrics.om_snapshot_visible_activated_entry_ids.is_empty() {
append_query_plan_note(
result,
&format!(
"om_snapshot_visible_activated_entries:{}",
metrics.om_snapshot_visible_activated_entry_ids.join(",")
),
);
}
if !metrics.om_snapshot_visible_buffered_entry_ids.is_empty() {
append_query_plan_note(
result,
&format!(
"om_snapshot_visible_buffered_entries:{}",
metrics.om_snapshot_visible_buffered_entry_ids.join(",")
),
);
}
}
if !metrics.om_snapshot_buffered_chunk_ids.is_empty() {
append_query_plan_note(
result,
&format!(
"om_snapshot_buffered_chunk_ids:{}",
metrics.om_snapshot_buffered_chunk_ids.join(",")
),
);
}
}
append_query_plan_note(
result,
&format!("om_hint_applied:{}", u8::from(metrics.om_hint_applied)),
);
append_query_plan_note(
result,
&format!("session_hints_final:{}", metrics.session_hint_count_final),
);
append_query_plan_note(
result,
&format!("observer_triggers:{}", metrics.observer_trigger_count),
);
append_query_plan_note(
result,
&format!("reflector_triggers:{}", metrics.reflector_trigger_count),
);
append_query_plan_note(
result,
&format!("om_filtered_messages:{}", metrics.om_filtered_message_count),
);
append_query_plan_note(
result,
&format!(
"om_hint_policy:{}/{}/{}/{}",
policy.recent_hint_limit,
policy.total_hint_limit,
policy.keep_recent_with_om,
policy.context_max_messages
),
);
}
fn hint_policy_to_json(policy: OmHintPolicy) -> serde_json::Value {
serde_json::json!({
"context_max_archives": policy.context_max_archives,
"context_max_messages": policy.context_max_messages,
"recent_hint_limit": policy.recent_hint_limit,
"total_hint_limit": policy.total_hint_limit,
"keep_recent_with_om": policy.keep_recent_with_om,
})
}
pub(super) fn search_request_details(input: SearchRequestLogInput<'_>) -> serde_json::Value {
let SearchRequestLogInput {
query,
requested_limit,
session,
budget,
score_threshold,
min_match_tokens,
metrics,
hint_policy,
typed_edge_enrichment,
result_count,
} = input;
let mut details = serde_json::json!({
"query": query,
"limit": requested_limit,
"session": session,
"budget": budget_to_json(budget),
"score_threshold": score_threshold,
"min_match_tokens": min_match_tokens,
"retrieval_backend": RETRIEVAL_BACKEND_MEMORY,
"retrieval_backend_policy": RETRIEVAL_BACKEND_POLICY_MEMORY_ONLY,
"context_tokens_before_om": metrics.context_tokens_before_om,
"context_tokens_after_om": metrics.context_tokens_after_om,
"observation_tokens_active": metrics.observation_tokens_active,
"observer_trigger_count": metrics.observer_trigger_count,
"reflector_trigger_count": metrics.reflector_trigger_count,
"om_hint_applied": metrics.om_hint_applied,
"om_hint_reader": if metrics.om_hint_reader_snapshot_v2 { "snapshot_v2" } else { "none" },
"om_snapshot_buffered_chunk_count": metrics.om_snapshot_buffered_chunk_count,
"om_snapshot_buffered_chunk_ids": metrics.om_snapshot_buffered_chunk_ids,
"om_hint_compaction": if metrics.om_hint_compaction_priority_v2 { "priority_v2" } else { "none" },
"om_hint_high_priority_selected_count": metrics.om_hint_high_priority_selected_count,
"om_snapshot_visible_entry_ids": metrics.om_snapshot_visible_entry_ids,
"om_hint_selected_entry_ids": metrics.om_snapshot_visible_entry_ids,
"om_snapshot_visible_activated_entry_ids": metrics.om_snapshot_visible_activated_entry_ids,
"om_snapshot_visible_buffered_entry_ids": metrics.om_snapshot_visible_buffered_entry_ids,
"om_hint_current_task_reserved": metrics.om_hint_current_task_reserved,
"session_recent_hint_count": metrics.session_recent_hint_count,
"session_hint_count_final": metrics.session_hint_count_final,
"om_filtered_message_count": metrics.om_filtered_message_count,
"om_hint_policy": hint_policy_to_json(hint_policy),
"typed_edge_enrichment": typed_edge_enrichment,
});
if let Some(result_count) = result_count {
details["result_count"] = serde_json::json!(result_count);
}
details
}