starnix_logging/
logging.rs1use starnix_task_command::TaskCommand;
6use starnix_uapi::errors::Errno;
7use starnix_uapi::{pid_t, tid_t};
8use std::cell::RefCell;
9use std::fmt;
10
11#[doc(hidden)]
14pub use log as __log;
15
16pub use log::kv::{ToValue, Value};
17pub use log::{Level, Record, logger};
18
19enum TaskDebugInfo {
21 Kernel,
23 User { pid: pid_t, tid: tid_t, command: TaskCommand, leader_command: TaskCommand },
26 Unknown,
29}
30
31impl TaskDebugInfo {
32 pub fn leader_command(&self) -> TaskCommand {
33 match self {
34 Self::Kernel => TaskCommand::new(b"kthreadd"),
35 Self::User { leader_command, .. } => leader_command.clone(),
36 Self::Unknown => TaskCommand::new(b"<unknown>"),
37 }
38 }
39}
40
41thread_local! {
42 static CURRENT_TASK_INFO: RefCell<TaskDebugInfo> = const { RefCell::new(TaskDebugInfo::Kernel) } ;
46}
47
48impl fmt::Display for TaskDebugInfo {
49 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
50 match self {
51 Self::Kernel => write!(f, "kthread"),
52 Self::User { pid, tid, command, .. } => write!(f, "{pid}:{tid}[{command}]"),
53 Self::Unknown => write!(f, "unknown"),
54 }
55 }
56}
57
58#[inline]
59pub const fn trace_debug_logs_enabled() -> bool {
60 cfg!(debug_assertions) || cfg!(feature = "trace_and_debug_logs_in_release")
63}
64
65#[macro_export]
66macro_rules! log_trace {
67 ($($key:tt $(:$capture:tt)? $(= $value:expr)?),+; $($arg:tt)+) => {
68 if $crate::trace_debug_logs_enabled() {
69 $crate::with_current_task_info(|_task_info| {
70 $crate::__log::trace!(
71 tag:% = _task_info,
72 $($key $(:$capture)* $(= $value)*),+;
73 $($arg)*
74 );
75 });
76 }
77 };
78 ($($arg:tt)*) => {
79 if $crate::trace_debug_logs_enabled() {
80 $crate::with_current_task_info(|_task_info| {
81 $crate::__log::trace!(tag:% = _task_info; $($arg)*);
82 });
83 }
84 };
85}
86
87#[macro_export]
88macro_rules! log_syscall {
89 ($current_task:expr, $($arg:tt)*) => {
90 if $crate::trace_debug_logs_enabled() {
91 $crate::log!(
92 $current_task.task.thread_group.syscall_log_level(),
93 $($arg)*
94 );
95 }
96 }
97}
98
99#[macro_export]
100macro_rules! log_debug {
101 ($($key:tt $(:$capture:tt)? $(= $value:expr)?),+; $($arg:tt)+) => {
102 if $crate::trace_debug_logs_enabled() {
103 $crate::with_current_task_info(|_task_info| {
104 $crate::__log::debug!(
105 tag:% = _task_info,
106 $($key $(:$capture)* $(= $value)*),+;
107 $($arg)*
108 );
109 });
110 }
111 };
112 ($($arg:tt)*) => {
113 if $crate::trace_debug_logs_enabled() {
114 $crate::with_current_task_info(|_task_info| {
115 $crate::__log::debug!(tag:% = _task_info; $($arg)*);
116 });
117 }
118 };
119}
120
121#[macro_export]
122macro_rules! log_info {
123 ($($arg:tt)*) => {
124 $crate::log!($crate::__log::Level::Info, $($arg)*);
125 };
126}
127
128#[macro_export]
129macro_rules! log_warn {
130 ($($arg:tt)*) => {
131 $crate::log!($crate::__log::Level::Warn, $($arg)*);
132 };
133}
134
135#[macro_export]
136macro_rules! log_error {
137 ($($arg:tt)*) => {
138 $crate::log!($crate::__log::Level::Error, $($arg)*);
139 };
140}
141
142#[macro_export]
143macro_rules! log {
144 ($lvl:expr, $($key:tt $(:$capture:tt)? $(= $value:expr)?),+; $($arg:tt)+) => {
145 $crate::with_current_task_info(|_task_info| {
146 $crate::__log::log!(
147 $lvl,
148 tag:% = _task_info,
149 $($key $(:$capture)* $(= $value)*),+;
150 $($arg)*
151 );
152 });
153 };
154 ($lvl:expr, $($arg:tt)+) => {
155 $crate::with_current_task_info(|_task_info| {
156 $crate::__log::log!($lvl, tag:% = _task_info; $($arg)*);
157 });
158 };
159}
160
161#[track_caller]
164pub fn impossible_error(status: zx::Status) -> Errno {
165 panic!("encountered impossible error: {status}");
166}
167
168pub fn set_zx_name(obj: &impl zx::AsHandleRef, name: impl AsRef<[u8]>) {
169 obj.as_handle_ref()
170 .set_name(&zx::Name::from_bytes_lossy(name.as_ref()))
171 .map_err(impossible_error)
172 .unwrap();
173}
174
175pub fn with_zx_name<O: zx::AsHandleRef>(obj: O, name: impl AsRef<[u8]>) -> O {
176 set_zx_name(&obj, name);
177 obj
178}
179
180pub fn set_current_task_info(
184 command: TaskCommand,
185 leader_command: TaskCommand,
186 pid: pid_t,
187 tid: tid_t,
188) {
189 CURRENT_TASK_INFO.with(|task_info| {
190 *task_info.borrow_mut() = TaskDebugInfo::User { pid, tid, command, leader_command };
191 });
192}
193
194#[doc(hidden)]
201pub fn with_current_task_info<T>(f: impl Fn(&dyn fmt::Display) -> T) -> T {
202 match CURRENT_TASK_INFO.try_with(|task_info| f(&task_info.borrow())) {
203 Ok(value) => value,
204 Err(_) => f(&TaskDebugInfo::Unknown),
205 }
206}
207
208pub(crate) fn get_current_leader_command() -> flyweights::FlyByteStr {
209 match CURRENT_TASK_INFO.try_with(|task_info| task_info.borrow().leader_command()) {
210 Ok(value) => value.into(),
211 Err(_) => flyweights::FlyByteStr::new(b"<unknown>"),
212 }
213}
214
215#[derive(Debug, Clone, PartialEq, Eq, Hash)]
217pub struct SyscallLogFilter {
218 match_string: String,
219}
220
221impl SyscallLogFilter {
222 pub fn new(match_string: String) -> Self {
223 Self { match_string }
224 }
225
226 pub fn matches(&self, command: &TaskCommand) -> bool {
227 let matcher = self.match_string.as_bytes();
228 command.as_bytes().windows(matcher.len()).any(|w| w == matcher)
229 }
230}