1use std::borrow::ToOwned;
10use std::sync::Arc;
11use std::thread;
12
13use backtrace::Backtrace;
14use base::id::{ScriptEventLoopId, TEST_PIPELINE_ID, TEST_WEBVIEW_ID};
15use constellation_traits::{
16 EmbedderToConstellationMessage, LogEntry, ScriptToConstellationMessage,
17 ScriptToConstellationSender,
18};
19use crossbeam_channel::Sender;
20use log::{Level, LevelFilter, Log, Metadata, Record};
21use parking_lot::ReentrantMutex;
22
23pub struct FromScriptLogger {
26 pub script_to_constellation_sender: Arc<ReentrantMutex<ScriptToConstellationSender>>,
28}
29
30impl FromScriptLogger {
32 pub fn new(script_to_constellation_chan: ScriptToConstellationSender) -> FromScriptLogger {
34 FromScriptLogger {
35 script_to_constellation_sender: Arc::new(ReentrantMutex::new(
36 script_to_constellation_chan,
37 )),
38 }
39 }
40
41 pub fn filter(&self) -> LevelFilter {
43 LevelFilter::Warn
44 }
45}
46
47impl Log for FromScriptLogger {
48 fn enabled(&self, metadata: &Metadata) -> bool {
49 metadata.level() <= Level::Warn
50 }
51
52 fn log(&self, record: &Record) {
53 if let Some(entry) = log_entry(record) {
54 let thread_name = thread::current().name().map(ToOwned::to_owned);
55 let _ = self.script_to_constellation_sender.lock().send(
56 (
61 TEST_WEBVIEW_ID,
62 TEST_PIPELINE_ID,
63 ScriptToConstellationMessage::LogEntry(
64 ScriptEventLoopId::installed(),
65 thread_name,
66 entry,
67 ),
68 ),
69 );
70 }
71 }
72
73 fn flush(&self) {}
74}
75
76#[derive(Clone)]
78pub struct FromEmbedderLogger {
79 pub constellation_chan: Arc<ReentrantMutex<Sender<EmbedderToConstellationMessage>>>,
81}
82
83impl FromEmbedderLogger {
84 pub fn new(constellation_chan: Sender<EmbedderToConstellationMessage>) -> FromEmbedderLogger {
86 FromEmbedderLogger {
87 constellation_chan: Arc::new(ReentrantMutex::new(constellation_chan)),
88 }
89 }
90
91 pub fn filter(&self) -> LevelFilter {
93 LevelFilter::Warn
94 }
95}
96
97impl Log for FromEmbedderLogger {
98 fn enabled(&self, metadata: &Metadata) -> bool {
99 metadata.level() <= Level::Warn
100 }
101
102 fn log(&self, record: &Record) {
103 if let Some(entry) = log_entry(record) {
104 let event_loop_id = ScriptEventLoopId::installed();
105 let thread_name = thread::current().name().map(ToOwned::to_owned);
106 let msg = EmbedderToConstellationMessage::LogEntry(event_loop_id, thread_name, entry);
107 let chan = self.constellation_chan.lock();
108 let _ = chan.send(msg);
109 }
110 }
111
112 fn flush(&self) {}
113}
114
115fn log_entry(record: &Record) -> Option<LogEntry> {
120 match record.level() {
121 Level::Error if thread::panicking() => Some(LogEntry::Panic(
122 format!("{}", record.args()),
123 format!("{:?}", Backtrace::new()),
124 )),
125 Level::Error => Some(LogEntry::Error(format!("{}", record.args()))),
126 Level::Warn => Some(LogEntry::Warn(format!("{}", record.args()))),
127 _ => None,
128 }
129}