xref: /aosp_15_r20/external/pigweed/pw_log/protobuf.rst (revision 61c4878ac05f98d0ceed94b57d316916de578985)
1.. _module-pw_log-protobuf:
2
3-------------------
4The pw_log protobuf
5-------------------
6.. pigweed-module-subpage::
7   :name: pw_log
8
9``pw_log`` defines a protocol buffer for storing and transmitting log messages.
10The protobuf is optimized to be maximally efficient.
11
12Fields
13======
14The ``pw_log`` protobuf is defined in ``log.proto``.
15
16.. literalinclude:: log.proto
17  :language: protobuf
18  :lines: 14-
19
20Timestamps
21----------
22Timestamps are specified in implementation-defined ticks. Ticks could be
23milliseconds, microsends, or any arbitrary duration derived from the device’s
24clock.
25
26For many applications, the timestamp field can be interpreted based on the prior
27knowledge of the system. For example, ``timestamp`` might be known to be
28milliseconds since boot for one core or microseconds since boot for another.
29
30If desired, a project could collect information about clock parameters
31separately from ``pw_log``, and use that to interpret log timestamps. For
32example, they may call an RPC that returns a ``pw_chrono`` ``ClockParamters``
33protobuf. The values from that could be used to interpret timestamp from that
34device.
35
36The ``pw_log`` proto contains two timestamp fields, only one of which may be set
37at a time:
38
39- ``timestamp`` – Absolute time when message was logged.
40- ``time_since_last_entry`` – When the message was logged, relative
41  to the previously encoded log message. This is used when multiple log entries
42  are sent in a single ``LogEntries`` proto. The previous log entry must use the
43  same time source. If logs with multiple time sources are intermingled in a
44  single ``LogEntries`` proto, they must use an absolute timestamp each time the
45  time source changes.
46
47Optionally tokenized text fields
48--------------------------------
49Several fields in the ``pw_log`` proto store text. Examples include ``message``,
50``module``, and ``thread``. These fields may contain either plain or tokenized
51text, either of which is represented as a single bytes field. These fields are
52marked with a protocol buffer option so the ``pw_tokenizer.proto`` module can
53detect and detokenize tokenized fields as appropriate.
54
55See :ref:`module-pw_tokenizer-proto` for details.
56
57Packing and unpacking line_level
58--------------------------------
59As a way to minimize on-the-wire log message size, the log level and the line
60number of a given log statement are packed into a single proto field. There are
61helpers in ``pw_log/proto_utils.h`` for properly packing and unpacking this
62field.
63
64.. code-block:: cpp
65
66   #include "pw_bytes/span.h"
67   #include "pw_log/levels.h"
68   #include "pw_log/proto_utils.h"
69   #include "pw_protobuf/decoder.h"
70
71  bool FilterLog(pw::ConstByteSpan serialized_log) {
72    pw::protobuf::Decoder log_decoder(serialized_log);
73    while (log_decoder.Next().ok()) {
74      if (log_decoder.FieldNumber() == 2) {
75        uint32_t line_and_level;
76        entry_decoder.ReadUint32(&line_and_level);
77        PW_DCHECK(entry_decoder.ok());
78
79        uint8_t level = std::get<1>(pw::log::UnpackLineLevel(line_and_level));
80        if (level < PW_LOG_LEVEL_INFO) {
81          return false;
82        }
83      }
84    }
85
86    return true;
87  }
88
89Log encoding helpers
90--------------------
91Encoding logs to the ``log.proto`` format can be performed using the helpers
92provided in the ``pw_log/proto_utils.h`` header. Separate helpers are provided
93for encoding tokenized logs and string-based logs.
94
95The following example shows a :c:func:`pw_log_tokenized_HandleLog`
96implementation that encodes the results to a protobuf.
97
98.. code-block:: cpp
99
100   #include "pw_log/proto_utils.h"
101
102   extern "C" void pw_log_tokenized_HandleLog(
103       uint32_t payload, const uint8_t data[], size_t size) {
104     pw::log_tokenized::Metadata metadata(payload);
105     std::byte log_buffer[kLogBufferSize];
106
107     Result<ConstByteSpan> result = EncodeTokenizedLog(
108         metadata,
109         pw::as_bytes(pw::span(data, size)),
110         log_buffer);
111     if (result.ok()) {
112       // This makes use of the encoded log proto and is custom per-product.
113       // It should be implemented by the caller and is not in Pigweed.
114       EmitProtoLogEntry(result.value());
115     }
116   }
117