Skip to content

Commit 1d58e98

Browse files
authored
Add logging to ros2_rust (#371)
1 parent 4099c8d commit 1d58e98

File tree

9 files changed

+189
-5
lines changed

9 files changed

+189
-5
lines changed

examples/chatter/talker.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
1919

2020
while !shut_down.load(Ordering::Relaxed) && context.ok() {
2121
message.data = format!("Hello, world! {}", publish_count);
22-
println!("Publishing: [{}]", message.data);
22+
rclrs::log_info!(node.logger_name(), "Publishing: {}", message.data);
2323
publisher.publish(&message)?;
2424
publish_count += 1;
2525
std::thread::sleep(std::time::Duration::from_millis(500));

examples/zero_copy/listener.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
2323
.as_micros() as u64;
2424
let delay_us = now - msg.timestamp;
2525
let data_length = msg.data_length as usize;
26-
println!(
26+
rclrs::log_info!(node.logger_name(),
2727
"Delay {} us, I heard: '{:?}'",
2828
delay_us,
2929
String::from_utf8(msg.data[..data_length].to_vec()).unwrap()

examples/zero_copy/talker.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
3737
let msg_len = msg.len();
3838
message.data_length = msg_len as u64;
3939
message.data[..msg_len].copy_from_slice(msg.as_bytes());
40-
println!("Publishing: {}", msg);
40+
rclrs::log_info!(node.logger_name(), "Publishing: {}", msg);
4141
message.publish()?;
4242
publish_count += 1;
4343
std::thread::sleep(std::time::Duration::from_millis(callback_period_ms as u64));
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
diff --git a/rclrs/src/lib.rs b/rclrs/src/lib.rs
2+
index 4924b36..3a22c6d 100644
3+
--- a/rclrs/src/lib.rs
4+
+++ b/rclrs/src/lib.rs
5+
@@ -11,6 +11,7 @@ mod clock;
6+
mod context;
7+
mod error;
8+
mod executor;
9+
+mod logging;
10+
mod node;
11+
mod parameter;
12+
mod publisher;
13+
@@ -38,6 +39,7 @@ pub use clock::*;
14+
pub use context::*;
15+
pub use error::*;
16+
pub use executor::*;
17+
+pub use logging::*;
18+
pub use node::*;
19+
pub use parameter::*;
20+
pub use publisher::*;
21+
diff --git a/rclrs/src/node.rs b/rclrs/src/node.rs
22+
index 97684d6..defd1f3 100644
23+
--- a/rclrs/src/node.rs
24+
+++ b/rclrs/src/node.rs
25+
@@ -440,6 +440,17 @@ impl Node {
26+
pub fn builder(context: &Context, node_name: &str) -> NodeBuilder {
27+
NodeBuilder::new(context, node_name)
28+
}
29+
+
30+
+ /// Returns the logger name of the node.
31+
+ pub fn logger_name(&self) -> &str {
32+
+ let rcl_node = self.handle.rcl_node.lock().unwrap();
33+
+ let name_raw_ptr = unsafe { rcl_node_get_logger_name(&*rcl_node) };
34+
+ if name_raw_ptr.is_null() {
35+
+ return "";
36+
+ }
37+
+ let name_cstr = unsafe { CStr::from_ptr(name_raw_ptr) };
38+
+ name_cstr.to_str().unwrap_or("")
39+
+ }
40+
}
41+
42+
// Helper used to implement call_string_getter(), but also used to get the FQN in the Node::new()

repositories/ros2_rust.BUILD.bazel

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,10 @@ rust_library(
6565
srcs = glob(
6666
["rclrs/src/**/*.rs"],
6767
exclude = ["rclrs/src/vendor/*.rs"],
68-
) + ["rclrs/src/rcl_bindings_generated.rs"],
68+
) + [
69+
"rclrs/src/rcl_bindings_generated.rs",
70+
":logging_generator",
71+
],
6972
edition = "2021",
7073
visibility = ["//visibility:public"],
7174
deps = [
@@ -76,6 +79,12 @@ rust_library(
7679
],
7780
)
7881

82+
copy_file(
83+
name = "logging_generator",
84+
src = "@com_github_mvukov_rules_ros2//third_party/ros2_rust_logging:logging.rs",
85+
out = "rclrs/src/logging.rs",
86+
)
87+
7988
GENERATOR_APP_PY = "rosidl_generator_rs_app.py"
8089

8190
copy_file(

repositories/rust_setup_stage_1.bzl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ def rust_setup_stage_1():
2121
"@com_github_mvukov_rules_ros2//repositories/patches:ros2_rust_fix_rcl_bindings.patch",
2222
"@com_github_mvukov_rules_ros2//repositories/patches:ros2_rust_fix_rosidl_generator.patch",
2323
"@com_github_mvukov_rules_ros2//repositories/patches:ros2_rust_no_msg_vendoring.patch",
24+
"@com_github_mvukov_rules_ros2//repositories/patches:ros2_rust_logging.patch",
2425
],
2526
)
2627

ros2/test/rust/publisher.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,9 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
1515
let mut publish_count: u32 = 1;
1616

1717
while !shut_down.load(Ordering::Relaxed) && context.ok() {
18-
message.data = format!("Hello, world! {}", publish_count);
18+
let msg = format!("Hello, world! {}", publish_count);
19+
message.data = msg.clone();
20+
rclrs::log_info!(node.logger_name(), "{}", msg);
1921
publisher.publish(&message)?;
2022
publish_count += 1;
2123
std::thread::sleep(std::time::Duration::from_millis(10));
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
exports_files([
2+
"logging.rs",
3+
])
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
// Copyright (c) 2019 Sequence Planner
2+
// SPDX-License-Identifier: Apache-2.0 AND MIT
3+
// Adapted from https://github.com/sequenceplanner/r2r/blob/89cec03d07a1496a225751159cbc7bfb529d9dd1/r2r/src/utils.rs
4+
5+
use std::{
6+
ffi::CString,
7+
sync::{Mutex, Once},
8+
};
9+
10+
use crate::error;
11+
use crate::rcl_bindings::*;
12+
13+
static INIT: Once = Once::new();
14+
static LOG_GUARD: Mutex<()> = Mutex::new(());
15+
16+
/// Don't call this directly, use the logging macros instead.
17+
#[doc(hidden)]
18+
pub fn log(msg: &str, logger_name: &str, file: &str, line: u32, severity: LogSeverity) {
19+
// currently not possible to get function name in rust.
20+
// see https://github.com/rust-lang/rfcs/pull/2818
21+
let function = CString::new("").unwrap();
22+
let file = CString::new(file).unwrap();
23+
let location = rcutils_log_location_t {
24+
function_name: function.as_ptr(),
25+
file_name: file.as_ptr(),
26+
line_number: line as usize,
27+
};
28+
let format = CString::new("%s").unwrap();
29+
let logger_name = CString::new(logger_name).unwrap();
30+
let message = CString::new(msg).unwrap();
31+
let severity = severity.to_native();
32+
33+
INIT.call_once(|| {
34+
let ret = unsafe { rcutils_logging_initialize() };
35+
if let Err(code) = error::to_rclrs_result(ret) {
36+
panic!("Failed to initialize logging: {:?}", code);
37+
}
38+
});
39+
let _guard = LOG_GUARD.lock().unwrap();
40+
unsafe {
41+
rcutils_log(
42+
&location,
43+
severity as i32,
44+
logger_name.as_ptr(),
45+
format.as_ptr(),
46+
message.as_ptr(),
47+
);
48+
}
49+
}
50+
51+
/// Logging severity
52+
#[doc(hidden)]
53+
pub enum LogSeverity {
54+
Unset,
55+
Debug,
56+
Info,
57+
Warn,
58+
Error,
59+
Fatal,
60+
}
61+
62+
impl LogSeverity {
63+
fn to_native(&self) -> RCUTILS_LOG_SEVERITY {
64+
use crate::rcl_bindings::rcl_log_severity_t::*;
65+
match self {
66+
LogSeverity::Unset => RCUTILS_LOG_SEVERITY_UNSET,
67+
LogSeverity::Debug => RCUTILS_LOG_SEVERITY_DEBUG,
68+
LogSeverity::Info => RCUTILS_LOG_SEVERITY_INFO,
69+
LogSeverity::Warn => RCUTILS_LOG_SEVERITY_WARN,
70+
LogSeverity::Error => RCUTILS_LOG_SEVERITY_ERROR,
71+
LogSeverity::Fatal => RCUTILS_LOG_SEVERITY_FATAL,
72+
}
73+
}
74+
}
75+
76+
/// A helper macro to log the message.
77+
#[macro_export]
78+
macro_rules! __impl_log {
79+
($logger_name:expr, $msg:expr, $file:expr, $line:expr, $severity:expr) => {{
80+
$crate::log(&std::fmt::format($msg), $logger_name, $file, $line, $severity);
81+
}};
82+
}
83+
84+
/// Debug log message.
85+
#[macro_export]
86+
macro_rules! log_debug {
87+
($logger_name:expr, $($args:tt)*) => {{
88+
$crate::__impl_log!($logger_name, format_args!($($args)*),
89+
file!(), line!(), $crate::LogSeverity::Debug)
90+
}}
91+
}
92+
93+
/// Info log message.
94+
#[macro_export]
95+
macro_rules! log_info {
96+
($logger_name:expr, $($args:tt)*) => {{
97+
$crate::__impl_log!($logger_name, format_args!($($args)*),
98+
file!(), line!(), $crate::LogSeverity::Info)
99+
}}
100+
}
101+
102+
/// Warning log message.
103+
#[macro_export]
104+
macro_rules! log_warn {
105+
($logger_name:expr, $($args:tt)*) => {{
106+
$crate::__impl_log!($logger_name, format_args!($($args)*),
107+
file!(), line!(), $crate::LogSeverity::Warn)
108+
}}
109+
}
110+
111+
/// Error log message.
112+
#[macro_export]
113+
macro_rules! log_error {
114+
($logger_name:expr, $($args:tt)*) => {{
115+
$crate::__impl_log!($logger_name, format_args!($($args)*),
116+
file!(), line!(), $crate::LogSeverity::Error)
117+
}}
118+
}
119+
120+
/// Fatal log message.
121+
#[macro_export]
122+
macro_rules! log_fatal {
123+
($logger_name:expr, $($args:tt)*) => {{
124+
$crate::__impl_log!($logger_name, format_args!($($args)*),
125+
file!(), line!(), $crate::LogSeverity::Fatal)
126+
}}
127+
}

0 commit comments

Comments
 (0)