Class LogProvider
Defined in File log_provider.hpp
Class Documentation
-
class LogProvider
Provider interface for log storage backends.
Typed provider interface implemented by plugins alongside GatewayPlugin via multiple inheritance. When a LogProvider plugin is loaded, LogManager delegates all query/config operations to it and stops using the local /rosout ring buffer for serving results.
Multiple plugins implementing LogProvider can be loaded; only the first registered LogProvider is used for queries (same as UpdateProvider). ALL LogProvider plugins receive on_log_entry() calls (observer pattern) - unless the primary provider returns true from manages_ingestion(), in which case the /rosout subscription is never created and on_log_entry() is never called.
Two modes of operation:
Observer mode (default, manages_ingestion() == false): LogManager subscribes to /rosout and feeds entries to all observers via on_log_entry(). The primary provider replaces the query/config backend; the /rosout ring buffer is still populated unless on_log_entry() returns true.
Full ingestion (manages_ingestion() == true): The primary provider owns the entire log pipeline - choosing its own source (journald, CloudWatch, custom topics), format, and storage. LogManager skips the /rosout subscription and ring buffer entirely.
See also
GatewayPlugin for the base class all plugins must also implement
See also
LogManager for the subsystem that uses this
- Thread safety
All methods may be called from multiple threads concurrently. Implementations must provide their own synchronization.
- Example use cases
OpenTelemetry exporter: implement on_log_entry() to forward to OTLP endpoint
Database backend: implement get_logs() to query a SQLite/InfluxDB/etc. store
Log aggregator: combine /rosout with external log sources
Full ingestion: subscribe to journald/CloudWatch/custom topics directly
Public Functions
-
virtual ~LogProvider() = default
-
inline virtual bool manages_ingestion() const
Whether this provider fully manages log ingestion.
When true, LogManager skips the /rosout subscription and ring buffer entirely. The plugin is responsible for sourcing log entries from whatever transport it chooses (journald, CloudWatch, custom ROS 2 topics, etc.).
When false (the default), LogManager subscribes to /rosout and populates the ring buffer as usual; all LogProvider observers receive on_log_entry() calls.
Only the primary LogProvider’s return value is checked (at LogManager construction).
- Returns:
true if the plugin owns the entire log pipeline; false for observer mode
-
virtual std::vector<LogEntry> get_logs(const std::vector<std::string> &node_fqns, bool prefix_match, const std::string &min_severity, const std::string &context_filter, const std::string &entity_id) = 0
Query log entries for a set of node names.
- Parameters:
node_fqns – Node FQNs WITHOUT leading slash (e.g. “powertrain/engine/temp_sensor”)
prefix_match – If true, treat each entry as a namespace prefix (for Component queries). If false, match exactly (for App queries).
min_severity – Optional additional severity filter (“debug”,”info”,”warning”,”error”,”fatal”). Empty string = no additional filter beyond entity config.
context_filter – Optional substring filter applied to the log entry’s node/logger name.
entity_id – Entity ID for config lookup (determines base severity_filter and max_entries).
- Returns:
LogEntry objects sorted by id ascending, capped at config.max_entries. LogManager handles JSON serialization via entry_to_json().
-
virtual LogConfig get_config(const std::string &entity_id) const = 0
Get the current log configuration for an entity.
- Returns:
Entity config (default values if entity was never configured)
-
virtual std::string update_config(const std::string &entity_id, const std::optional<std::string> &severity_filter, const std::optional<size_t> &max_entries) = 0
Update log configuration for an entity.
- Returns:
Empty string on success, error message on validation failure
-
inline virtual bool on_log_entry(const LogEntry &entry)
Called for each /rosout log entry before it is stored in the default ring buffer.
All LogProvider plugins receive this call (observer pattern), regardless of whether they are the primary query provider.
OR-aggregation: if ANY observer returns true, ring buffer storage is suppressed. All observers are always called regardless of earlier return values.
Example: An OpenTelemetry plugin forwards to OTLP and returns false (keeps ring buffer). A database plugin stores in SQLite, returns true (replaces ring buffer for that entry).
Note
This method is never called when the primary provider’s manages_ingestion() returns true, because the /rosout subscription is not created in that case.
- Parameters:
entry – The log entry (name field is WITHOUT leading slash)
- Returns:
true to suppress default ring buffer storage; false to allow it (default)