Introduce new logging API, fixes #858

PiperOrigin-RevId: 930744288
Change-Id: I6ec1203b55c031390f3eef23192e2337508ce886
This commit is contained in:
Yuval Tassa
2026-06-11 14:36:17 -07:00
committed by Copybara-Service
parent a2abaf7aef
commit 58f6d52491
45 changed files with 2586 additions and 422 deletions
+16 -9
View File
@@ -32,10 +32,14 @@ you are simulating multiple models in parallel, they use the same set of callbac
mju_user_error
~~~~~~~~~~~~~~
This is called from within the main error function :ref:`mju_error`. When installed, this function overrides the default
error processing. Once it prints error messages (or whatever else the user wants to do), it must **exit** the program.
MuJoCo is written with the assumption that mju_error will not return. If it does, the behavior of the software is
undefined.
.. deprecated::
Use :ref:`mju_setLogHandler` instead. See :ref:`siLogHandler`.
Called by the default log handler when a fatal error occurs. If installed, this function overrides the default error
processing. It may ``longjmp`` out or return. MuJoCo is written with the assumption that error handlers will not
return; if they do, the behavior of the software is undefined.
If a custom log handler is installed via :ref:`mju_setLogHandler`, this callback is not consulted.
.. code-block:: C
@@ -47,8 +51,11 @@ undefined.
mju_user_warning
~~~~~~~~~~~~~~~~
This is called from within the main warning function :ref:`mju_warning`. It is similar to the error handler, but instead
it must return without exiting the program.
.. deprecated::
Use :ref:`mju_setLogHandler` instead. See :ref:`siLogHandler`.
Called by the default log handler when a warning occurs. If a custom log handler is installed via
:ref:`mju_setLogHandler`, this callback is not consulted.
.. code-block:: C
@@ -185,9 +192,9 @@ mjcb_time
~~~~~~~~~
Installing this callback enables the built-in profiler, and keeps timing statistics in ``mjData.timer``. The return type
is mjtNum, while the time units are up to the user. :ref:`simulate.cc <saSimulate>` assumes the unit is 1 millisecond.
In order to be useful, the callback should use high-resolution timers with at least microsecond precision. This is
because the computations being timed are very fast.
is mjtNum, while the time units are up to the user. Both :ref:`simulate.cc <saSimulate>` and the ``mjTOPIC_TIME_STP``
informational :ref:`topic <mjtLogTopic>` assume the unit is 1 millisecond. In order to be useful, the callback should
use high-resolution timers with at least microsecond precision.
.. code-block:: C
+77
View File
@@ -540,6 +540,33 @@ Sleep state of an object.
.. mujoco-include:: mjtSleepState
.. _tyLogEnums:
Logging
~~~~~~~
.. _mjtLogLevel:
mjtLogLevel
"""""""""""
Log message severity level.
.. mujoco-include:: mjtLogLevel
.. _mjtLogTopic:
mjtLogTopic
"""""""""""
Topic identifiers for informational messages. Used with :ref:`mju_info` for topic-based filtering.
Topic 0 (``mjTOPIC_NONE``) always passes through the default handler's filter. Other topics must be enabled in
the :ref:`mjLogConfig` bitmask. Since topics are 1-indexed, the bitmask for topic ``t`` is ``(1 << (t - 1))``.
.. mujoco-include:: mjtLogTopic
.. _tyVisEnums:
Visualization
@@ -1059,6 +1086,36 @@ Asset cache used by the compiler to avoid repeated slow recompilation. See :ref:
.. mujoco-include:: mjCache
.. _tyLogStructure:
Logging
^^^^^^^
.. _mjLogMessage:
mjLogMessage
~~~~~~~~~~~~
Structured log message passed to :ref:`mjfLogHandler` callbacks. Contains the severity level, optional topic for
info messages, a one-line subject, an optional multi-line body, and optional source location (function name, file
name, line number).
.. mujoco-include:: mjLogMessage
.. _mjLogConfig:
mjLogConfig
~~~~~~~~~~~
Configuration for the default log handler. Controls whether messages are printed to the console and/or written to
a log file (default: ``MUJOCO_LOG.TXT``). The ``logto_file`` field enables file logging, while ``logfile`` specifies
the file path. The ``topics`` field is a bitmask of :ref:`mjtLogTopic` values: bit ``(topic - 1)`` enables
that topic. Topic 0 (``mjTOPIC_NONE``) always passes through.
.. mujoco-include:: mjLogConfig
.. _tyStatStructure:
Sim statistics
@@ -1836,6 +1893,26 @@ mjfCollision
This is the function type of the callbacks in the collision table :ref:`mjCOLLISIONFUNC`.
.. _tyLogCallbacks:
Log Callbacks
^^^^^^^^^^^^^
.. _mjfLogHandler:
mjfLogHandler
~~~~~~~~~~~~~
.. code-block:: C
typedef void (*mjfLogHandler)(const mjLogMessage*);
This is the function type of the log handler callback installed via :ref:`mju_setLogHandler`. The handler receives
all errors, warnings and informational messages as structured :ref:`mjLogMessage` data. It must be thread-safe.
It must not call :ref:`mju_error` from within the callback.
.. _tyUICallbacks:
UI Callbacks
+112 -3
View File
@@ -1971,7 +1971,9 @@ Error and memory
.. mujoco-include:: mju_error
Main error function; does not return to caller.
Main error function. The error message is dispatched to the active log handler (see :ref:`mju_setLogHandler`).
Errors are always fatal: if the handler returns, the process is terminated with ``exit(EXIT_FAILURE)``. Handlers
wishing to recover must ``longjmp`` or otherwise transfer control before returning.
.. _mju_warning:
@@ -1980,7 +1982,7 @@ Main error function; does not return to caller.
.. mujoco-include:: mju_warning
Main warning function; returns to caller.
Main warning function; returns to caller. The warning message is dispatched to the active log handler.
.. _mju_clearHandlers:
@@ -1989,7 +1991,114 @@ Main warning function; returns to caller.
.. mujoco-include:: mju_clearHandlers
Clear user error and memory handlers.
Clear all user handlers and restore defaults. Resets the legacy error/warning/memory callbacks to ``NULL``, restores
the default log handler, and resets the log configuration to its defaults (console and file output enabled, all info
topics disabled).
.. _mju_setLogHandler:
`mju_setLogHandler <#mju_setLogHandler>`__
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. mujoco-include:: mju_setLogHandler
Set the active global log handler. Returns the previous handler (which is never ``NULL``), intended for save/restore
or callback chaining. If ``handler`` is ``NULL``, the default handler is restored. The handler receives all errors,
warnings and informational messages as a structured :ref:`mjLogMessage`. See :ref:`siLogHandler` for usage examples.
.. _mju_getLogConfig:
`mju_getLogConfig <#mju_getLogConfig>`__
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. mujoco-include:: mju_getLogConfig
Get the current default handler configuration. See :ref:`mjLogConfig`.
.. _mju_setLogConfig:
`mju_setLogConfig <#mju_setLogConfig>`__
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. mujoco-include:: mju_setLogConfig
Set the default handler configuration. Controls console output, file output, and info topic filtering.
See :ref:`mjLogConfig`.
Example usage (disabling file output):
.. code-block:: C
mjLogConfig config = mju_getLogConfig();
config.logto_file = false;
mju_setLogConfig(config);
.. _mju_info:
`mju_info <#mju_info>`__
~~~~~~~~~~~~~~~~~~~~~~~~
.. mujoco-include:: mju_info
Log an informational message with optional topic filtering. The ``topic`` argument is a :ref:`mjtLogTopic` value.
Topic 0 (``mjTOPIC_NONE``) always passes through. Other topics must be enabled in the default handler configuration
via :ref:`mju_setLogConfig`. Note that topic filtering is implemented in the default handler; custom handlers
receive all info messages regardless.
.. _mju_message:
`mju_message <#mju_message>`__
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. mujoco-include:: mju_message
Dispatch a structured :ref:`mjLogMessage` to the active log handler. This is the primary entry point for emitting
log messages with full control over all fields. The convenience functions :ref:`mju_error`, :ref:`mju_warning`, and
:ref:`mju_info` are thin wrappers that populate an ``mjLogMessage`` and call this function.
The ``subject`` field is a one-line summary (up to 1024 bytes, inline in the struct). The ``body`` field is an
optional ``const char*`` pointer to multi-line detail text, owned by the caller. When ``body`` is ``NULL``, only the
subject line is printed.
The default handler formats the output as follows:
.. code-block:: text
LEVEL FUNC (FILE:LINE) TIME: SUBJECT
BODY
where:
- ``LEVEL`` is ``ERROR``, ``WARNING``, ``INFO``, or ``DEBUG``.
- ``FUNC`` is present when the ``func`` field is set.
- ``(FILE:LINE)`` is present when the ``file`` and ``line`` fields are set.
- ``TIME`` is present when the ``timestamp`` field is set or file logging is active.
- ``SUBJECT`` is the contents of the ``subject`` field.
- ``BODY`` follows on the next line(s), printed raw without indentation or separators, only if non-NULL.
The default handler appends a trailing blank line after ``ERROR``, ``WARNING``, and ``INFO`` messages for visual
separation. ``DEBUG`` messages are printed compactly without a trailing blank line.
Example usage:
.. code-block:: C
mjLogMessage msg = {
.level = mjLOG_INFO,
.timestamp = true,
.body = " height: 0.001 m\n velocity: 0.000 m/s\n bounces: 47",
};
snprintf(msg.subject, sizeof(msg.subject), "The ball has come to rest");
mju_message(&msg);
This produces:
.. code-block:: text
INFO Mon Jun 9 15:04:05 2026: The ball has come to rest
height: 0.001 m
velocity: 0.000 m/s
bounces: 47
.. _mju_malloc:
+96
View File
@@ -463,6 +463,102 @@ time, while :ref:`mjui_update` is called only when changes in the UI take place.
.. _Errorandmemory:
.. _mju_error:
Main error function. The error message is dispatched to the active log handler (see :ref:`mju_setLogHandler`).
Errors are always fatal: if the handler returns, the process is terminated with ``exit(EXIT_FAILURE)``. Handlers
wishing to recover must ``longjmp`` or otherwise transfer control before returning.
.. _mju_warning:
Main warning function; returns to caller. The warning message is dispatched to the active log handler.
.. _mju_clearHandlers:
Clear all user handlers and restore defaults. Resets the legacy error/warning/memory callbacks to ``NULL``, restores
the default log handler, and resets the log configuration to its defaults (console and file output enabled, all info
topics disabled).
.. _mju_setLogHandler:
Set the active global log handler. Returns the previous handler (which is never ``NULL``), intended for save/restore
or callback chaining. If ``handler`` is ``NULL``, the default handler is restored. The handler receives all errors,
warnings and informational messages as a structured :ref:`mjLogMessage`. See :ref:`siLogHandler` for usage examples.
.. _mju_getLogConfig:
Get the current default handler configuration. See :ref:`mjLogConfig`.
.. _mju_setLogConfig:
Set the default handler configuration. Controls console output, file output, and info topic filtering.
See :ref:`mjLogConfig`.
Example usage (disabling file output):
.. code-block:: C
mjLogConfig config = mju_getLogConfig();
config.logto_file = false;
mju_setLogConfig(config);
.. _mju_info:
Log an informational message with optional topic filtering. The ``topic`` argument is a :ref:`mjtLogTopic` value.
Topic 0 (``mjTOPIC_NONE``) always passes through. Other topics must be enabled in the default handler configuration
via :ref:`mju_setLogConfig`. Note that topic filtering is implemented in the default handler; custom handlers
receive all info messages regardless.
.. _mju_message:
Dispatch a structured :ref:`mjLogMessage` to the active log handler. This is the primary entry point for emitting
log messages with full control over all fields. The convenience functions :ref:`mju_error`, :ref:`mju_warning`, and
:ref:`mju_info` are thin wrappers that populate an ``mjLogMessage`` and call this function.
The ``subject`` field is a one-line summary (up to 1024 bytes, inline in the struct). The ``body`` field is an
optional ``const char*`` pointer to multi-line detail text, owned by the caller. When ``body`` is ``NULL``, only the
subject line is printed.
The default handler formats the output as follows:
.. code-block:: text
LEVEL FUNC (FILE:LINE) TIME: SUBJECT
BODY
where:
- ``LEVEL`` is ``ERROR``, ``WARNING``, ``INFO``, or ``DEBUG``.
- ``FUNC`` is present when the ``func`` field is set.
- ``(FILE:LINE)`` is present when the ``file`` and ``line`` fields are set.
- ``TIME`` is present when the ``timestamp`` field is set or file logging is active.
- ``SUBJECT`` is the contents of the ``subject`` field.
- ``BODY`` follows on the next line(s), printed raw without indentation or separators, only if non-NULL.
The default handler appends a trailing blank line after ``ERROR``, ``WARNING``, and ``INFO`` messages for visual
separation. ``DEBUG`` messages are printed compactly without a trailing blank line.
Example usage:
.. code-block:: C
mjLogMessage msg = {
.level = mjLOG_INFO,
.timestamp = true,
.body = " height: 0.001 m\n velocity: 0.000 m/s\n bounces: 47",
};
snprintf(msg.subject, sizeof(msg.subject), "The ball has come to rest");
mju_message(&msg);
This produces:
.. code-block:: text
INFO Mon Jun 9 15:04:05 2026: The ball has come to rest
height: 0.001 m
velocity: 0.000 m/s
bounces: 47
.. _Standardmath:
The "functions" in this section are preprocessor macros replaced with the corresponding C standard library math