blob: de28a7b901166d60f888d5b69e297a68ea03e77e [file] [log] [blame]
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