Skip to content

Commit e658f7e

Browse files
committed
[WIP]feat(agnocastlib): add --disable-external-lib-logs arg
1 parent 398f0fe commit e658f7e

3 files changed

Lines changed: 68 additions & 6 deletions

File tree

docs/agnocast_node_interface_comparison.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -200,8 +200,8 @@ This provides the same argument parsing functionality as rcl.
200200
| `--` (end marker) || **Full Support** | - | ROS arguments end marker |
201201
| `-r node:old:=new` || **Full Support** | - | Node-specific remapping |
202202
| `--log-level` || **Full Support** | - | Set log level |
203-
| `--enable-rosout-logs` | - | **Supportable** | TBD | Enable logging to rosout |
204-
| `--disable-external-lib-logs` | - | **Default** | - | Disable external library logs |
203+
| `--enable-rosout-logs` | | **Full Support** | - | Enable logging to rosout |
204+
| `--disable-external-lib-logs` | | **Full Support** | - | Disable external library logs |
205205
| `--disable-stdout-logs` || **Full Support** | - | Disable stdout logging |
206206
| `-e` (enclave) || **Unsupported** | - | Specify security enclave |
207207

src/agnocastlib/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ find_package(std_msgs REQUIRED)
3131
find_package(ament_index_cpp REQUIRED)
3232
find_package(message_filters REQUIRED)
3333
find_package(glog REQUIRED)
34+
find_package(spdlog REQUIRED)
3435

3536
add_library(agnocast SHARED
3637
src/agnocast.cpp src/agnocast_utils.cpp src/agnocast_publisher.cpp src/agnocast_subscription.cpp
@@ -52,6 +53,7 @@ target_link_libraries(agnocast
5253
${rcl_yaml_param_parser_LIBRARIES}
5354
${tracetools_LIBRARIES}
5455
${LTTNGUST_LIBRARIES}
56+
spdlog::spdlog
5557
)
5658

5759
target_include_directories(agnocast PUBLIC

src/agnocastlib/src/node/agnocast_context.cpp

Lines changed: 64 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,17 @@
33
#include <rcl/log_level.h>
44
#include <rcutils/logging.h>
55

6+
#include <spdlog/sinks/basic_file_sink.h>
7+
#include <spdlog/spdlog.h>
8+
9+
#include <unistd.h>
10+
11+
#include <chrono>
12+
#include <cstdlib>
13+
#include <filesystem>
14+
#include <iomanip>
15+
#include <sstream>
16+
617
#include "agnocast/agnocast_tracepoint_wrapper.h"
718

819
namespace agnocast
@@ -11,6 +22,48 @@ namespace agnocast
1122
Context g_context;
1223
std::mutex g_context_mtx;
1324

25+
/// Generate a ROS2-style log directory path: ~/.ros/log/<timestamp-hostname-pid>/
26+
static std::string generate_log_directory()
27+
{
28+
std::string base_dir;
29+
const char * ros_log_dir = std::getenv("ROS_LOG_DIR");
30+
const char * ros_home = std::getenv("ROS_HOME");
31+
if (ros_log_dir && ros_log_dir[0] != '\0') {
32+
base_dir = ros_log_dir;
33+
} else if (ros_home && ros_home[0] != '\0') {
34+
base_dir = std::string(ros_home) + "/log";
35+
} else {
36+
const char * home = std::getenv("HOME");
37+
base_dir = std::string(home ? home : "/tmp") + "/.ros/log";
38+
}
39+
40+
auto now = std::chrono::system_clock::now();
41+
auto time_t_now = std::chrono::system_clock::to_time_t(now);
42+
auto us =
43+
std::chrono::duration_cast<std::chrono::microseconds>(now.time_since_epoch()).count() % 1000000;
44+
std::tm tm_buf{};
45+
localtime_r(&time_t_now, &tm_buf);
46+
47+
char hostname[256] = {};
48+
gethostname(hostname, sizeof(hostname));
49+
50+
std::ostringstream oss;
51+
oss << base_dir << "/" << std::put_time(&tm_buf, "%Y-%m-%d-%H-%M-%S") << "-"
52+
<< std::setfill('0') << std::setw(6) << us << "-" << hostname << "-" << getpid();
53+
return oss.str();
54+
}
55+
56+
static void initialize_spdlog(const std::string & log_dir)
57+
{
58+
std::filesystem::create_directories(log_dir);
59+
std::string log_file = log_dir + "/agnocast.log";
60+
spdlog::drop("agnocast");
61+
auto logger = spdlog::basic_logger_mt("agnocast", log_file);
62+
logger->set_pattern("[%Y-%m-%d %H:%M:%S.%e] [%l] %v");
63+
logger->flush_on(spdlog::level::warn);
64+
spdlog::set_default_logger(logger);
65+
}
66+
1467
static void noop_log_output_handler(
1568
const rcutils_log_location_t *, int, const char *, rcutils_time_point_value_t, const char *,
1669
va_list *)
@@ -48,11 +101,11 @@ void Context::init(int argc, char const * const * argv)
48101
rcl_reset_error();
49102
}
50103

51-
// Apply --disable-stdout-logs and detect --enable-rosout-logs within --ros-args scope.
52-
// There is no public rcl API to extract these flags from rcl_arguments_t, so we scan argv
53-
// directly. rcl_logging_configure() cannot be used as it would initialize spdlog and attempt to
54-
// set up a rosout publisher (which requires rcl_node_t), neither of which exist in agnocast.
104+
// Scan argv for flags that have no public rcl getter API.
105+
// rcl_logging_configure() is not used because it would replace the rcutils output handler
106+
// and couple agnocast to rcl's logging lifecycle.
55107
bool in_ros_args = false;
108+
bool disable_external_lib_logs = false;
56109
for (const auto & arg : args) {
57110
if (arg == "--ros-args") {
58111
in_ros_args = true;
@@ -63,10 +116,17 @@ void Context::init(int argc, char const * const * argv)
63116
rcutils_logging_set_output_handler(noop_log_output_handler);
64117
} else if (arg == "--enable-rosout-logs") {
65118
enable_rosout_logs_ = true;
119+
} else if (arg == "--disable-external-lib-logs") {
120+
disable_external_lib_logs = true;
66121
}
67122
}
68123
}
69124

125+
// Initialize spdlog file logging unless explicitly disabled.
126+
if (!disable_external_lib_logs) {
127+
initialize_spdlog(generate_log_directory());
128+
}
129+
70130
initialized_ = true;
71131

72132
TRACEPOINT(agnocast_init, static_cast<const void *>(this));

0 commit comments

Comments
 (0)