1use std::{
5 panic::{self, PanicHookInfo},
6 sync::Once,
7};
8
9use log::{LevelFilter, Log, Metadata, Record};
10
11use crate::{
12 contract::wit::base_runtime_api as contract_wit, service::wit::base_runtime_api as service_wit,
13};
14
15static CONTRACT_LOGGER: ContractLogger = ContractLogger;
16static SERVICE_LOGGER: ServiceLogger = ServiceLogger;
17
18static INSTALL_LOGGER: Once = Once::new();
19
20#[derive(Clone, Copy, Debug)]
22pub struct ContractLogger;
23
24impl ContractLogger {
25 pub fn install() {
27 INSTALL_LOGGER.call_once(|| {
28 log::set_logger(&CONTRACT_LOGGER).expect("Failed to initialize contract logger");
29 log::set_max_level(LevelFilter::Trace);
30 panic::set_hook(Box::new(log_panic));
31 });
32 }
33}
34
35impl Log for ContractLogger {
36 fn enabled(&self, _: &Metadata) -> bool {
37 true
38 }
39
40 fn log(&self, record: &Record) {
41 contract_wit::log(&record.args().to_string(), record.level().into());
42 }
43
44 fn flush(&self) {}
45}
46
47#[derive(Clone, Copy, Debug)]
49pub struct ServiceLogger;
50
51impl ServiceLogger {
52 pub fn install() {
54 INSTALL_LOGGER.call_once(|| {
55 log::set_logger(&SERVICE_LOGGER).expect("Failed to initialize service logger");
56 log::set_max_level(LevelFilter::Trace);
57 panic::set_hook(Box::new(log_panic));
58 });
59 }
60}
61
62impl Log for ServiceLogger {
63 fn enabled(&self, _: &Metadata) -> bool {
64 true
65 }
66
67 fn log(&self, record: &Record) {
68 service_wit::log(&record.args().to_string(), record.level().into());
69 }
70
71 fn flush(&self) {}
72}
73
74fn log_panic(info: &PanicHookInfo<'_>) {
76 log::error!("{info}");
77}