xref: /aosp_15_r20/external/pigweed/pw_log_string/docs.rst (revision 61c4878ac05f98d0ceed94b57d316916de578985)
1.. _module-pw_log_string:
2
3=============
4pw_log_string
5=============
6``pw_log_string`` is a partial backend for ``pw_log``. This backend fowards the
7``PW_LOG_*`` macros to the ``pw_log_string:handler`` facade which is backed by
8a C API. ``pw_log_string:handler`` does not implement the full C API, leaving
9projects to provide their own implementation of
10``pw_log_string_HandleMessageVaList``. See ``pw_log_basic`` for a similar
11``pw_log`` backend that also provides an implementation.
12
13As this module passes the log message, file name, and module name as a string to
14the handler function, it's relatively expensive and not well suited for
15space-constrained devices. This module is oriented towards usage on a host
16(e.g. a simulated device).
17
18Note that ``pw_log_string:handler`` may be used even when it's not used
19as the backend for ``pw_log`` via ``pw_log_string``. For example it can be
20useful to mix tokenized and string based logging in case you have a C ABI where
21tokenization can not be used on the other side.
22
23.. _module-pw_log_string-get-started-gn:
24
25----------------
26Get started (GN)
27----------------
28This section outlines how to implement a ``pw_log_string`` backend in a
29GN-based project.
30
31.. note::
32   The example code was written for a :ref:`host <target-host>` target running
33   on Linux.
34
35Invoke a logging macro
36======================
37Call one of the :ref:`pw_log macros <module-pw_log-macros>` in your project
38code:
39
40.. code-block:: cpp
41   :emphasize-lines: 9
42
43   /* //src/app.cc */
44
45   #include <unistd.h>
46
47   #include "pw_log/log.h"
48
49   int main() {
50       while (true) {
51           PW_LOG_INFO("Hello, world!");
52           sleep(5);
53       }
54       return 0;
55   }
56
57Implement the logging function
58==============================
59Implement :cpp:func:`pw_log_string_HandleMessageVaList()` in C. Macros like
60:cpp:func:`PW_LOG()` hand off the actual logging implementation to this
61function.
62
63The function signature of your implementation must match the one specified by
64Pigweed.
65
66The example code below just logs most of the available information to
67``stdout``:
68
69.. code-block:: c
70
71   /* //src/pw_log_string_backend.c */
72
73   #include <stdio.h>
74   #include <stdarg.h>
75
76   void pw_log_string_HandleMessageVaList(int level,
77                                          unsigned int flags,
78                                          const char* module_name,
79                                          const char* file_name,
80                                          int line_number,
81                                          const char* message,
82                                          va_list args) {
83       printf("Entering custom pw_log_string backend...\n");
84       printf("%d\n", level);
85       printf("%u\n", flags);
86       printf("%s\n", module_name);
87       printf("%s\n", file_name);
88       printf("%d\n", line_number);
89       printf("%s\n", message);
90       if (args) { /* Do something with your args here... */ }
91       printf("Exiting custom pw_log_string backend...\n\n");
92   }
93
94What exactly ``pw_log_string_HandleMessageVaList()`` should do is entirely up to
95the implementation. The log handler in ``pw_log_basic`` is one example, but it's
96also possible to encode as protobuf and send over a TCP port, write to a file,
97or even blink an LED to log as morse code.
98
99Create source sets
100==================
101.. _source set: https://gn.googlesource.com/gn/+/main/docs/reference.md#c_language-source_sets
102
103Use ``pw_source_set`` to create a `source set`_ for your logging
104implementation. Do not use GN's built-in ``source_set`` feature.
105
106.. code-block:: python
107
108   # //src/BUILD.gn
109
110   ...
111
112   pw_source_set("pw_log_string_backend") {
113       sources = [ "pw_log_string_backend.c" ]
114   }
115
116   pw_source_set("pw_log_string_backend.impl") {
117       sources = []
118   }
119
120   ...
121
122.. _//pw_log/BUILD.gn: https://cs.opensource.google/pigweed/pigweed/+/main:pw_log/BUILD.gn
123
124The empty ``pw_log_string_backend.impl`` source set prevents circular
125dependencies. See the comment for ``group("impl")`` in `//pw_log/BUILD.gn`_
126for more context.
127
128Configure backends
129==================
130Update your target toolchain configuration file:
131
132* Set ``pw_log_BACKEND`` to ``dir_pw_log_string``
133* Point ``pw_log_string_HANDLER_BACKEND`` to your source set that implements
134  :cpp:func:`pw_log_string_HandleMessageVaList()`
135* Update :ref:`pw_build_LINK_DEPS <module-pw_build-link-deps>` to include
136  ``"$dir_pw_log:impl"`` and ``"$dir_pw_log_string:handler:impl"``
137
138.. code-block:: python
139   :emphasize-lines: 11,12,14,15
140
141   # //targets/my_target/target_toolchains.gni
142
143   ...
144
145   my_target = {
146     ...
147     my_toolchain = {
148       name = "my_toolchain"
149       defaults = {
150         ...
151         pw_log_BACKEND = dir_pw_log_string
152         pw_log_string_HANDLER_BACKEND = "//src:pw_log_string_backend"
153         pw_build_LINK_DEPS = [
154           "$dir_pw_log:impl",
155           "$dir_pw_log_string:handler.impl",
156           ...
157         ]
158         ...
159       }
160     }
161   }
162
163   ...
164
165
166(Optional) Implement message handler
167====================================
168Optionally provide your own implementation of ``PW_LOG_STRING_HANDLE_MESSAGE``
169which invokes ``pw_log_string_HANDLER_BACKEND`` with your selected arguments.
170
171``assert`` wrapper
172==================
173A wrapper for ``assert`` is provided that redirects calls to the ``pw_log_string``
174handler. This can be used to replace all usage of ``assert`` in a Newlib binary
175at link time.
176
177-------------
178API reference
179-------------
180.. 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)
181