systemprompt_cli/commands/admin/agents/
logs_db.rs1use std::sync::Arc;
2
3use anyhow::{Context, Result, anyhow};
4use systemprompt_database::DbPool;
5use systemprompt_loader::ConfigLoader;
6use systemprompt_logging::LoggingRepository;
7use systemprompt_runtime::AppContext;
8
9use super::logs::LogsArgs;
10use super::types::AgentLogsOutput;
11use crate::CliConfig;
12use crate::shared::CommandOutput;
13
14pub(super) async fn execute_db_mode(args: &LogsArgs, config: &CliConfig) -> Result<CommandOutput> {
15 let ctx = Arc::new(
16 AppContext::new()
17 .await
18 .context("Failed to initialize app context")?,
19 );
20 execute_db_mode_with_pool(args, ctx.db_pool(), config).await
21}
22
23pub async fn execute_db_mode_with_pool(
24 args: &LogsArgs,
25 pool: &DbPool,
26 _config: &CliConfig,
27) -> Result<CommandOutput> {
28 let repo = LoggingRepository::new(pool)?;
29
30 let patterns = match &args.agent {
31 Some(agent) => build_agent_patterns(agent),
32 None => build_all_agent_patterns()?,
33 };
34
35 let entries = repo
36 .get_logs_by_module_patterns(&patterns, args.lines as i64)
37 .await
38 .context("Failed to query logs from database")?;
39
40 if entries.is_empty() {
41 return Err(anyhow!("No logs found in database for agents"));
42 }
43
44 let logs: Vec<String> = entries
45 .iter()
46 .map(|e| {
47 let message = console::strip_ansi_codes(&e.message);
48 format!(
49 "{} {} [{}] {}",
50 e.timestamp.format("%Y-%m-%d %H:%M:%S"),
51 e.level,
52 e.module,
53 message
54 )
55 })
56 .filter(|line| !line.contains("[profile:"))
57 .collect();
58
59 let agent_label = args.agent.clone().unwrap_or_else(|| "all".to_owned());
60
61 Ok(CommandOutput::card_value(
62 format!("Agent Logs (DB): {}", agent_label),
63 &AgentLogsOutput {
64 agent: Some(agent_label),
65 source: "database".to_owned(),
66 logs,
67 log_files: vec![],
68 },
69 ))
70}
71
72fn build_agent_patterns(agent: &str) -> Vec<String> {
73 vec![
74 format!("%{}%", agent),
75 "%agent%".to_owned(),
76 "%a2a%".to_owned(),
77 ]
78}
79
80fn build_all_agent_patterns() -> Result<Vec<String>> {
81 let services_config = ConfigLoader::load().context("Failed to load services config")?;
82
83 let mut patterns: Vec<String> = services_config
84 .agents
85 .keys()
86 .flat_map(|name| vec![format!("%{}%", name)])
87 .collect();
88
89 patterns.push("%agent%".to_owned());
90 patterns.push("%a2a%".to_owned());
91 patterns.push("%orchestration%".to_owned());
92
93 Ok(patterns)
94}