Logging
-------

Mynewt log package supports logging of information within a Mynewt
application. It allows packages to define their own log streams with
separate names. It also allows an application to control the output
destination of logs. 

.. contents::
  :local:
  :depth: 2

Description
^^^^^^^^^^^

In the Mynewt OS, the log package comes in two versions:

-  The ``sys/log/full`` package implements the complete log
   functionality and API.

-  The ``sys/log/stub`` package implements stubs for the API.

Both packages export the ``log`` API, and any package that uses the log
API must list ``log`` as a requirement in its ``pkg.yml`` file as
follows:

.. code-block:: console

    pkg.req_apis:
        - log

The application's ``pkg.yml`` file specifies the version of the log
package to use. A project that requires the full logging capability must
list the ``sys/log/full`` package as a dependency in its ``pkg.yml``
file:

.. code-block:: console

    pkg.deps:
        - "@apache-mynewt-core/sys/log/full"

You can use the ``sys/log/stub`` package if you want to build your
application without logging to reduce code size.

Syscfg Settings
^^^^^^^^^^^^^^^

The ``LOG_LEVEL`` syscfg setting allows you to specify the level of logs
to enable in your application. Only logs for levels higher or equal to
the value of ``LOG_LEVEL`` are enabled. The amount of logs you include
affects your application code size. ``LOG_LEVEL: 0`` specifies
LOG\_LEVEL\_DEBUG and includes all logs. You set ``LOG_LEVEL: 255`` to
disable all logging. The ``#defines`` for the log levels are specified
in the ``sys/log/full/include/log/log.h`` file. For example the
following setting corresponds to LOG\_LEVEL\_ERROR:

.. code-block:: console

    syscfg.vals:
        LOG_LEVEL: 3   

The ``LOG_LEVEL`` setting applies to all modules registered with the log
package.

Log
~~~~~~~~~~~~~~~


Each log stream requires a ``log`` structure to define its logging
properties.

Log Handler
~~~~~~~~~~~

To use logs, a log handler that handles the I/O from the log is
required. The log package comes with three pre-built log handlers:

-  console -- streams log events directly to the console port. Does not
   support walking and reading.
-  cbmem -- writes/reads log events to a circular buffer. Supports
   walking and reading for access by newtmgr and shell commands.
-  fcb -- writes/reads log events to a :doc:`flash circular
   buffer <../fcb/fcb>`. Supports walking and reading for
   access by newtmgr and shell commands.

In addition, it is possible to create custom log handlers for other
methods. Examples may include

-  Flash file system
-  Flat flash buffer
-  Streamed over some other interface

To use logging, you typically do not need to create your own log
handler. You can use one of the pre-built ones.

A package or an application must define a variable of type
``struct log`` and register a log handler for it with the log package.
It must call the ``log_register()`` function to specify the log handler
to use:

.. code:: c

    log_register(char *name, struct log *log, const struct log_handler *lh, void *arg, uint8_t level)

The parameters are:

-  ``name``- Name of the log stream.
-  ``log`` - Log instance to register,
-  ``lh`` - Pointer to the log handler. You can specify one of the
   pre-built ones:

   -  ``&log_console_handler`` for console
   -  ``&log_cbm_handler`` for circular buffer
   -  ``&log_fcb_handler`` for flash circular buffer

-  ``arg`` - Opaque argument that the specified log handler uses. The
   value of this argument depends on the log handler you specify:

   -  NULL for the ``log_console_handler``.
   -  Pointer to an initialized ``cbmem`` structure (see ``util/cbmem``
      package) for the ``log_cbm_handler``.
   -  Pointer to an initialized ``fcb_log`` structure (see ``fs/fcb``
      package) for the ``log_fcb_handler``.

Typically, a package that uses logging defines a global variable, such
as ``my_package_log``, of type ``struct log``. The package can call the
``log_register()`` function with default values, but usually an
application will override the logging properties and where to log to.
There are two ways a package can allow an application to override the
values:

-  Define system configuration settings that an application can set and
   the package can then call the ``log_register()`` function with the
   configuration values.
-  Make the ``my_package_log`` variable external and let the application
   call the ``log_register()`` function to specify a log handler for its
   specific purpose.

Configuring Logging for Packages that an Application Uses
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Here is an example of how an application can set the log handlers for
the logs of the packages that the application includes.

In this example, the ``package1`` package defines the variable
``package1_log`` of type ``struct log`` and externs the variable.
Similarly, the ``package2`` package defines the variable
``package2_log`` and externs the variable. The application sets logs for
``package1`` to use console and sets logs for ``package2`` to use a
circular buffer.

.. code:: c

    #include <package1/package1.h>
    #include <package2/package2.h>
    #include <util/cbmem.h>

    #include <log/log.h>

    #define MAX_CBMEM_BUF 300
    static uint8_t cbmem_buf[MAX_CBMEM_BUF];
    static struct cbmem cbmem;


    void app_log_init(void)
    {


       
        log_register("package1_log", &package1_log, &log_console_handler, NULL, LOG_SYSLEVEL);

        cbmem_init(&cbmem, cbmem_buf, MAX_CBMEM_BUF);
        log_register("package2_log", &package2_log, &log_cbmem_handler, &cbmem, LOG_SYSLEVEL);

    }

Implementing a Package that Uses Logging
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

This example shows how a package logs to console. The package registers
default logging properties to use the console, but allows an application
to override the values. It defines the ``my_package_log`` variable and
makes it external so an application can override log handler.

Make the ``my_package_log`` variable external:

.. code:: c

    /* my_package.h*/

    /* pick a unique name here */
    extern struct log my_package_log;

Define the ``my_package_log`` variable and register the console log
handler:

.. code:: c

    /* my_package.c */

    struct log my_package_log;

    {
        ...

        /* register my log with a name to the system */
        log_register("log", &my_package_log, &log_console_handler, NULL, LOG_LEVEL_DEBUG);

        LOG_DEBUG(&my_package_log, LOG_MODULE_DEFAULT, "bla");
        LOG_DEBUG(&my_package_log, LOG_MODULE_DEFAULT, "bab");
    }

Log API and Log Levels
~~~~~~~~~~~~~~~~~~~~~~

.. doxygenfile:: full/include/log/log.h
