ROS Resources: Documentation | Support | Discussion Forum | Index | Service Status | ros @ Robotics Stack Exchange
Ask Your Question
5

ROS2 disable logging to file

asked 2021-02-14 05:56:06 -0500

grouchy gravatar image

On ROS2 Foxy, it seems rclcpp nodes create log files in ~/.ros/log. Is there any way to disable this file logging, but still log to stdout/stderr and /rosout?

The reason I want to do this is because I am running ROS2 on an embedded system and nodes should run for weeks or months, and I will need to rotate the log files occasionally because storage space is at a premium. Journald is a good way to do this, and is well documented. When ROS2 nodes are run under systemd, the stdout/stderr logging is enough to get everything working as I want it. I could delete the .ros/log directory every now and again on a cron job, but this feels like a hack. I would also like to minimize the amount of eMMC thrashing.

Here is a similar question for ROS 1, but the answer was fairly unsatisfactory. I was hoping ROS2 would be more geared toward production systems and thus would support this out of the box.

The concept page on logging mentions very little and the logging tutorial mentions how to change the log dir, but not how to disable it. Also, this functionality only works on Galactic.

It seems this file logging feature is actually relatively new, here is a discussion on adding the file logging feature from 2019. In this discussion, wjwwood mentioned

For production system [logging to systemd] makes sense though, and because of that it should be possible to disable file logging in favor of just printing to stdout/stderr.

Here is a long discussion on logging and the linked comment discusses modifying the rcl_logging_spdlog package is the way to go. This question confirms that recompiled is required. This seems like the best option for me right now? Looking at the default spdlog logger it looks like it doesn't support an external config file yet, but I guess this could be the way to go in the future.

edit retag flag offensive close merge delete

Comments

Here is a similar question for ROS 1, but the answer was fairly unsatisfactory

that question, and the answers, is from 2011 ..

Since then there have been quite a few changes: Disable logging to /rosout, Disable all logging, ros/ros_comm#139 and ros/rosconsole#8.

gvdhoorn gravatar image gvdhoorn  ( 2021-02-14 06:10:41 -0500 )edit

Thanks for the extra info @gvdhoorn. I didn't want to include too many links to ROS1-specific solutions in my question, because this question is about ROS2.

grouchy gravatar image grouchy  ( 2021-02-14 07:02:49 -0500 )edit

I know it is. I just wanted to help future readers.

It's unclear to me why you mention that Q&A at all, as it doesn't really matter here whether a question from 2011 gave a satisfactory answer for a ROS version you're not using.

gvdhoorn gravatar image gvdhoorn  ( 2021-02-14 07:13:05 -0500 )edit

I guess I wanted to show I'd searched for similar questions before posting a new one. I should have said: "Here is a similar question for ROS 1, but the answers are not applicable to ROS2"

grouchy gravatar image grouchy  ( 2021-02-14 07:17:51 -0500 )edit
1

Agreed that this is a missing feature. Especially because logging from launch scripts can be configured; e.g.:

output='screen' will prevent logging to file, and

output='own_log' will cause every node to log to it's own file inside a common folder.

The launch configuration of logging is however in addition to direct file logging. Meaning, that:

output='screen' causes logging to file to be disabled from launch, but logs from each node are still saved to file, and

output='own_log' causes every log file to be duplicated inside the launch directory.

rasmusan- gravatar image rasmusan-  ( 2021-04-15 09:09:54 -0500 )edit

2 Answers

Sort by ยป oldest newest most voted
0

answered 2023-01-26 01:13:36 -0500

Okay so I found a solution by creating a replacement for ros2 launch. Just put the following into a Python script like quiet_launch.py and use it in place of ros2 launch to launch your launch file. I hope this comes in handy for anyone looking for a way to turn off all log file generation. Only tested on an old version of foxy.

# STEP 1

# Instead of creating a unique directory for logs, leave it up to the user.
# Here we're just making the dir if it doesn't exist.
# Log dir should be set through the ROS_LOG_DIR env var.

