1 // Copyright 2020 The ChromiumOS Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 //! Implementation of the Syslog trait as a wrapper around Android's logging library, liblog.
6
7 extern crate android_log_sys;
8
9 use std::ffi::CString;
10 use std::ffi::NulError;
11 use std::mem::size_of;
12
13 use android_log_sys::__android_log_is_loggable;
14 use android_log_sys::__android_log_message;
15 use android_log_sys::__android_log_write_log_message;
16 use android_log_sys::log_id_t;
17 use android_log_sys::LogPriority;
18
19 use crate::syslog::Error;
20 use crate::syslog::Facility;
21 use crate::syslog::Level;
22 use crate::syslog::Log;
23 use crate::syslog::Syslog;
24 use crate::RawDescriptor;
25
26 pub struct PlatformSyslog {
27 proc_name: String,
28 }
29
30 impl Syslog for PlatformSyslog {
new( proc_name: String, facility: Facility, ) -> Result<(Option<Box<dyn Log + Send>>, Option<RawDescriptor>), Error>31 fn new(
32 proc_name: String,
33 facility: Facility,
34 ) -> Result<(Option<Box<dyn Log + Send>>, Option<RawDescriptor>), Error> {
35 Ok((Some(Box::new(Self { proc_name })), None))
36 }
37 }
38
39 impl Log for PlatformSyslog {
log(&self, record: &log::Record)40 fn log(&self, record: &log::Record) {
41 let priority = match record.level() {
42 Level::Error => LogPriority::ERROR,
43 Level::Warn => LogPriority::WARN,
44 Level::Info => LogPriority::INFO,
45 Level::Debug => LogPriority::VERBOSE,
46 Level::Trace => LogPriority::VERBOSE,
47 };
48 let message = std::fmt::format(*record.args());
49 let _ = android_log(
50 log_id_t::SYSTEM,
51 priority,
52 &self.proc_name,
53 record.file(),
54 record.line(),
55 &message,
56 );
57 }
58
enabled(&self, metadata: &log::Metadata) -> bool59 fn enabled(&self, metadata: &log::Metadata) -> bool {
60 true
61 }
62
flush(&self)63 fn flush(&self) {}
64 }
65
66 /// Send a log message to the Android logger (logd, by default) if it is currently configured to be
67 /// loggable based on the priority and tag.
68 ///
69 /// # Arguments
70 /// * `priority` - The Android log priority. Used to determine whether the message is loggable.
71 /// * `tag` - A tag to indicate where the log comes from.
72 /// * `file` - The name of the file from where the message is being logged, if available.
73 /// * `line` - The line number from where the message is being logged, if available.
74 /// * `message` - The message to log.
android_log( buffer_id: log_id_t, priority: LogPriority, tag: &str, file: Option<&str>, line: Option<u32>, message: &str, ) -> Result<(), NulError>75 fn android_log(
76 buffer_id: log_id_t,
77 priority: LogPriority,
78 tag: &str,
79 file: Option<&str>,
80 line: Option<u32>,
81 message: &str,
82 ) -> Result<(), NulError> {
83 let tag = CString::new(tag)?;
84 let default_pri = LogPriority::VERBOSE;
85 if unsafe { __android_log_is_loggable(priority as i32, tag.as_ptr(), default_pri as i32) } != 0
86 {
87 let c_file_name = match file {
88 Some(file_name) => CString::new(file_name)?.as_ptr(),
89 None => std::ptr::null(),
90 };
91 let line = line.unwrap_or(0);
92 let message = CString::new(message)?;
93 let mut log_message = __android_log_message {
94 struct_size: size_of::<__android_log_message>(),
95 buffer_id: buffer_id as i32,
96 priority: priority as i32,
97 tag: tag.as_ptr(),
98 file: c_file_name,
99 line,
100 message: message.as_ptr(),
101 };
102 unsafe { __android_log_write_log_message(&mut log_message) };
103 }
104 Ok(())
105 }
106