1*598139dcSAndroid Build Coastguard Worker // Copyright 2024, The Android Open Source Project 2*598139dcSAndroid Build Coastguard Worker // 3*598139dcSAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License"); 4*598139dcSAndroid Build Coastguard Worker // you may not use this file except in compliance with the License. 5*598139dcSAndroid Build Coastguard Worker // You may obtain a copy of the License at 6*598139dcSAndroid Build Coastguard Worker // 7*598139dcSAndroid Build Coastguard Worker // http://www.apache.org/licenses/LICENSE-2.0 8*598139dcSAndroid Build Coastguard Worker // 9*598139dcSAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software 10*598139dcSAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS, 11*598139dcSAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12*598139dcSAndroid Build Coastguard Worker // See the License for the specific language governing permissions and 13*598139dcSAndroid Build Coastguard Worker // limitations under the License. 14*598139dcSAndroid Build Coastguard Worker 15*598139dcSAndroid Build Coastguard Worker //! # Structed Logger API for Android 16*598139dcSAndroid Build Coastguard Worker 17*598139dcSAndroid Build Coastguard Worker use log_event_list::__private_api::{LogContext, LogContextError}; 18*598139dcSAndroid Build Coastguard Worker 19*598139dcSAndroid Build Coastguard Worker /// Add functionality to a type to log to a LogContext 20*598139dcSAndroid Build Coastguard Worker pub trait Value { 21*598139dcSAndroid Build Coastguard Worker /// Apend value to provided context add_to_context(&self, ctx: LogContext) -> Result<LogContext, LogContextError>22*598139dcSAndroid Build Coastguard Worker fn add_to_context(&self, ctx: LogContext) -> Result<LogContext, LogContextError>; 23*598139dcSAndroid Build Coastguard Worker } 24*598139dcSAndroid Build Coastguard Worker 25*598139dcSAndroid Build Coastguard Worker impl Value for f32 { add_to_context(&self, ctx: LogContext) -> Result<LogContext, LogContextError>26*598139dcSAndroid Build Coastguard Worker fn add_to_context(&self, ctx: LogContext) -> Result<LogContext, LogContextError> { 27*598139dcSAndroid Build Coastguard Worker ctx.append_f32(*self) 28*598139dcSAndroid Build Coastguard Worker } 29*598139dcSAndroid Build Coastguard Worker } 30*598139dcSAndroid Build Coastguard Worker 31*598139dcSAndroid Build Coastguard Worker impl Value for i32 { add_to_context(&self, ctx: LogContext) -> Result<LogContext, LogContextError>32*598139dcSAndroid Build Coastguard Worker fn add_to_context(&self, ctx: LogContext) -> Result<LogContext, LogContextError> { 33*598139dcSAndroid Build Coastguard Worker ctx.append_i32(*self) 34*598139dcSAndroid Build Coastguard Worker } 35*598139dcSAndroid Build Coastguard Worker } 36*598139dcSAndroid Build Coastguard Worker 37*598139dcSAndroid Build Coastguard Worker impl Value for i64 { add_to_context(&self, ctx: LogContext) -> Result<LogContext, LogContextError>38*598139dcSAndroid Build Coastguard Worker fn add_to_context(&self, ctx: LogContext) -> Result<LogContext, LogContextError> { 39*598139dcSAndroid Build Coastguard Worker ctx.append_i64(*self) 40*598139dcSAndroid Build Coastguard Worker } 41*598139dcSAndroid Build Coastguard Worker } 42*598139dcSAndroid Build Coastguard Worker 43*598139dcSAndroid Build Coastguard Worker impl Value for &str { add_to_context(&self, ctx: LogContext) -> Result<LogContext, LogContextError>44*598139dcSAndroid Build Coastguard Worker fn add_to_context(&self, ctx: LogContext) -> Result<LogContext, LogContextError> { 45*598139dcSAndroid Build Coastguard Worker ctx.append_str(self) 46*598139dcSAndroid Build Coastguard Worker } 47*598139dcSAndroid Build Coastguard Worker } 48*598139dcSAndroid Build Coastguard Worker 49*598139dcSAndroid Build Coastguard Worker impl Value for String { add_to_context(&self, ctx: LogContext) -> Result<LogContext, LogContextError>50*598139dcSAndroid Build Coastguard Worker fn add_to_context(&self, ctx: LogContext) -> Result<LogContext, LogContextError> { 51*598139dcSAndroid Build Coastguard Worker ctx.append_str(self.as_str()) 52*598139dcSAndroid Build Coastguard Worker } 53*598139dcSAndroid Build Coastguard Worker } 54*598139dcSAndroid Build Coastguard Worker 55*598139dcSAndroid Build Coastguard Worker /// Enum provides values to control sections. 56*598139dcSAndroid Build Coastguard Worker #[derive(PartialEq)] 57*598139dcSAndroid Build Coastguard Worker pub enum StructuredLogSection { 58*598139dcSAndroid Build Coastguard Worker /// Start a new section 59*598139dcSAndroid Build Coastguard Worker SubsectionStart, 60*598139dcSAndroid Build Coastguard Worker /// End a section 61*598139dcSAndroid Build Coastguard Worker SubsectionEnd, 62*598139dcSAndroid Build Coastguard Worker } 63*598139dcSAndroid Build Coastguard Worker 64*598139dcSAndroid Build Coastguard Worker impl Value for StructuredLogSection { add_to_context(&self, ctx: LogContext) -> Result<LogContext, LogContextError>65*598139dcSAndroid Build Coastguard Worker fn add_to_context(&self, ctx: LogContext) -> Result<LogContext, LogContextError> { 66*598139dcSAndroid Build Coastguard Worker match *self { 67*598139dcSAndroid Build Coastguard Worker StructuredLogSection::SubsectionStart => ctx.begin_list(), 68*598139dcSAndroid Build Coastguard Worker StructuredLogSection::SubsectionEnd => ctx.end_list(), 69*598139dcSAndroid Build Coastguard Worker } 70*598139dcSAndroid Build Coastguard Worker } 71*598139dcSAndroid Build Coastguard Worker } 72*598139dcSAndroid Build Coastguard Worker 73*598139dcSAndroid Build Coastguard Worker // The following uses global crate names to make the usage of the macro 74*598139dcSAndroid Build Coastguard Worker // as simple as possible as the using code does not need to use the 75*598139dcSAndroid Build Coastguard Worker // dependencies explicitly. 76*598139dcSAndroid Build Coastguard Worker // Using imported crate names would require using code to import all our 77*598139dcSAndroid Build Coastguard Worker // internal dependencies without using them manually. 78*598139dcSAndroid Build Coastguard Worker 79*598139dcSAndroid Build Coastguard Worker /// Events log buffer. 80*598139dcSAndroid Build Coastguard Worker /// C++ implementation always logs to events, and used by default for consistent behavior between Rust and C++. 81*598139dcSAndroid Build Coastguard Worker pub const LOG_ID_EVENTS: u32 = log_event_list_bindgen::log_id_LOG_ID_EVENTS; 82*598139dcSAndroid Build Coastguard Worker /// Security log buffer. 83*598139dcSAndroid Build Coastguard Worker pub const LOG_ID_SECURITY: u32 = log_event_list_bindgen::log_id_LOG_ID_SECURITY; 84*598139dcSAndroid Build Coastguard Worker /// Statistics log buffer. 85*598139dcSAndroid Build Coastguard Worker pub const LOG_ID_STATS: u32 = log_event_list_bindgen::log_id_LOG_ID_STATS; 86*598139dcSAndroid Build Coastguard Worker 87*598139dcSAndroid Build Coastguard Worker /// Add a structured log entry to buffer $log_id. 88*598139dcSAndroid Build Coastguard Worker /// Should not be used directly, but the macros below. 89*598139dcSAndroid Build Coastguard Worker /// Warning: Since this macro is internal, it may change any time. 90*598139dcSAndroid Build Coastguard Worker /// Usage: __structured_log_internal!(LOG_ID, TAG, value1, value2, ...) 91*598139dcSAndroid Build Coastguard Worker /// Returns Result: 92*598139dcSAndroid Build Coastguard Worker /// Ok if entry was written successfully 93*598139dcSAndroid Build Coastguard Worker /// Err(str) with an error description 94*598139dcSAndroid Build Coastguard Worker #[doc(hidden)] 95*598139dcSAndroid Build Coastguard Worker #[macro_export] 96*598139dcSAndroid Build Coastguard Worker macro_rules! __structured_log_internal { 97*598139dcSAndroid Build Coastguard Worker ($log_id:expr, $tag:expr, $($entry:expr),+) => ( 98*598139dcSAndroid Build Coastguard Worker { 99*598139dcSAndroid Build Coastguard Worker let mut ctx = 100*598139dcSAndroid Build Coastguard Worker log_event_list::__private_api::LogContext::new($log_id, $tag) 101*598139dcSAndroid Build Coastguard Worker .ok_or(log_event_list::__private_api::LogContextError).map_err(|_| 102*598139dcSAndroid Build Coastguard Worker "Unable to create a log context"); 103*598139dcSAndroid Build Coastguard Worker $(ctx = ctx.and_then(|c| $crate::Value::add_to_context(&$entry, c) 104*598139dcSAndroid Build Coastguard Worker .map_err(|_| "unable to log value"));)+; 105*598139dcSAndroid Build Coastguard Worker ctx.and_then(|c| c.write() 106*598139dcSAndroid Build Coastguard Worker .map_err(|_| "unable to write log message")) 107*598139dcSAndroid Build Coastguard Worker } 108*598139dcSAndroid Build Coastguard Worker ) 109*598139dcSAndroid Build Coastguard Worker } 110*598139dcSAndroid Build Coastguard Worker 111*598139dcSAndroid Build Coastguard Worker /// Add a structured log entry to events. 112*598139dcSAndroid Build Coastguard Worker /// Usage: structured_log!(TAG, value1, value2, ...) 113*598139dcSAndroid Build Coastguard Worker /// To use a different log buffer, you can specify it with log_id. 114*598139dcSAndroid Build Coastguard Worker /// Usage: structured_log!(log_id: LOG_ID, TAG, value1, value2, ...) 115*598139dcSAndroid Build Coastguard Worker /// Returns Result: 116*598139dcSAndroid Build Coastguard Worker /// Ok if entry was written successfully 117*598139dcSAndroid Build Coastguard Worker /// Err(str) with an error description 118*598139dcSAndroid Build Coastguard Worker #[macro_export] 119*598139dcSAndroid Build Coastguard Worker macro_rules! structured_log { 120*598139dcSAndroid Build Coastguard Worker (log_id: $log_id:expr, $tag:expr, $($entry:expr),+) => ( 121*598139dcSAndroid Build Coastguard Worker { 122*598139dcSAndroid Build Coastguard Worker $crate::__structured_log_internal!($log_id, $tag, $($entry),+) 123*598139dcSAndroid Build Coastguard Worker } 124*598139dcSAndroid Build Coastguard Worker ); 125*598139dcSAndroid Build Coastguard Worker ($tag:expr, $($entry:expr),+) => ( 126*598139dcSAndroid Build Coastguard Worker { 127*598139dcSAndroid Build Coastguard Worker $crate::__structured_log_internal!($crate::LOG_ID_EVENTS, $tag, $($entry),+) 128*598139dcSAndroid Build Coastguard Worker } 129*598139dcSAndroid Build Coastguard Worker ) 130*598139dcSAndroid Build Coastguard Worker } 131