witchcraft_server/logging/
mod.rs1use crate::extensions::AuditLogEntry;
17use crate::logging::api::objects::{AuditLogV3, EventLogV2, RequestLogV2};
18use crate::shutdown_hooks::ShutdownHooks;
19use conjure_error::Error;
20use conjure_serde::json;
21use futures::executor::block_on;
22use futures::SinkExt;
23use lazycell::AtomicLazyCell;
24pub(crate) use logger::Appender;
25use once_cell::sync::OnceCell;
26use refreshable::Refreshable;
27use std::io;
28use std::io::Write as _;
29use std::sync::Arc;
30use tokio::sync::Mutex;
31use witchcraft_metrics::MetricRegistry;
32use witchcraft_server_config::install::InstallConfig;
33use witchcraft_server_config::runtime::LoggingConfig;
34
35pub use witchcraft_logging_api as api;
36
37mod cleanup;
38mod format;
39mod logger;
40pub mod mdc;
41mod metric;
42mod service;
43mod trace;
44
45pub(crate) static AUDIT_LOGGER: AtomicLazyCell<Arc<Mutex<Appender<AuditLogV3>>>> =
46 AtomicLazyCell::NONE;
47
48static EVENT_LOGGER: OnceCell<Appender<EventLogV2>> = OnceCell::new();
49
50pub(crate) const REQUEST_ID_KEY: &str = "_requestId";
51pub(crate) const SAMPLED_KEY: &str = "_sampled";
52
53pub(crate) struct Loggers {
54 pub request_logger: Arc<Appender<RequestLogV2>>,
55 pub audit_logger: Arc<Mutex<Appender<AuditLogV3>>>,
56}
57
58pub(crate) fn early_init() {
59 service::early_init()
60}
61
62pub(crate) async fn init(
63 metrics: &Arc<MetricRegistry>,
64 install: &InstallConfig,
65 runtime: &Refreshable<LoggingConfig, Error>,
66 hooks: &mut ShutdownHooks,
67) -> Result<Loggers, Error> {
68 metric::init(metrics, install, hooks).await?;
69 service::init(metrics, install, runtime, hooks).await?;
70 trace::init(metrics, install, runtime, hooks).await?;
71 let request_logger = logger::appender(install, metrics, hooks).await?;
72 let request_logger = Arc::new(request_logger);
73 let audit_logger = logger::appender(install, metrics, hooks).await?;
74 let audit_logger = Arc::new(Mutex::new(audit_logger));
75 let event_logger = logger::appender(install, metrics, hooks).await?;
76
77 AUDIT_LOGGER
78 .fill(audit_logger.clone())
79 .ok()
80 .expect("Audit logger already initialized");
81
82 EVENT_LOGGER
83 .set(event_logger)
84 .ok()
85 .expect("Event logger already initialized");
86
87 cleanup::cleanup_logs().await;
88
89 Ok(Loggers {
90 request_logger,
91 audit_logger,
92 })
93}
94
95pub async fn audit_log(entry: AuditLogEntry) -> Result<(), Error> {
101 let audit_logger = AUDIT_LOGGER
102 .borrow()
103 .ok_or_else(|| Error::internal_safe("Audit logger not initialized"))?;
104
105 audit_logger
106 .lock()
107 .await
108 .feed(entry.0)
109 .await
110 .map_err(|_| Error::internal_safe("Audit logger is closed or not ready"))?;
111
112 Ok(())
113}
114
115pub fn audit_log_blocking(entry: AuditLogEntry) -> Result<(), Error> {
117 block_on(audit_log(entry))
118}
119
120pub fn event_log(entry: EventLogV2) {
124 match EVENT_LOGGER.get() {
125 Some(event_logger) => {
126 let _ = event_logger.try_send(entry);
127 }
128 None => {
129 let mut buf = json::to_vec(&entry).unwrap();
130 buf.push(b'\n');
131 let _ = io::stdout().write_all(&buf);
132 }
133 }
134}