.. _section-debugging: Debugging ========= .. note:: Logging is *only* available in the *Debug* libraries. |me| maintains a log of events occuring in a |me| application. Information on each event is formatted into a log entry. Each entry can be stored in a buffer, converted into a string as a displayable message, and/or redirected to a user-defined log handler. For a list of error codes, please refer to :link_connextmicro_dds_api_c_up_one:`Logging Reference `. Configuring logging ------------------- By default, |me| sets the log verbosity to *Error* (see :ref:`section-log-message-kinds` for details). The log verbosity can be changed at any time by calling :link_connextmicro_dds_api_c_up_one:`OSAPI_Log_set_verbosity() ` using the desired verbosity as a parameter. The |me| log stores new log entries in a log buffer. You can set a custom buffer size with the :link_connextmicro_dds_api_c_up_one:`OSAPI_Log_set_property() ` function. For example, to set a buffer size of 128 bytes: .. code-block:: c struct OSAPI_LogProperty prop = OSAPI_LogProperty_INIITALIZER; OSAPI_Log_get_property(&prop); prop.max_buffer_size = 128; OSAPI_Log_set_property(&prop); .. note:: If the buffer size is too small, log entries will be truncated in order to fit in the available buffer. In order to provide |me| with a mechanism for writing log messages, you have to set a function used for this purpose. This can be done via the function :link_connextmicro_dds_api_c_up_one:`OSAPI_Log_set_property() ` as well. If your application code defines the function ``my_log_write_buffer`` like this: .. code-block:: c #include static void my_log_write_buffer(const char *buffer,RTI_SIZE_T length) { write(1, buffer, length); } then you can set it as the ``write_buffer`` function for |me| as follows: .. code-block:: c struct OSAPI_LogProperty prop = OSAPI_LogProperty_INIITALIZER; OSAPI_Log_get_property(&prop); prop.write_buffer = my_log_write_buffer; OSAPI_Log_set_property(&prop); Alternatively, you can install a log handler function to process each new log entry. The handler must conform to the definition :link_connextmicro_dds_api_c_up_one:`OSAPI_LogHandler_T `, and it is set by :link_connextmicro_dds_api_c_up_one:`OSAPI_Log_set_log_handler() `. When called, the handler has parameters containing the raw log entry and detailed log information (e.g., error code, module, file and function names, line number). The log handler is called for every new log entry, even when the log buffer is full. This allows you to redirect log entries to another logger, such as one native to a particular platform. .. _section-log-message-kinds: Log message kinds ----------------- Each log entry is classified as one of the following kinds: - *Error*: An unexpected event with negative functional impact. - *Warning*: An event that may not have negative functional impact but could indicate an unexpected situation. - *Information*: An event logged for informative purposes. By default, the log verbosity is set to *Error*, so only error logs will be visible. To change the log verbosity, simply call the function :link_connextmicro_dds_api_c_up_one:`OSAPI_Log_set_verbosity() ` with the desired verbosity level. Interpreting log messages and error codes ----------------------------------------- A log entry in |me| has a defined format. Each entry contains a header with the following information: - *Length*: The length of the log message, in bytes. - *Module ID*: A numerical ID of the module from which the message was logged. - *Error Code*: A numerical ID for the log message. This ID is unique within a module. Although we refer to this as an "error" code, it exists for all log kinds (error, warning, info). The module ID and error code together uniquely identify a log message within |me|. You can also configure |me| to provide additional details per log message: - *Line Number*: The line number of the source file from which the message is logged. - *Module Name*: The name of the module from which the message is logged. - *Function Name*: The name of the function from which the message is logged. When an event is logged, by default it is printed as a message to standard output. An example error entry looks like this: .. code-block:: none [943921909.645099999]ERROR: ModuleID=7 Errcode=200 X=1 E=0 T=1 dds_c/DomainFactory.c:163/DDS_DomainParticipantFactory_get_instance: kind=19 - *X*: Extended debug information is present, such as file and line number. - *E*: Exception, the log message has been truncated. - *T*: The log message has a valid timestamp (successful call to OSAPI_System_get_time()). You will need to interpret the log message when an error or warning has occurred and its cause needs to be determined, or when you have set a log handler and are processing each log message based on its contents. You can retrieve a description of an error code printed in a log message by following these steps: - Navigate to the module that corresponds to the Module ID, or the printed module name in the second line. In the above example, ``ModuleID=7`` corresponds to DDS. - Search for the error code to find it in the list of the module's error codes. In the example above, with ``Errcode=200``, search for ``200`` to find the log message that has the value ``(DDSC_LOG_BASE + 200)``.