xref: /aosp_15_r20/system/logging/rust/structured_logger.rs (revision 598139dc91b21518d67c408eaea2644226490971)
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