ros2_medkit_linux_introspection
This section contains design documentation for the ros2_medkit_linux_introspection package.
Overview
The ros2_medkit_linux_introspection package provides three gateway plugins that
enrich discovered entities with Linux-specific runtime metadata. Each plugin
implements both the GatewayPlugin and IntrospectionProvider interfaces,
registering vendor extension endpoints (x-medkit-*) and feeding metadata into
the discovery merge pipeline.
Architecture
The following diagram shows the three plugins and their shared infrastructure.
Linux Introspection Plugin Architecture
Plugins
ProcfsPlugin (
procfs_introspection) - Process-level metrics from/procRegisters
x-medkit-procfscapability on Apps and ComponentsReads
/proc/{pid}/stat,/proc/{pid}/status,/proc/{pid}/cmdlineExposes: PID, PPID, state, RSS, VM size, CPU ticks, thread count, command line, exe path
Component-level endpoint aggregates processes, deduplicating by PID (multiple nodes may share a process)
SystemdPlugin (
systemd_introspection) - Systemd unit metadata via sd-busRegisters
x-medkit-systemdcapability on Apps and ComponentsMaps PID to systemd unit via
sd_pid_get_unit()Queries unit properties over D-Bus: ActiveState, SubState, NRestarts, WatchdogUSec
Component-level endpoint aggregates units, deduplicating by unit name
Uses RAII wrapper (
SdBusPtr) for sd-bus connection lifetime
ContainerPlugin (
container_introspection) - Container detection from cgroupsRegisters
x-medkit-containercapability on Apps and ComponentsReads
/proc/{pid}/cgroupto extract container ID and runtime (Docker, containerd, Podman)Component-level endpoint aggregates containers, deduplicating by container ID
Returns 404 for entities not running in a container (not an error - just bare-metal)
PidCache
All three plugins share the PidCache class for mapping ROS 2 node fully-qualified
names to Linux PIDs. The cache:
Scans
/procfor processes whose command line matches ROS 2 node naming patternsUses TTL-based refresh (default 10 seconds, configurable via
pid_cache_ttl_seconds)Is thread-safe via
std::shared_mutex(concurrent reads, exclusive writes)Each plugin instance owns its own
PidCache(no cross-plugin sharing, avoids lock contention)
The proc_root configuration parameter (default /) allows testing with a mock
/proc filesystem without running as root.
Vendor Extension Endpoints
Each plugin registers REST endpoints following the SOVD vendor extension pattern:
GET /api/v1/apps/{entity_id}/x-medkit-procfs
GET /api/v1/components/{entity_id}/x-medkit-procfs
GET /api/v1/apps/{entity_id}/x-medkit-systemd
GET /api/v1/components/{entity_id}/x-medkit-systemd
GET /api/v1/apps/{entity_id}/x-medkit-container
GET /api/v1/components/{entity_id}/x-medkit-container
All endpoints validate the entity via PluginContext::validate_entity_for_route()
and return SOVD-compliant error responses on failure.
Design Decisions
Three Separate Plugins
Each Linux subsystem (procfs, systemd, cgroups) is a separate plugin rather than
one monolithic “linux” plugin. This allows deployers to load only what they need -
for example, a containerized deployment may only want the container plugin, while
a systemd-managed robot would use the systemd plugin. Each plugin is an independent
shared library (.so) loaded at runtime.
IntrospectionProvider Dual Interface
Each plugin implements both GatewayPlugin (for HTTP routes and capabilities) and
IntrospectionProvider (for the discovery merge pipeline). The introspect()
method feeds metadata into the entity cache during each discovery cycle, while the
HTTP routes serve on-demand queries for individual entities. The C export function
get_introspection_provider() enables the plugin loader to obtain both interfaces
from a single .so file.
Configurable proc_root
The proc_root parameter defaults to / but can be overridden to point at a
mock filesystem tree. This enables unit testing of /proc parsing logic without
root privileges or actual processes, and supports containerized gateway deployments
where the host /proc is mounted at a non-standard path.