/* This Source Code Form is subject to the terms of the Mozilla Public *License,v.2.0.IfacopyoftheMPLwasnotdistributedwiththis
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use std::fmt::{self, Write};
use log::{Level, LevelFilter, Log, Metadata, Record}; use moz_task::{Task, TaskRunnable, ThreadPtrHandle, ThreadPtrHolder}; use nserror::nsresult; use nsstring::nsString; use xpcom::{interfaces::mozIServicesLogSink, RefPtr};
impl LogSink { /// Creates a log sink that adapts the Rust `log` crate to the Sync /// `Log.sys.mjs` logger. /// /// This is copied from `bookmark_sync::Logger`. It would be nice to share /// these, but, for now, we've just duplicated it to make prototyping /// easier. #[inline] pubfn new(max_level: LevelFilter, logger: ThreadPtrHandle<mozIServicesLogSink>) -> LogSink {
LogSink {
max_level,
logger: Some(logger),
}
}
/// Creates a log sink using the given Services `logger` as the /// underlying implementation. The `logger` will always be called /// asynchronously on its owning thread; it doesn't need to be /// thread-safe. pubfn with_logger(logger: Option<&mozIServicesLogSink>) -> Result<LogSink, nsresult> {
Ok(iflet Some(logger) = logger { // Fetch the maximum log level while we're on the main thread, so // that `LogSink::enabled()` can check it while on the background // thread. Otherwise, we'd need to dispatch a `LogTask` for every // log message, only to discard most of them when the task calls // into the logger on the main thread. letmut raw_max_level = 0i16; let rv = unsafe { logger.GetMaxLevel(&mut raw_max_level) }; let max_level = if rv.succeeded() { match raw_max_level {
mozIServicesLogSink::LEVEL_ERROR => LevelFilter::Error,
mozIServicesLogSink::LEVEL_WARN => LevelFilter::Warn,
mozIServicesLogSink::LEVEL_DEBUG => LevelFilter::Debug,
mozIServicesLogSink::LEVEL_TRACE => LevelFilter::Trace,
mozIServicesLogSink::LEVEL_INFO => LevelFilter::Info,
_ => LevelFilter::Off,
}
} else {
LevelFilter::Off
};
LogSink::new(
max_level,
ThreadPtrHolder::new(cstr!("mozIServicesLogSink"), RefPtr::new(logger))?,
)
} else {
LogSink::default()
})
}
/// Returns a reference to the underlying `mozIServicesLogSink`. pubfn logger(&self) -> Option<&mozIServicesLogSink> { self.logger.as_ref().and_then(|l| l.get())
}
/// Logs a message to the Sync logger, if one is set. This would be better /// implemented as a macro, as Dogear does, so that we can pass variadic /// arguments without manually invoking `fmt_args!()` every time we want /// to log a message. /// /// The `log` crate's macros aren't suitable here, because those log to the /// global logger. However, we don't want to set the global logger in our /// crate, because that will log _everything_ that uses the Rust `log` crate /// to the Sync logs, including WebRender and audio logging. pubfn debug(&self, args: fmt::Arguments) { let meta = Metadata::builder()
.level(Level::Debug)
.target(module_path!())
.build(); ifself.enabled(&meta) { self.log(&Record::builder().args(args).metadata(meta).build());
}
}
}
/// Logs a message to the mirror logger. This task is created on the background /// thread queue, and dispatched to the main thread. struct LogTask {
logger: ThreadPtrHandle<mozIServicesLogSink>,
level: Level,
message: nsString,
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.