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