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