blob: e17aee6d8b08d8cf0513941d8e83a60e849be0f6 [file] [log] [blame]
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::
:depth: 2
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
.. code-block:: console
- 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``
.. code-block:: console
- "@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
The ``LOG_LEVEL`` setting applies to all modules registered with the log
Each log stream requires a ``log`` structure to define its logging
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
- 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>
static uint32_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
.. 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