Debugging
=========

Overview
--------

|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, stringified into a displayable log message, 
and/or redirected to a user-defined log handler.

For a list of error codes, please refer to :link_connextmicro_dds_api_cpp_up_one:`Logging Reference <group__LoggingModule.html>`.

Configuring Logging
-------------------

By default, |me| sets the log verbosity to *Error*. It can be changed at
any time by calling **OSAPI_Log_set_verbosity()** using the desired 
verbosity as a parameter.

Note that when compiling with RTI_CERT defined, logging is completely removed.

The |me| log stores new log entries in a log buffer.  

The default buffer size is different for Debug and Release libraries. 
The Debug libraries are configured to use a much larger buffer than the Release 
ones. A custom buffer size can be configured using the **OSAPI_Log_set_property()** 
function. For example, to set a buffer size of 128 bytes::

    struct OSAPI_LogProperty prop = OSAPI_LogProperty_INIITALIZER;
    
    OSAPI_Log_get_property(&prop);
    prop.max_buffer_size = 128;
    OSAPI_Log_set_property(&prop);

Note that if the buffer size is too small, log entries will be truncated in 
order to fit in the available buffer.

The function used to write the logs can be set during compilation by 
defining the macro OSAPI_LOG_WRITE_BUFFER. This macro shall have the same parameters
as the function prototype **OSAPI_Log_write_buffer_T**.

It is also possible to set this function during runtime by using the function 
**OSAPI_Log_set_property()**::

    struct OSAPI_LogProperty prop = OSAPI_LogProperty_INIITALIZER;
    
    OSAPI_Log_get_property(&prop);
    prop.write_buffer = <pointer to user defined write function>;
    OSAPI_Log_set_property(&prop);

A user can install a log handler function to process each new log entry. The 
handler must conform to the definition OSAPI_LogHandler_T, and it is set by 
**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. An expected use case is redirecting log entries to another logger, such 
as one native to a particular platform.

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 **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. It is unique within a module. 

Though referred to 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|.  

|me| can be configured 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::

    [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()).


A log message will need to be interpreted by the user when an error or 
warning has occurred and its cause needs to be determined, or the user has 
set a log handler and is processing each log message based on its contents.

A description of an error code printed in a log message can be determined 
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)".