Use a relative target for the `latest` log symlink so it survives different absolute mount paths (host/Docker)
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 155
- Forks
- 182
- Avg merge
- 2d 14h
- Merged PRs (30d)
- 6
Description
Description
launch.logging maintains a latest symlink pointing at the most recent log directory. It is created in _renew_latest_log_dir() with an absolute target:
https://github.com/ros2/launch/blob/rolling/launch/launch/logging/__init__.py#L93-L108
def _renew_latest_log_dir(*, log_dir: str) -> bool:
base_dir = os.path.dirname(log_dir)
latest_dir = os.path.join(base_dir, 'latest')
if os.path.lexists(latest_dir):
if not os.path.islink(latest_dir):
return False
os.unlink(latest_dir)
os.symlink(log_dir, latest_dir, target_is_directory=True) # absolute target
return True
Because latest and the dated log directory are always siblings in base_dir, the link target could just as well be relative (the directory's basename). Proposed change:
os.symlink(
os.path.basename(log_dir), latest_dir, target_is_directory=True)
Motivation
The absolute target breaks whenever the log directory is viewed under a different absolute path than the one in effect when the link was written. The most common case is a shared/mounted log directory between a host and a Docker container:
- Container writes logs to
/root/.ros/log, solatest -> /root/.ros/log/<run>. - The same volume is mounted on the host at e.g.
/home/user/ros-logs, where/root/.ros/log/<run>does not exist, solatestdangles.
The reverse (host writes, container reads) fails the same way. It also affects any setup where the logs are relocated, bind-mounted, or inspected from a different mount namespace.
A relative target resolves correctly regardless of the absolute mount point, since latest and its target stay in the same directory. There is no scenario in which latest and the dated directory are not siblings, so the relative form is always equivalent for in-place use and strictly more portable.
Design / Implementation Considerations
- One-line change in
_renew_latest_log_dir(): useos.path.basename(log_dir)as the symlink target instead of the fulllog_dir. target_is_directory=Trueis retained (only relevant on Windows).- Reading
os.path.realpath(latest_dir)/ accessing files throughlatest/is unchanged for local use — a relative symlink resolves identically when the CWD-independent parent directory is intact. - Tools that call
os.readlink('.../latest')and expect an absolute path would now get a basename. This seems unlikely (the documented/contract value is "the latest log directory", reachable via the link itself), but it is the one behavioural difference worth noting. - Backward compatibility: existing
latestlinks are recreated on the next run, so no migration is needed.
I'm happy to open a PR with the change plus a test asserting the link target is relative and still resolves to the run directory.
Additional Information
We currently work around this downstream by monkey-patching _renew_latest_log_dir to emit a relative target. It would be cleaner for launch to do this by default, as there appears to be no downside for the standard local-use case.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in launch/launch/logging/init.py at _renew_latest_log_dir(), where the latest symlink is created. Check the existing logging tests, then verify that the link target is relative and still resolves to the dated log directory when accessed through latest/.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- tooling
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 82/100