Skip to main content

systemprompt_logging/
lib.rs

1pub mod extension;
2pub mod layer;
3pub mod models;
4pub mod repository;
5pub mod services;
6pub mod trace;
7
8pub use extension::LoggingExtension;
9
10pub use layer::DatabaseLayer;
11pub use models::{LogEntry, LogFilter, LogLevel};
12pub use repository::{AnalyticsEvent, AnalyticsRepository, LoggingRepository};
13pub use services::{
14    CliService, DatabaseLogService, FilterSystemFields, LoggingMaintenanceService, RequestSpan,
15    RequestSpanBuilder, SystemSpan, is_startup_mode, publish_log, set_log_publisher,
16    set_startup_mode,
17};
18pub use trace::{
19    AiRequestInfo, AiRequestSummary, AiTraceService, ConversationMessage, ExecutionStep,
20    ExecutionStepSummary, McpExecutionSummary, McpToolExecution, TaskArtifact, TaskInfo,
21    ToolLogEntry, TraceEvent, TraceQueryService,
22};
23
24use std::sync::OnceLock;
25
26use systemprompt_database::DbPool;
27use tracing_subscriber::layer::SubscriberExt;
28use tracing_subscriber::util::SubscriberInitExt;
29use tracing_subscriber::{EnvFilter, Layer};
30
31static LOGGING_INITIALIZED: OnceLock<()> = OnceLock::new();
32
33const NOISE_FILTERS: &[&str] = &[
34    "tokio_cron_scheduler=warn",
35    "sqlx::postgres::notice=warn",
36    "sqlx::query=warn",
37    "handlebars=warn",
38    "systemprompt_database::lifecycle=info",
39    "systemprompt_templates=info",
40    "systemprompt_extension::registry=info",
41    "systemprompt_api::services::middleware::session=info",
42];
43
44fn build_filter(base: &str) -> EnvFilter {
45    let filter_str = std::iter::once(base.to_string())
46        .chain(NOISE_FILTERS.iter().map(ToString::to_string))
47        .collect::<Vec<_>>()
48        .join(",");
49    EnvFilter::new(filter_str)
50}
51
52pub fn init_logging(db_pool: DbPool) {
53    if LOGGING_INITIALIZED.set(()).is_err() {
54        return;
55    }
56
57    let console_filter = if is_startup_mode() {
58        EnvFilter::new("warn")
59    } else {
60        EnvFilter::try_from_default_env().unwrap_or_else(|_| build_filter("info"))
61    };
62
63    let fmt_layer = tracing_subscriber::fmt::layer()
64        .fmt_fields(FilterSystemFields::new())
65        .with_target(true)
66        .with_writer(std::io::stderr)
67        .with_filter(console_filter);
68
69    let db_layer =
70        DatabaseLayer::new(db_pool).with_filter(tracing_subscriber::filter::LevelFilter::INFO);
71
72    tracing_subscriber::registry()
73        .with(fmt_layer)
74        .with(db_layer)
75        .init();
76}
77
78pub fn init_console_logging() {
79    init_console_logging_with_level(None);
80}
81
82pub fn init_console_logging_with_level(level: Option<&str>) {
83    if LOGGING_INITIALIZED.set(()).is_err() {
84        return;
85    }
86
87    let env_filter =
88        EnvFilter::try_from_default_env().unwrap_or_else(|_| build_filter(level.unwrap_or("info")));
89
90    tracing_subscriber::fmt().with_env_filter(env_filter).init();
91}