xref: /aosp_15_r20/external/pigweed/pw_log_tokenized/docs.rst (revision 61c4878ac05f98d0ceed94b57d316916de578985)
1*61c4878aSAndroid Build Coastguard Worker.. _module-pw_log_tokenized:
2*61c4878aSAndroid Build Coastguard Worker
3*61c4878aSAndroid Build Coastguard Worker----------------
4*61c4878aSAndroid Build Coastguard Workerpw_log_tokenized
5*61c4878aSAndroid Build Coastguard Worker----------------
6*61c4878aSAndroid Build Coastguard WorkerThe ``pw_log_tokenized`` module contains utilities for tokenized logging. It
7*61c4878aSAndroid Build Coastguard Workerconnects ``pw_log`` to ``pw_tokenizer`` and supports
8*61c4878aSAndroid Build Coastguard Worker:ref:`module-pw_log-tokenized-args`.
9*61c4878aSAndroid Build Coastguard Worker
10*61c4878aSAndroid Build Coastguard WorkerC++ backend
11*61c4878aSAndroid Build Coastguard Worker===========
12*61c4878aSAndroid Build Coastguard Worker``pw_log_tokenized`` provides a backend for ``pw_log`` that tokenizes log
13*61c4878aSAndroid Build Coastguard Workermessages with the ``pw_tokenizer`` module. The log level, 16-bit tokenized
14*61c4878aSAndroid Build Coastguard Workermodule name, and flags bits are passed through the payload argument. The macro
15*61c4878aSAndroid Build Coastguard Workereventually passes logs to the :c:func:`pw_log_tokenized_HandleLog` function,
16*61c4878aSAndroid Build Coastguard Workerwhich must be implemented by the application.
17*61c4878aSAndroid Build Coastguard Worker
18*61c4878aSAndroid Build Coastguard Worker.. doxygenfunction:: pw_log_tokenized_HandleLog
19*61c4878aSAndroid Build Coastguard Worker
20*61c4878aSAndroid Build Coastguard WorkerExample implementation:
21*61c4878aSAndroid Build Coastguard Worker
22*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp
23*61c4878aSAndroid Build Coastguard Worker
24*61c4878aSAndroid Build Coastguard Worker   extern "C" void pw_log_tokenized_HandleLog(
25*61c4878aSAndroid Build Coastguard Worker       uint32_t payload, const uint8_t message[], size_t size) {
26*61c4878aSAndroid Build Coastguard Worker     // The metadata object provides the log level, module token, and flags.
27*61c4878aSAndroid Build Coastguard Worker     // These values can be recorded and used for runtime filtering.
28*61c4878aSAndroid Build Coastguard Worker     pw::log_tokenized::Metadata metadata(payload);
29*61c4878aSAndroid Build Coastguard Worker
30*61c4878aSAndroid Build Coastguard Worker     if (metadata.level() < current_log_level) {
31*61c4878aSAndroid Build Coastguard Worker       return;
32*61c4878aSAndroid Build Coastguard Worker     }
33*61c4878aSAndroid Build Coastguard Worker
34*61c4878aSAndroid Build Coastguard Worker     if (metadata.flags() & HIGH_PRIORITY_LOG != 0) {
35*61c4878aSAndroid Build Coastguard Worker       EmitHighPriorityLog(metadata.module(), message, size);
36*61c4878aSAndroid Build Coastguard Worker     } else {
37*61c4878aSAndroid Build Coastguard Worker       EmitLowPriorityLog(metadata.module(), message, size);
38*61c4878aSAndroid Build Coastguard Worker     }
39*61c4878aSAndroid Build Coastguard Worker   }
40*61c4878aSAndroid Build Coastguard Worker
41*61c4878aSAndroid Build Coastguard WorkerSee the documentation for :ref:`module-pw_tokenizer` for further details.
42*61c4878aSAndroid Build Coastguard Worker
43*61c4878aSAndroid Build Coastguard WorkerMetadata in the format string
44*61c4878aSAndroid Build Coastguard Worker-----------------------------
45*61c4878aSAndroid Build Coastguard WorkerWith tokenized logging, the log format string is converted to a 32-bit token.
46*61c4878aSAndroid Build Coastguard WorkerRegardless of how long the format string is, it's always represented by a 32-bit
47*61c4878aSAndroid Build Coastguard Workertoken. Because of this, metadata can be packed into the tokenized string with
48*61c4878aSAndroid Build Coastguard Workerno cost.
49*61c4878aSAndroid Build Coastguard Worker
50*61c4878aSAndroid Build Coastguard Worker``pw_log_tokenized`` uses a simple key-value format to encode metadata in a
51*61c4878aSAndroid Build Coastguard Workerformat string. Each field starts with the ``■`` (U+25A0 "Black Square")
52*61c4878aSAndroid Build Coastguard Workercharacter, followed by the key name, the ``♦`` (U+2666 "Black Diamond Suit")
53*61c4878aSAndroid Build Coastguard Workercharacter, and then the value. The string is encoded as UTF-8. Key names are
54*61c4878aSAndroid Build Coastguard Workercomprised of alphanumeric ASCII characters and underscore and start with a
55*61c4878aSAndroid Build Coastguard Workerletter.
56*61c4878aSAndroid Build Coastguard Worker
57*61c4878aSAndroid Build Coastguard Worker.. code-block::
58*61c4878aSAndroid Build Coastguard Worker
59*61c4878aSAndroid Build Coastguard Worker   "■key1♦contents1■key2♦contents2■key3♦contents3"
60*61c4878aSAndroid Build Coastguard Worker
61*61c4878aSAndroid Build Coastguard WorkerThis format makes the message easily machine parseable and human readable. It is
62*61c4878aSAndroid Build Coastguard Workerextremely unlikely to conflict with log message contents due to the characters
63*61c4878aSAndroid Build Coastguard Workerused.
64*61c4878aSAndroid Build Coastguard Worker
65*61c4878aSAndroid Build Coastguard Worker``pw_log_tokenized`` uses three fields: ``msg``, ``module``, and ``file``.
66*61c4878aSAndroid Build Coastguard WorkerImplementations may add other fields, but they will be ignored by the
67*61c4878aSAndroid Build Coastguard Worker``pw_log_tokenized`` tooling.
68*61c4878aSAndroid Build Coastguard Worker
69*61c4878aSAndroid Build Coastguard Worker.. code-block::
70*61c4878aSAndroid Build Coastguard Worker
71*61c4878aSAndroid Build Coastguard Worker   "■msg♦Hyperdrive %d set to %f■module♦engine■file♦propulsion/hyper.cc"
72*61c4878aSAndroid Build Coastguard Worker
73*61c4878aSAndroid Build Coastguard WorkerUsing key-value pairs allows placing the fields in any order.
74*61c4878aSAndroid Build Coastguard Worker``pw_log_tokenized`` places the message first. This is prefered when tokenizing
75*61c4878aSAndroid Build Coastguard WorkerC code because the tokenizer only hashes a fixed number of characters. If the
76*61c4878aSAndroid Build Coastguard Workerfile were first, the long path might take most of the hashed characters,
77*61c4878aSAndroid Build Coastguard Workerincreasing the odds of a collision with other strings in that file. In C++, all
78*61c4878aSAndroid Build Coastguard Workercharacters in the string are hashed, so the order is not important.
79*61c4878aSAndroid Build Coastguard Worker
80*61c4878aSAndroid Build Coastguard WorkerThe format string is created by the :c:macro:`PW_LOG_TOKENIZED_FORMAT_STRING`
81*61c4878aSAndroid Build Coastguard Workermacro.
82*61c4878aSAndroid Build Coastguard Worker
83*61c4878aSAndroid Build Coastguard Worker.. doxygendefine:: PW_LOG_TOKENIZED_FORMAT_STRING
84*61c4878aSAndroid Build Coastguard Worker
85*61c4878aSAndroid Build Coastguard WorkerMetadata in the tokenizer payload argument
86*61c4878aSAndroid Build Coastguard Worker-------------------------------------------
87*61c4878aSAndroid Build Coastguard Worker``pw_log_tokenized`` packs runtime-accessible metadata into a 32-bit integer
88*61c4878aSAndroid Build Coastguard Workerwhich is passed as the "payload" argument for ``pw_log_tokenizer``'s global
89*61c4878aSAndroid Build Coastguard Workerhandler with payload facade. Packing this metadata into a single word rather
90*61c4878aSAndroid Build Coastguard Workerthan separate arguments reduces the code size significantly.
91*61c4878aSAndroid Build Coastguard Worker
92*61c4878aSAndroid Build Coastguard WorkerFour items are packed into the payload argument:
93*61c4878aSAndroid Build Coastguard Worker
94*61c4878aSAndroid Build Coastguard Worker- Log level -- Used for runtime log filtering by level.
95*61c4878aSAndroid Build Coastguard Worker- Line number -- Used to track where a log message originated.
96*61c4878aSAndroid Build Coastguard Worker- Log flags -- Implementation-defined log flags.
97*61c4878aSAndroid Build Coastguard Worker- Tokenized :c:macro:`PW_LOG_MODULE_NAME` -- Used for runtime log filtering by
98*61c4878aSAndroid Build Coastguard Worker  module.
99*61c4878aSAndroid Build Coastguard Worker
100*61c4878aSAndroid Build Coastguard WorkerConfiguring metadata bit fields
101*61c4878aSAndroid Build Coastguard Worker^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
102*61c4878aSAndroid Build Coastguard WorkerThe number of bits to use for each metadata field is configurable through macros
103*61c4878aSAndroid Build Coastguard Workerin ``pw_log/config.h``. The field widths must sum to 32 bits. A field with zero
104*61c4878aSAndroid Build Coastguard Workerbits allocated is excluded from the log metadata.
105*61c4878aSAndroid Build Coastguard Worker
106*61c4878aSAndroid Build Coastguard Worker.. doxygendefine:: PW_LOG_TOKENIZED_LEVEL_BITS
107*61c4878aSAndroid Build Coastguard Worker.. doxygendefine:: PW_LOG_TOKENIZED_LINE_BITS
108*61c4878aSAndroid Build Coastguard Worker.. doxygendefine:: PW_LOG_TOKENIZED_FLAG_BITS
109*61c4878aSAndroid Build Coastguard Worker.. doxygendefine:: PW_LOG_TOKENIZED_MODULE_BITS
110*61c4878aSAndroid Build Coastguard Worker
111*61c4878aSAndroid Build Coastguard WorkerCreating and reading Metadata payloads
112*61c4878aSAndroid Build Coastguard Worker^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
113*61c4878aSAndroid Build Coastguard Worker``pw_log_tokenized`` provides a C++ class to facilitate the creation and
114*61c4878aSAndroid Build Coastguard Workerinterpretation of packed log metadata payloads.
115*61c4878aSAndroid Build Coastguard Worker
116*61c4878aSAndroid Build Coastguard Worker.. doxygenclass:: pw::log_tokenized::GenericMetadata
117*61c4878aSAndroid Build Coastguard Worker.. doxygentypedef:: pw::log_tokenized::Metadata
118*61c4878aSAndroid Build Coastguard Worker
119*61c4878aSAndroid Build Coastguard WorkerThe following example shows that a ``Metadata`` object can be created from a
120*61c4878aSAndroid Build Coastguard Worker``uint32_t`` log metadata payload.
121*61c4878aSAndroid Build Coastguard Worker
122*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp
123*61c4878aSAndroid Build Coastguard Worker
124*61c4878aSAndroid Build Coastguard Worker   extern "C" void pw_log_tokenized_HandleLog(
125*61c4878aSAndroid Build Coastguard Worker       uint32_t payload,
126*61c4878aSAndroid Build Coastguard Worker       const uint8_t message[],
127*61c4878aSAndroid Build Coastguard Worker       size_t size_bytes) {
128*61c4878aSAndroid Build Coastguard Worker     pw::log_tokenized::Metadata metadata = payload;
129*61c4878aSAndroid Build Coastguard Worker     // Check the log level to see if this log is a crash.
130*61c4878aSAndroid Build Coastguard Worker     if (metadata.level() == PW_LOG_LEVEL_FATAL) {
131*61c4878aSAndroid Build Coastguard Worker       HandleCrash(metadata, pw::ConstByteSpan(
132*61c4878aSAndroid Build Coastguard Worker           reinterpret_cast<const std::byte*>(message), size_bytes));
133*61c4878aSAndroid Build Coastguard Worker       PW_UNREACHABLE;
134*61c4878aSAndroid Build Coastguard Worker     }
135*61c4878aSAndroid Build Coastguard Worker     // ...
136*61c4878aSAndroid Build Coastguard Worker   }
137*61c4878aSAndroid Build Coastguard Worker
138*61c4878aSAndroid Build Coastguard WorkerIt's also possible to get a ``uint32_t`` representation of a ``Metadata``
139*61c4878aSAndroid Build Coastguard Workerobject:
140*61c4878aSAndroid Build Coastguard Worker
141*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp
142*61c4878aSAndroid Build Coastguard Worker
143*61c4878aSAndroid Build Coastguard Worker   // Logs an explicitly created string token.
144*61c4878aSAndroid Build Coastguard Worker   void LogToken(uint32_t token, int level, int line_number, int module) {
145*61c4878aSAndroid Build Coastguard Worker     const uint32_t payload =
146*61c4878aSAndroid Build Coastguard Worker         log_tokenized::Metadata(
147*61c4878aSAndroid Build Coastguard Worker             level, module, PW_LOG_FLAGS, line_number)
148*61c4878aSAndroid Build Coastguard Worker             .value();
149*61c4878aSAndroid Build Coastguard Worker     std::array<std::byte, sizeof(token)> token_buffer =
150*61c4878aSAndroid Build Coastguard Worker         pw::bytes::CopyInOrder(endian::little, token);
151*61c4878aSAndroid Build Coastguard Worker
152*61c4878aSAndroid Build Coastguard Worker     pw_log_tokenized_HandleLog(
153*61c4878aSAndroid Build Coastguard Worker         payload,
154*61c4878aSAndroid Build Coastguard Worker         reinterpret_cast<const uint8_t*>(token_buffer.data()),
155*61c4878aSAndroid Build Coastguard Worker         token_buffer.size());
156*61c4878aSAndroid Build Coastguard Worker   }
157*61c4878aSAndroid Build Coastguard Worker
158*61c4878aSAndroid Build Coastguard WorkerThe binary tokenized message may be encoded in the :ref:`prefixed Base64 format
159*61c4878aSAndroid Build Coastguard Worker<module-pw_tokenizer-base64-format>` with the following function:
160*61c4878aSAndroid Build Coastguard Worker
161*61c4878aSAndroid Build Coastguard Worker.. doxygenfunction:: PrefixedBase64Encode(span<const std::byte>)
162*61c4878aSAndroid Build Coastguard Worker
163*61c4878aSAndroid Build Coastguard WorkerBuild targets
164*61c4878aSAndroid Build Coastguard Worker-------------
165*61c4878aSAndroid Build Coastguard WorkerThe GN build for ``pw_log_tokenized`` has two targets: ``pw_log_tokenized`` and
166*61c4878aSAndroid Build Coastguard Worker``log_backend``. The ``pw_log_tokenized`` target provides the
167*61c4878aSAndroid Build Coastguard Worker``pw_log_tokenized/log_tokenized.h`` header. The ``log_backend`` target
168*61c4878aSAndroid Build Coastguard Workerimplements the backend for the ``pw_log`` facade. ``pw_log_tokenized`` invokes
169*61c4878aSAndroid Build Coastguard Workerthe ``pw_log_tokenized:handler`` facade, which must be implemented by the user
170*61c4878aSAndroid Build Coastguard Workerof ``pw_log_tokenized``.
171*61c4878aSAndroid Build Coastguard Worker
172*61c4878aSAndroid Build Coastguard WorkerGCC has a bug resulting in section attributes of templated functions being
173*61c4878aSAndroid Build Coastguard Workerignored. This in turn means that log tokenization cannot work for templated
174*61c4878aSAndroid Build Coastguard Workerfunctions, because the token database entries are lost at build time.
175*61c4878aSAndroid Build Coastguard WorkerFor more information see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70435.
176*61c4878aSAndroid Build Coastguard WorkerIf you are using GCC, the ``gcc_partially_tokenized`` target can be used as a
177*61c4878aSAndroid Build Coastguard Workerbackend for the ``pw_log`` facade instead which tokenizes as much as possible
178*61c4878aSAndroid Build Coastguard Workerand uses the ``pw_log_string:handler`` for the rest using string logging.
179*61c4878aSAndroid Build Coastguard Worker
180*61c4878aSAndroid Build Coastguard WorkerPython package
181*61c4878aSAndroid Build Coastguard Worker==============
182*61c4878aSAndroid Build Coastguard Worker``pw_log_tokenized`` includes a Python package for decoding tokenized logs.
183*61c4878aSAndroid Build Coastguard Worker
184*61c4878aSAndroid Build Coastguard Workerpw_log_tokenized
185*61c4878aSAndroid Build Coastguard Worker----------------
186*61c4878aSAndroid Build Coastguard Worker.. automodule:: pw_log_tokenized
187*61c4878aSAndroid Build Coastguard Worker  :members:
188*61c4878aSAndroid Build Coastguard Worker  :undoc-members:
189