![]() |
Tesseract 0.28.4
|
Tesseract uses spdlog for severity filtering, formatting, sinks, and named logger registry access. Tesseract owns the active default logger so its convenience macros can avoid registry lookup on the logging hot path. The header tesseract/common/logging.h also adds structured records and fan-out handlers for integrations that need more than formatted text.
tesseract::common::getLogger() returns the Tesseract-owned default logger. Configure it with normal spdlog APIs:
Applications may replace the default logger during single-threaded startup, before creating worker threads or emitting log messages. The replacement must be named tesseract:
Do not call setLogger() concurrently with logging. Tesseract retains shared ownership of the replacement, and spdlog::drop("tesseract") removes only its registry entry: the default macros and getLogger() continue using the owned logger. Use setLogger() for replacement and getLogger() for normal direct configuration.
Named loggers clone the default logger's sinks, formatter, level, error handler, and flush level when they are first requested. Configure the default logger before creating named loggers when they should share the same initial setup. Tesseract libraries should use the TESSERACT_LOG_* macros rather than call a logger directly so registered structured record handlers also receive the event. Use stable subsystem names such as tesseract.environment or tesseract.collision.bullet; do not create logger names from object identifiers or other transient values.
The macros check the current runtime level before formatting. When expensive work is needed only to prepare a debug message, guard it without a registry lookup:
The TESSERACT_LOG_* macros emit both the formatted spdlog message and a tesseract::common::LogRecord. A record contains the original timestamp and severity, logger and optional component names, source location, thread ID, message, and typed attributes. Use the macros for ordinary messages. Construct a record directly when an integration needs machine-readable context that should not be encoded into the message:
Keep subsystem-specific values such as object identifiers, resource paths, operation names, and middleware endpoint identifiers in attributes. Add a first-class LogRecord field only when it has stable semantics across Tesseract subsystems and logging integrations.
Register a handler at the application boundary only when an integration needs structured records:
Calls made directly through spdlog::logger, such as logger->info(...), do not create a structured record and do not invoke LogRecordHandler callbacks. Use the Tesseract macros or call emitLogRecord() when structured fan-out is required. Handlers are additional outputs; they do not replace or reconfigure the logger's spdlog sinks. Handlers run synchronously on the logging thread. A handler that performs network, disk, or other potentially blocking work should enqueue a copy of the record and return promptly. Tesseract libraries must not install application logging handlers or configure process-wide sinks and providers.
The tesseract_rosutils package provides an adapter that forwards structured records to rcutils. Keep the RAII handler alive for as long as forwarding is required:
The severity mapping is trace/debug to DEBUG, info to INFO, warn to WARN, error to ERROR, and critical to FATAL. Logger name and source location are passed natively to rcutils. The component name and typed attributes are appended to the message as deterministic key=value text because rcutils has no structured-attribute API. rcutils assigns the ROS log timestamp when it receives the record; its public logging API cannot accept the original Tesseract timestamp.