from launch import logging

import os


def make_log_dir(*, base_path):
    os.makedirs(base_path, exist_ok=True)

    return base_path


logging._make_unique_log_dir = make_log_dir

# STEP 2

# Replace the log file handler used by `launch` with any log file handler
# you want. Here we're using NullHandler so `launch` doesn't log to file.

# It's unfortunate there is no type completion here but we need the wrapped version
# of the log file handler from `launch`. Refer module launch.logging.handlers.
# For full list of handlers, refer module logging.handlers.

from launch.logging.handlers import NullHandler

logging.launch_config.log_handler_factory = lambda path, encoding=None: NullHandler()

# Here's an example of setting up a timed rotating file handler:

# from launch.logging.handlers import TimedRotatingFileHandler

# logging.launch_config.log_handler_factory = (
#     lambda path, encoding=None: TimedRotatingFileHandler(
#         path, when="S", interval=10, backupCount=3, encoding=encoding
#     )
# )

# STEP 3

# Make sure you set your log output type when launching your node. I.e.
# output='screen'. Refer to options below.

# You can override all node setting by setting the env var as below:
# OVERRIDE_LAUNCH_PROCESS_OUTPUT='screen'

# - 'screen': stdout and stderr are logged to the screen,
# - 'log': stdout and stderr are logged to launch log file and stderr to
#       the screen,
# - 'both': both stdout and stderr are logged to the screen and to launch
#       main log file,
# - 'own_log' for stdout, stderr and their combination to be logged to
#       their own log files, and
# - 'full' to have stdout and stderr sent to the screen, to the main launch
#       log file, and their own separate and combined log files.

# STEP 4

# For C++ nodes, if you want to disable file logging you need to pass `ros-arg`
# `disable-external-lib-logs`. Due to a bug in launch_ros.actions.node (line 180)
# you need to manually prepend "--ros-args" for the argument to be processed. I.e.:

# arguments=[
#     "--ros-args",
#     "--disable-external-lib-logs",
# ],

# STEP 5

# When you launch a lifecycle node, `launch_ros.ros_adapters` creates a node
# for lifecycle-node-specific features to be started (i.e. a '/change_state'
# service is created). Unfortunately, no mechanism has been provided to pass
# ros-args to rclpy.init when it is called.
# Here we patch the module to insert the ros-args we want so a log file isn't
# created by `launch_ros`.

from launch_ros import ros_adapters


class MyROSAdapter(ros_adapters.ROSAdapter):
    def __init__(self, *, argv=None, autostart=True):
        argv = [] if argv is None else argv
        argv.extend(["--ros-args", "--disable-external-lib-logs"])
        super().__init__(argv=argv, autostart=autostart)


ros_adapters.ROSAdapter = MyROSAdapter

# STEP 6

# Implement the bare-minimum needed ...
(more)
edit flag offensive delete link more
0

answered 2022-06-27 04:09:43 -0500

Try xrgtn/nullfs. I tried xrgtn/nullfs with raspberry pi 4, ubuntu20.04 and ros2 foxy. It worked fine.

Detail procedure to install and test xrgtn/nullfs as follows.

(1)Install xrgtn/nullfs
sudo apt update
sudo apt install -y git libfuse-dev build-essential
git clone https://github.com/xrgtn/nullfs
cd nullfs/
make nullfs

(2)Make nullfs directry
mkdir ~/nulldir
./nullfs ~/nulldir/

(3)Change ROS_LOG_DIR
Add folowing lines at the end of ~/.bashrc
export ROS_LOG_DIR=~/nulldir
~/nullfs/nullfs ~/nulldir

(4)Test
source ~/.bashrc
Run any ROS/ROS2 program and check that no files in ~/.ros/log and ~/nulldir.

edit flag offensive delete link more

Question Tools

2 followers

Stats

Asked: 2021-02-14 05:56:06 -0500

Seen: 2,041 times

Last updated: Jun 27 '22