Skip to main content

systemprompt_cli/commands/admin/agents/
logs_db.rs

1use 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}