Tesseract 0.28.4
Loading...
Searching...
No Matches
Logging

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.

Native spdlog configuration

tesseract::common::getLogger() returns the Tesseract-owned default logger. Configure it with normal spdlog APIs:

logger->set_level(spdlog::level::debug);
logger->set_pattern("[%Y-%m-%d %T.%e] [%n] [%l] %v");
TESSERACT_LOG_INFO("Loaded {} links", link_count);
TESSERACT_LOG_DEBUG_NAMED("tesseract.environment", "Revision {}", revision);
Structured logging extensions for spdlog.
#define TESSERACT_LOG_INFO(...)
Emit an informational record through the default tesseract logger.
Definition logging.h:264
#define TESSERACT_LOG_DEBUG_NAMED(name,...)
Emit a debug record through a named logger.
Definition logging.h:275
std::shared_ptr< spdlog::logger > getLogger(std::string_view name="tesseract")
Get the Tesseract-owned default logger or a registered named logger.
Definition logging.cpp:182

Applications may replace the default logger during single-threaded startup, before creating worker threads or emitting log messages. The replacement must be named tesseract:

auto logger = std::make_shared<spdlog::logger>("tesseract", application_sink);
logger->set_level(spdlog::level::debug);
tesseract::common::setLogger(std::move(logger));
void setLogger(std::shared_ptr< spdlog::logger > logger)
Replace the default Tesseract logger.
Definition logging.cpp:216

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:

if (tesseract::common::isLogLevelEnabled(spdlog::level::debug))
buildAndLogDebugDetails();
bool isLogLevelEnabled(spdlog::level::level_enum level) noexcept
Check whether the default Tesseract logger accepts a severity.
Definition logging.cpp:229

Structured records

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:

record.level = spdlog::level::warn;
record.logger_name = "tesseract.environment";
record.component_name = "environment";
record.message = "Command rejected";
record.attributes.emplace("revision", std::int64_t{ revision });
record.attributes.emplace("command_type", command_type);
#define TESSERACT_LOG_SOURCE_LOCATION
Capture the current source file, line, and function for a log record.
Definition logging.h:243
void emitLogRecord(const LogRecord &record) noexcept
Emit a structured record through its spdlog logger and all registered handlers.
Definition logging.cpp:336
Structured representation of a Tesseract log event.
Definition logging.h:51
LogAttributes attributes
Typed application-defined attributes attached to the event.
Definition logging.h:74
spdlog::source_loc source_location
Source file, line, and function at which the event originated.
Definition logging.h:68
spdlog::level::level_enum level
Native spdlog severity of the event.
Definition logging.h:56
std::string message
Fully formatted human-readable event message.
Definition logging.h:65
std::string component_name
Logical component that produced the event, if known.
Definition logging.h:62
std::string logger_name
Name of the spdlog logger that owns the event.
Definition logging.h:59

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:

[](const tesseract::common::LogRecord& record) {
exportRecord(record);
});
// Remove the handler before destroying state captured by its callback.
LogRecordHandlerId addLogRecordHandler(LogRecordHandler handler)
Register a callback that receives structured log records.
Definition logging.cpp:235
bool removeLogRecordHandler(LogRecordHandlerId id) noexcept
Unregister a structured-record callback.
Definition logging.cpp:251

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.

ROS 2 adapter

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:

#include <tesseract_rosutils/log_record_handler.h>
tesseract_rosutils::RosLogRecordHandler ros_logging;
ros_logging.start();

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.