blob: f3875062d6a07c8c6e455c54440e7fd1fcfe168c [file] [log] [blame]
// Copyright 2020 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//! Implementation of the Syslog trait as a wrapper around Android's logging library, liblog.
extern crate android_log_sys;
use crate::syslog::{Error, Facility, Priority, Syslog};
use android_log_sys::{
__android_log_is_loggable, __android_log_message, __android_log_write_log_message, log_id_t,
LogPriority,
};
use std::ffi::{CString, NulError};
use std::fmt;
use std::mem::size_of;
use std::os::unix::io::RawFd;
pub struct PlatformSyslog {
enabled: bool,
}
impl Syslog for PlatformSyslog {
fn new() -> Result<Self, Error> {
Ok(Self { enabled: true })
}
fn enable(&mut self, enable: bool) -> Result<(), Error> {
self.enabled = enable;
Ok(())
}
fn push_fds(&self, _fds: &mut Vec<RawFd>) {}
fn log(
&self,
proc_name: Option<&str>,
pri: Priority,
_fac: Facility,
file_line: Option<(&str, u32)>,
args: fmt::Arguments,
) {
let priority = match pri {
Priority::Emergency => LogPriority::ERROR,
Priority::Alert => LogPriority::ERROR,
Priority::Critical => LogPriority::ERROR,
Priority::Error => LogPriority::ERROR,
Priority::Warning => LogPriority::WARN,
Priority::Notice => LogPriority::INFO,
Priority::Info => LogPriority::DEBUG,
Priority::Debug => LogPriority::VERBOSE,
};
let tag = proc_name.unwrap_or("crosvm");
let message = std::fmt::format(args);
let _ = android_log(
log_id_t::SYSTEM,
priority,
tag,
file_line.map(|(file, _)| file),
file_line.map(|(_, line)| line),
&message,
);
}
}
/// Send a log message to the Android logger (logd, by default) if it is currently configured to be
/// loggable based on the priority and tag.
///
/// # Arguments
/// * `priority` - The Android log priority. Used to determine whether the message is loggable.
/// * `tag` - A tag to indicate where the log comes from.
/// * `file` - The name of the file from where the message is being logged, if available.
/// * `line` - The line number from where the message is being logged, if available.
/// * `message` - The message to log.
fn android_log(
buffer_id: log_id_t,
priority: LogPriority,
tag: &str,
file: Option<&str>,
line: Option<u32>,
message: &str,
) -> Result<(), NulError> {
let tag = CString::new(tag)?;
let default_pri = LogPriority::VERBOSE;
if unsafe { __android_log_is_loggable(priority as i32, tag.as_ptr(), default_pri as i32) } != 0
{
let c_file_name = match file {
Some(file_name) => CString::new(file_name)?.as_ptr(),
None => std::ptr::null(),
};
let line = line.unwrap_or(0);
let message = CString::new(message)?;
let mut log_message = __android_log_message {
struct_size: size_of::<__android_log_message>(),
buffer_id: buffer_id as i32,
priority: priority as i32,
tag: tag.as_ptr(),
file: c_file_name,
line,
message: message.as_ptr(),
};
unsafe { __android_log_write_log_message(&mut log_message) };
}
Ok(())
}