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