systemprompt_logging/
lib.rs1pub 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};
13#[cfg(feature = "cli")]
14pub use services::CliService;
15pub use services::{
16 DatabaseLogService, FilterSystemFields, LoggingMaintenanceService, RequestSpan,
17 RequestSpanBuilder, SystemSpan, is_startup_mode, publish_log, set_log_publisher,
18 set_startup_mode,
19};
20pub use trace::{
21 AiRequestDetail, AiRequestFilter, AiRequestInfo, AiRequestListItem, AiRequestStats,
22 AiRequestSummary, AiTraceService, AuditLookupResult, AuditToolCallRow, ConversationMessage,
23 ExecutionStep, ExecutionStepSummary, LevelCount, LinkedMcpCall, LogSearchFilter, LogSearchItem,
24 LogTimeRange, McpExecutionSummary, McpToolExecution, ModelStatsRow, ModuleCount,
25 ProviderStatsRow, TaskArtifact, TaskInfo, ToolExecutionFilter, ToolExecutionItem, ToolLogEntry,
26 TraceEvent, TraceListFilter, TraceListItem, TraceQueryService,
27};
28
29use std::sync::OnceLock;
30
31use systemprompt_database::DbPool;
32use tracing_subscriber::layer::SubscriberExt;
33use tracing_subscriber::util::SubscriberInitExt;
34use tracing_subscriber::{EnvFilter, Layer};
35
36static LOGGING_INITIALIZED: OnceLock<()> = OnceLock::new();
37
38const NOISE_FILTERS: &[&str] = &[
39 "tokio_cron_scheduler=warn",
40 "sqlx::postgres::notice=warn",
41 "sqlx::query=warn",
42 "handlebars=warn",
43 "systemprompt_database::lifecycle=info",
44 "systemprompt_templates=info",
45 "systemprompt_extension::registry=info",
46 "systemprompt_api::services::middleware::session=info",
47];
48
49fn build_filter(base: &str) -> EnvFilter {
50 let filter_str = std::iter::once(base.to_string())
51 .chain(NOISE_FILTERS.iter().map(ToString::to_string))
52 .collect::<Vec<_>>()
53 .join(",");
54 EnvFilter::new(filter_str)
55}
56
57pub fn init_logging(db_pool: DbPool) {
58 if LOGGING_INITIALIZED.set(()).is_err() {
59 return;
60 }
61
62 let console_filter = if is_startup_mode() {
63 EnvFilter::new("warn")
64 } else {
65 EnvFilter::try_from_default_env().unwrap_or_else(|_| build_filter("info"))
66 };
67
68 let fmt_layer = tracing_subscriber::fmt::layer()
69 .fmt_fields(FilterSystemFields::new())
70 .with_target(true)
71 .with_writer(std::io::stderr)
72 .with_filter(console_filter);
73
74 let db_layer =
75 DatabaseLayer::new(db_pool).with_filter(tracing_subscriber::filter::LevelFilter::INFO);
76
77 tracing_subscriber::registry()
78 .with(fmt_layer)
79 .with(db_layer)
80 .init();
81}
82
83pub fn init_console_logging() {
84 init_console_logging_with_level(None);
85}
86
87pub fn init_console_logging_with_level(level: Option<&str>) {
88 if LOGGING_INITIALIZED.set(()).is_err() {
89 return;
90 }
91
92 let env_filter =
93 EnvFilter::try_from_default_env().unwrap_or_else(|_| build_filter(level.unwrap_or("info")));
94
95 tracing_subscriber::fmt().with_env_filter(env_filter).init();
96}