blob: b4a67efcfb218fc64580d4a9a1fa82f0682ab72e [file] [log] [blame]
.. _module-pw_log_string:
=============
pw_log_string
=============
``pw_log_string`` is a partial backend for ``pw_log``. This backend fowards the
``PW_LOG_*`` macros to the ``pw_log_string:handler`` facade which is backed by
a C API. ``pw_log_string:handler`` does not implement the full C API, leaving
projects to provide their own implementation of
``pw_log_string_HandleMessageVaList``. See ``pw_log_basic`` for a similar
``pw_log`` backend that also provides an implementation.
As this module passes the log message, file name, and module name as a string to
the handler function, it's relatively expensive and not well suited for
space-constrained devices. This module is oriented towards usage on a host
(e.g. a simulated device).
Note that ``pw_log_string:handler`` may be used even when it's not used
as the backend for ``pw_log`` via ``pw_log_string``. For example it can be
useful to mix tokenized and string based logging in case you have a C ABI where
tokenization can not be used on the other side.
.. _module-pw_log_string-get-started-gn:
----------------
Get started (GN)
----------------
This section outlines how to implement a ``pw_log_string`` backend in a
GN-based project.
.. note::
The example code was written for a :ref:`host <target-host>` target running
on Linux.
Invoke a logging macro
======================
Call one of the :ref:`pw_log macros <module-pw_log-macros>` in your project
code:
.. code-block:: cpp
:emphasize-lines: 9
/* //src/app.cc */
#include <unistd.h>
#include "pw_log/log.h"
int main() {
while (true) {
PW_LOG_INFO("Hello, world!");
sleep(5);
}
return 0;
}
Implement the logging function
==============================
Implement :cpp:func:`pw_log_string_HandleMessageVaList()` in C. Macros like
:cpp:func:`PW_LOG()` hand off the actual logging implementation to this
function.
The function signature of your implementation must match the one specified by
Pigweed.
The example code below just logs most of the available information to
``stdout``:
.. code-block:: c
/* //src/pw_log_string_backend.c */
#include <stdio.h>
#include <stdarg.h>
void pw_log_string_HandleMessageVaList(int level,
unsigned int flags,
const char* module_name,
const char* file_name,
int line_number,
const char* message,
va_list args) {
printf("Entering custom pw_log_string backend...\n");
printf("%d\n", level);
printf("%u\n", flags);
printf("%s\n", module_name);
printf("%s\n", file_name);
printf("%d\n", line_number);
printf("%s\n", message);
if (args) { /* Do something with your args here... */ }
printf("Exiting custom pw_log_string backend...\n\n");
}
What exactly ``pw_log_string_HandleMessageVaList()`` should do is entirely up to
the implementation. The log handler in ``pw_log_basic`` is one example, but it's
also possible to encode as protobuf and send over a TCP port, write to a file,
or even blink an LED to log as morse code.
Create source sets
==================
.. _source set: https://gn.googlesource.com/gn/+/main/docs/reference.md#c_language-source_sets
Use ``pw_source_set`` to create a `source set`_ for your logging
implementation. Do not use GN's built-in ``source_set`` feature.
.. code-block:: python
# //src/BUILD.gn
...
pw_source_set("pw_log_string_backend") {
sources = [ "pw_log_string_backend.c" ]
}
pw_source_set("pw_log_string_backend.impl") {
sources = []
}
...
.. _//pw_log/BUILD.gn: https://cs.opensource.google/pigweed/pigweed/+/main:pw_log/BUILD.gn
The empty ``pw_log_string_backend.impl`` source set prevents circular
dependencies. See the comment for ``group("impl")`` in `//pw_log/BUILD.gn`_
for more context.
Configure backends
==================
Update your target toolchain configuration file:
* Set ``pw_log_BACKEND`` to ``dir_pw_log_string``
* Point ``pw_log_string_HANDLER_BACKEND`` to your source set that implements
:cpp:func:`pw_log_string_HandleMessageVaList()`
* Update :ref:`pw_build_LINK_DEPS <module-pw_build-link-deps>` to include
``"$dir_pw_log:impl"`` and ``"$dir_pw_log_string:handler:impl"``
.. code-block:: python
:emphasize-lines: 11,12,14,15
# //targets/my_target/target_toolchains.gni
...
my_target = {
...
my_toolchain = {
name = "my_toolchain"
defaults = {
...
pw_log_BACKEND = dir_pw_log_string
pw_log_string_HANDLER_BACKEND = "//src:pw_log_string_backend"
pw_build_LINK_DEPS = [
"$dir_pw_log:impl",
"$dir_pw_log_string:handler.impl",
...
]
...
}
}
}
...
(Optional) Implement message handler
====================================
Optionally provide your own implementation of ``PW_LOG_STRING_HANDLE_MESSAGE``
which invokes ``pw_log_string_HANDLER_BACKEND`` with your selected arguments.
-------------
API reference
-------------
.. doxygenfunction:: pw_log_string_HandleMessageVaList(int level, unsigned int flags, const char* module_name, const char* file_name, int line_number, const char* message, va_list args)