1*61c4878aSAndroid Build Coastguard Worker:tocdepth: 4 2*61c4878aSAndroid Build Coastguard Worker 3*61c4878aSAndroid Build Coastguard Worker.. _module-pw_log_rpc: 4*61c4878aSAndroid Build Coastguard Worker 5*61c4878aSAndroid Build Coastguard Worker========== 6*61c4878aSAndroid Build Coastguard Workerpw_log_rpc 7*61c4878aSAndroid Build Coastguard Worker========== 8*61c4878aSAndroid Build Coastguard WorkerAn RPC-based logging solution for Pigweed with log filtering and log drops 9*61c4878aSAndroid Build Coastguard Workerreporting -- coming soon! 10*61c4878aSAndroid Build Coastguard Worker 11*61c4878aSAndroid Build Coastguard Worker.. warning:: 12*61c4878aSAndroid Build Coastguard Worker This module is under construction and might change in the future. 13*61c4878aSAndroid Build Coastguard Worker 14*61c4878aSAndroid Build Coastguard Worker----------- 15*61c4878aSAndroid Build Coastguard WorkerRPC Logging 16*61c4878aSAndroid Build Coastguard Worker----------- 17*61c4878aSAndroid Build Coastguard Worker 18*61c4878aSAndroid Build Coastguard WorkerHow to Use 19*61c4878aSAndroid Build Coastguard Worker========== 20*61c4878aSAndroid Build Coastguard Worker1. Set up RPC 21*61c4878aSAndroid Build Coastguard Worker------------- 22*61c4878aSAndroid Build Coastguard WorkerSet up RPC for your target device. Basic deployments run RPC over a UART, with 23*61c4878aSAndroid Build Coastguard WorkerHDLC on top for framing. See :ref:`module-pw_rpc` for details on how to enable 24*61c4878aSAndroid Build Coastguard Worker``pw_rpc``. 25*61c4878aSAndroid Build Coastguard Worker 26*61c4878aSAndroid Build Coastguard Worker2. Set up tokenized logging (optional) 27*61c4878aSAndroid Build Coastguard Worker-------------------------------------- 28*61c4878aSAndroid Build Coastguard WorkerSet up the :ref:`module-pw_log_tokenized` log backend. 29*61c4878aSAndroid Build Coastguard Worker 30*61c4878aSAndroid Build Coastguard Worker3. Connect the tokenized logging handler to the MultiSink 31*61c4878aSAndroid Build Coastguard Worker--------------------------------------------------------- 32*61c4878aSAndroid Build Coastguard WorkerCreate a :ref:`MultiSink <module-pw_multisink>` instance to buffer log entries. 33*61c4878aSAndroid Build Coastguard WorkerThen, make the log backend handler, :c:func:`pw_log_tokenized_HandleLog`, encode 34*61c4878aSAndroid Build Coastguard Workerlog entries in the ``log::LogEntry`` format, and add them to the ``MultiSink``. 35*61c4878aSAndroid Build Coastguard Worker 36*61c4878aSAndroid Build Coastguard Worker4. Create log drains and filters 37*61c4878aSAndroid Build Coastguard Worker-------------------------------- 38*61c4878aSAndroid Build Coastguard WorkerCreate an ``RpcLogDrainMap`` with one ``RpcLogDrain`` for each RPC channel used 39*61c4878aSAndroid Build Coastguard Workerto stream logs. Optionally, create a ``FilterMap`` with ``Filter`` objects with 40*61c4878aSAndroid Build Coastguard Workerdifferent IDs. Provide these map to the ``LogService`` and register the latter 41*61c4878aSAndroid Build Coastguard Workerwith the application's RPC service. The ``RpcLogDrainMap`` provides a convenient 42*61c4878aSAndroid Build Coastguard Workerway to access and maintain each ``RpcLogDrain``. Attach each ``RpcLogDrain`` to 43*61c4878aSAndroid Build Coastguard Workerthe ``MultiSink``. Optionally, set the ``RpcLogDrain`` callback to decide if a 44*61c4878aSAndroid Build Coastguard Workerlog should be kept or dropped. This callback can be ``Filter::ShouldDropLog``. 45*61c4878aSAndroid Build Coastguard Worker 46*61c4878aSAndroid Build Coastguard Worker5. Flush the log drains in the background 47*61c4878aSAndroid Build Coastguard Worker----------------------------------------- 48*61c4878aSAndroid Build Coastguard WorkerDepending on the product's requirements, create a thread to flush all 49*61c4878aSAndroid Build Coastguard Worker``RpcLogDrain``\s or one thread per drain. The thread(s) must continuously call 50*61c4878aSAndroid Build Coastguard Worker``RpcLogDrain::Flush()`` to pull entries from the ``MultiSink`` and send them to 51*61c4878aSAndroid Build Coastguard Workerthe log listeners. Alternatively, use ``RpcLogDrain::Trickle`` to control the 52*61c4878aSAndroid Build Coastguard Workerrate of log entries streamed. Optionally, set up a callback to notify the 53*61c4878aSAndroid Build Coastguard Workerthread(s) when a drain is open. 54*61c4878aSAndroid Build Coastguard Worker 55*61c4878aSAndroid Build Coastguard WorkerLogging over RPC diagrams 56*61c4878aSAndroid Build Coastguard Worker========================= 57*61c4878aSAndroid Build Coastguard Worker 58*61c4878aSAndroid Build Coastguard WorkerSample RPC logs request 59*61c4878aSAndroid Build Coastguard Worker----------------------- 60*61c4878aSAndroid Build Coastguard WorkerThe log listener, e.g. a computer, requests logs via RPC. The log service 61*61c4878aSAndroid Build Coastguard Workerreceives the request and sets up the corresponding ``RpcLogDrain`` to start the 62*61c4878aSAndroid Build Coastguard Workerlog stream. 63*61c4878aSAndroid Build Coastguard Worker 64*61c4878aSAndroid Build Coastguard Worker.. mermaid:: 65*61c4878aSAndroid Build Coastguard Worker 66*61c4878aSAndroid Build Coastguard Worker graph TD 67*61c4878aSAndroid Build Coastguard Worker computer[Computer]-->pw_rpc; 68*61c4878aSAndroid Build Coastguard Worker pw_rpc-->log_service[LogService]; 69*61c4878aSAndroid Build Coastguard Worker log_service-->rpc_log_drain_pc[RpcLogDrain<br>streams to<br>computer];; 70*61c4878aSAndroid Build Coastguard Worker 71*61c4878aSAndroid Build Coastguard WorkerSample logging over RPC 72*61c4878aSAndroid Build Coastguard Worker------------------------ 73*61c4878aSAndroid Build Coastguard WorkerLogs are streamed via RPC to a computer, and to another log listener. There can 74*61c4878aSAndroid Build Coastguard Workeralso be internal log readers, i.e. ``MultiSink::Drain``\s, attached to the 75*61c4878aSAndroid Build Coastguard Worker``MultiSink``, such as a writer to persistent memory, for example. 76*61c4878aSAndroid Build Coastguard Worker 77*61c4878aSAndroid Build Coastguard Worker.. mermaid:: 78*61c4878aSAndroid Build Coastguard Worker 79*61c4878aSAndroid Build Coastguard Worker graph TD 80*61c4878aSAndroid Build Coastguard Worker source1[Source 1]-->log_api[pw_log API]; 81*61c4878aSAndroid Build Coastguard Worker source2[Source 2]-->log_api; 82*61c4878aSAndroid Build Coastguard Worker log_api-->log_backend[Log backend]; 83*61c4878aSAndroid Build Coastguard Worker log_backend-->multisink[MultiSink]; 84*61c4878aSAndroid Build Coastguard Worker multisink-->drain[MultiSink::Drain]; 85*61c4878aSAndroid Build Coastguard Worker multisink-->rpc_log_drain_pc[RpcLogDrain<br>streams to<br>computer]; 86*61c4878aSAndroid Build Coastguard Worker multisink-->rpc_log_drain_other[RpcLogDrain<br>streams to<br>other log listener]; 87*61c4878aSAndroid Build Coastguard Worker drain-->other_consumer[Other log consumer<br>e.g. persistent memory]; 88*61c4878aSAndroid Build Coastguard Worker rpc_log_drain_pc-->pw_rpc; 89*61c4878aSAndroid Build Coastguard Worker rpc_log_drain_other-->pw_rpc; 90*61c4878aSAndroid Build Coastguard Worker pw_rpc-->computer[Computer]; 91*61c4878aSAndroid Build Coastguard Worker pw_rpc-->other_listener[Other log<br>listener]; 92*61c4878aSAndroid Build Coastguard Worker 93*61c4878aSAndroid Build Coastguard WorkerRelation to pw_log and pw_log_tokenized 94*61c4878aSAndroid Build Coastguard Worker======================================= 95*61c4878aSAndroid Build Coastguard Worker``pw_log_rpc`` is often used in combination with ``pw_log`` and 96*61c4878aSAndroid Build Coastguard Worker``pw_log_tokenized``. The diagram below shows the order of execution after 97*61c4878aSAndroid Build Coastguard Workerinvoking a ``pw_log`` macro. 98*61c4878aSAndroid Build Coastguard Worker 99*61c4878aSAndroid Build Coastguard Worker.. mermaid:: 100*61c4878aSAndroid Build Coastguard Worker 101*61c4878aSAndroid Build Coastguard Worker flowchart TD 102*61c4878aSAndroid Build Coastguard Worker project["`**your project code**`"] 103*61c4878aSAndroid Build Coastguard Worker --> pw_log["`**pw_log** 104*61c4878aSAndroid Build Coastguard Worker *facade*`"] 105*61c4878aSAndroid Build Coastguard Worker --> token_backend["`**pw_log_tokenized** 106*61c4878aSAndroid Build Coastguard Worker *backend for pw_log*`"] 107*61c4878aSAndroid Build Coastguard Worker --> token_facade["`**pw_log_tokenized:handler** 108*61c4878aSAndroid Build Coastguard Worker *facade*`"] 109*61c4878aSAndroid Build Coastguard Worker --> custom_backend["`**your custom code** 110*61c4878aSAndroid Build Coastguard Worker *backend for pw_log_tokenized:handler*`"] 111*61c4878aSAndroid Build Coastguard Worker --> pw_log_rpc["`**pw_log_rpc**`"]; 112*61c4878aSAndroid Build Coastguard Worker 113*61c4878aSAndroid Build Coastguard Worker* See :ref:`docs-module-structure-facades` for an explanation of facades and 114*61c4878aSAndroid Build Coastguard Worker backends. 115*61c4878aSAndroid Build Coastguard Worker* See ``pw_log_tokenized_HandleLog()`` and ``pw_log_tokenized_HandleMessageVaList()`` 116*61c4878aSAndroid Build Coastguard Worker in ``//pw_system/log_backend.cc`` for an example of how :ref:`module-pw_system` 117*61c4878aSAndroid Build Coastguard Worker implements ``your custom code (pw_log_tokenized backend)``. 118*61c4878aSAndroid Build Coastguard Worker 119*61c4878aSAndroid Build Coastguard WorkerComponents Overview 120*61c4878aSAndroid Build Coastguard Worker=================== 121*61c4878aSAndroid Build Coastguard WorkerLogEntry and LogEntries 122*61c4878aSAndroid Build Coastguard Worker----------------------- 123*61c4878aSAndroid Build Coastguard WorkerRPC logging uses ``LogEntry`` to encapsulate each entry's data, such as level, 124*61c4878aSAndroid Build Coastguard Workertimestamp, and message. ``LogEntries`` can hold multiple instances of 125*61c4878aSAndroid Build Coastguard Worker``LogEntry`` to send more data using fewer transmissions. The ``LogEntries`` has 126*61c4878aSAndroid Build Coastguard Workeran optional field for the first message's sequence ID that corresponds to the 127*61c4878aSAndroid Build Coastguard Workercount of each ``LogEntry`` that passes the log filter and is sent. A client can 128*61c4878aSAndroid Build Coastguard Workeruse this sequence ID and the number of messages in a ``LogEntries`` to figure 129*61c4878aSAndroid Build Coastguard Workerout if logs were dropped during transmission. 130*61c4878aSAndroid Build Coastguard Worker 131*61c4878aSAndroid Build Coastguard WorkerRPC log service 132*61c4878aSAndroid Build Coastguard Worker--------------- 133*61c4878aSAndroid Build Coastguard WorkerThe ``LogService`` class is an RPC service that provides a way to request a log 134*61c4878aSAndroid Build Coastguard Workerstream sent via RPC and configure log filters. Thus, it helps avoid 135*61c4878aSAndroid Build Coastguard Workerusing a different protocol for logs and RPCs over the same interface(s). 136*61c4878aSAndroid Build Coastguard WorkerIt requires a ``RpcLogDrainMap`` to assign stream writers and delegate the 137*61c4878aSAndroid Build Coastguard Workerlog stream flushing to the user's preferred method, as well as a ``FilterMap`` 138*61c4878aSAndroid Build Coastguard Workerto retrieve and modify filters. The client may also stop streaming the logs by 139*61c4878aSAndroid Build Coastguard Workercalling ``Cancel()`` or ``RequestCompletion()`` using the ``RawClientReader`` 140*61c4878aSAndroid Build Coastguard Workerinterface. Note that ``Cancel()`` may lead to dropped logs. To prevent dropped 141*61c4878aSAndroid Build Coastguard Workerlogs use ``RequestCompletion()`` and enable :c:macro:`PW_RPC_COMPLETION_REQUEST_CALLBACK` 142*61c4878aSAndroid Build Coastguard Workere.g. ``-DPW_RPC_COMPLETION_REQUEST_CALLBACK=1``. 143*61c4878aSAndroid Build Coastguard WorkerIf ``PW_RPC_COMPLETION_REQUEST_CALLBACK`` is not enabled, RequestCompletion() 144*61c4878aSAndroid Build Coastguard Workercall will not stop the logging stream. 145*61c4878aSAndroid Build Coastguard Worker 146*61c4878aSAndroid Build Coastguard WorkerRpcLogDrain 147*61c4878aSAndroid Build Coastguard Worker----------- 148*61c4878aSAndroid Build Coastguard WorkerAn ``RpcLogDrain`` reads from the ``MultiSink`` instance that buffers logs, then 149*61c4878aSAndroid Build Coastguard Workerpacks, and sends the retrieved log entries to the log listener. One 150*61c4878aSAndroid Build Coastguard Worker``RpcLogDrain`` is needed for each log listener. An ``RpcLogDrain`` needs a 151*61c4878aSAndroid Build Coastguard Workerthread to continuously call ``Flush()`` to maintain the log stream. A thread can 152*61c4878aSAndroid Build Coastguard Workermaintain multiple log streams, but it must not be the same thread used by the 153*61c4878aSAndroid Build Coastguard WorkerRPC server, to avoid blocking it. 154*61c4878aSAndroid Build Coastguard Worker 155*61c4878aSAndroid Build Coastguard WorkerEach ``RpcLogDrain`` is identified by a known RPC channel ID and requires a 156*61c4878aSAndroid Build Coastguard Worker``rpc::RawServerWriter`` to write the packed multiple log entries. This writer 157*61c4878aSAndroid Build Coastguard Workeris assigned by the ``LogService::Listen`` RPC. 158*61c4878aSAndroid Build Coastguard Worker 159*61c4878aSAndroid Build Coastguard Worker``RpcLogDrain``\s can also be provided an open RPC writer, to constantly stream 160*61c4878aSAndroid Build Coastguard Workerlogs without the need to request them. This is useful in cases where the 161*61c4878aSAndroid Build Coastguard Workerconnection to the client is dropped silently because the log stream can continue 162*61c4878aSAndroid Build Coastguard Workerwhen reconnected without the client requesting logs again if the error handling 163*61c4878aSAndroid Build Coastguard Workeris set to ``kIgnoreWriterErrors`` otherwise the writer will be closed. 164*61c4878aSAndroid Build Coastguard Worker 165*61c4878aSAndroid Build Coastguard WorkerAn ``RpcLogDrain`` must be attached to a ``MultiSink`` containing multiple 166*61c4878aSAndroid Build Coastguard Worker``log::LogEntry``\s. When ``Flush`` is called, the drain acquires the 167*61c4878aSAndroid Build Coastguard Worker``rpc::RawServerWriter`` 's write buffer, grabs one ``log::LogEntry`` from the 168*61c4878aSAndroid Build Coastguard Workermultisink, encodes it into a ``log::LogEntries`` stream, and repeats the process 169*61c4878aSAndroid Build Coastguard Workeruntil the write buffer is full. Then the drain calls 170*61c4878aSAndroid Build Coastguard Worker``rpc::RawServerWriter::Write`` to flush the write buffer and repeats the 171*61c4878aSAndroid Build Coastguard Workerprocess until all the entries in the ``MultiSink`` are read or an error is 172*61c4878aSAndroid Build Coastguard Workerfound. 173*61c4878aSAndroid Build Coastguard Worker 174*61c4878aSAndroid Build Coastguard WorkerThe user must provide a buffer large enough for the largest entry in the 175*61c4878aSAndroid Build Coastguard Worker``MultiSink`` while also accounting for the interface's Maximum Transmission 176*61c4878aSAndroid Build Coastguard WorkerUnit (MTU). If the ``RpcLogDrain`` finds a drop message count as it reads the 177*61c4878aSAndroid Build Coastguard Worker``MultiSink`` it will insert a message in the stream with the drop message 178*61c4878aSAndroid Build Coastguard Workercount in the log proto dropped optional field. The receiving end can display the 179*61c4878aSAndroid Build Coastguard Workercount with the logs if desired. 180*61c4878aSAndroid Build Coastguard Worker 181*61c4878aSAndroid Build Coastguard WorkerRpcLogDrainMap 182*61c4878aSAndroid Build Coastguard Worker-------------- 183*61c4878aSAndroid Build Coastguard WorkerProvides a convenient way to access all or a single ``RpcLogDrain`` by its RPC 184*61c4878aSAndroid Build Coastguard Workerchannel ID. 185*61c4878aSAndroid Build Coastguard Worker 186*61c4878aSAndroid Build Coastguard WorkerRpcLogDrainThread 187*61c4878aSAndroid Build Coastguard Worker----------------- 188*61c4878aSAndroid Build Coastguard WorkerThe module includes a sample thread that flushes each drain sequentially. 189*61c4878aSAndroid Build Coastguard Worker``RpcLogDrainThread`` takes an encoding buffer span at construction. 190*61c4878aSAndroid Build Coastguard Worker``RpcLogDrainThreadWithBuffer`` takes a template parameter for the buffer size, 191*61c4878aSAndroid Build Coastguard Workerwhich must be large enough to fit at least one log entry. 192*61c4878aSAndroid Build Coastguard Worker 193*61c4878aSAndroid Build Coastguard WorkerFuture work might replace this with enqueueing the flush work on a work queue. 194*61c4878aSAndroid Build Coastguard WorkerThe user can also choose to have different threads flushing individual 195*61c4878aSAndroid Build Coastguard Worker``RpcLogDrain``\s with different priorities. 196*61c4878aSAndroid Build Coastguard Worker 197*61c4878aSAndroid Build Coastguard WorkerWhen creating a ``RpcLogDrainThread``, the thread can be configured to 198*61c4878aSAndroid Build Coastguard Workerrate limit logs by introducing a limit to how many logs can be flushed from 199*61c4878aSAndroid Build Coastguard Workereach sink before a configurable sleep period begins to give the sinks time to 200*61c4878aSAndroid Build Coastguard Workerhandle the flushed logs. For example, if the rate limiting is configured to 2 201*61c4878aSAndroid Build Coastguard Workerlog bundles per flush with minimum delay of 100ms between flushes, the logging 202*61c4878aSAndroid Build Coastguard Workerthread will send at most 20 log bundles per second over each sink. Log bundle 203*61c4878aSAndroid Build Coastguard Workersize is dictated by the size of the encode buffer provided to the 204*61c4878aSAndroid Build Coastguard WorkerRpcLogDrainThread. 205*61c4878aSAndroid Build Coastguard Worker 206*61c4878aSAndroid Build Coastguard WorkerRate limiting is helpful in cases where transient bursts of high volumes of logs 207*61c4878aSAndroid Build Coastguard Workercause transport buffers to saturate. By rate limiting the RPC log drain, the 208*61c4878aSAndroid Build Coastguard Workertransport buffers are given time to send data. As long as the average logging 209*61c4878aSAndroid Build Coastguard Workerrate is significantly less than the rate limit imposed by the 210*61c4878aSAndroid Build Coastguard Worker``RpcLogDrainThread``, the logging pipeline should be more resilient high 211*61c4878aSAndroid Build Coastguard Workervolume log bursts. 212*61c4878aSAndroid Build Coastguard Worker 213*61c4878aSAndroid Build Coastguard WorkerRate limiting log drains is particularly helpful for systems that collect logs 214*61c4878aSAndroid Build Coastguard Workerto a multisink in bulk when communications aren't available (e.g. collecting 215*61c4878aSAndroid Build Coastguard Workerearly boot logs until the logging thread starts). If a very full log buffer is 216*61c4878aSAndroid Build Coastguard Workersuddenly flushed to the sinks without rate limiting, it's possible to overwhelm 217*61c4878aSAndroid Build Coastguard Workerthe output buffers if they don't have sufficient headroom. 218*61c4878aSAndroid Build Coastguard Worker 219*61c4878aSAndroid Build Coastguard Worker.. note:: 220*61c4878aSAndroid Build Coastguard Worker Introducing a logging drain rate limit will increase logging latency, but 221*61c4878aSAndroid Build Coastguard Worker usually not by much. It's important to tune the rate limit configuration to 222*61c4878aSAndroid Build Coastguard Worker ensure it doesn't unnecessarily introduce a logging bottleneck or 223*61c4878aSAndroid Build Coastguard Worker significantly increase latency. 224*61c4878aSAndroid Build Coastguard Worker 225*61c4878aSAndroid Build Coastguard WorkerCalling ``OpenUnrequestedLogStream()`` is a convenient way to set up a log 226*61c4878aSAndroid Build Coastguard Workerstream that is started without the need to receive an RCP request for logs. 227*61c4878aSAndroid Build Coastguard Worker 228*61c4878aSAndroid Build Coastguard WorkerThe ``RpcLogDrainThread`` sets up a callback for each drain, to be notified when 229*61c4878aSAndroid Build Coastguard Workera drain is opened and flushing must resume. 230*61c4878aSAndroid Build Coastguard Worker 231*61c4878aSAndroid Build Coastguard Worker--------- 232*61c4878aSAndroid Build Coastguard WorkerLog Drops 233*61c4878aSAndroid Build Coastguard Worker--------- 234*61c4878aSAndroid Build Coastguard WorkerUnfortunately, logs can be dropped and not reach the destination. This module 235*61c4878aSAndroid Build Coastguard Workerexpects to cover all cases and be able to notify the user of log drops when 236*61c4878aSAndroid Build Coastguard Workerpossible. Logs can be dropped when 237*61c4878aSAndroid Build Coastguard Worker 238*61c4878aSAndroid Build Coastguard Worker- They don't pass a filter. This is the expected behavior, so filtered logs will 239*61c4878aSAndroid Build Coastguard Worker not be tracked as dropped logs. 240*61c4878aSAndroid Build Coastguard Worker- The drains are too slow to keep up. In this case, the ring buffer is full of 241*61c4878aSAndroid Build Coastguard Worker undrained entries; when new logs come in, old entries are dropped. The log 242*61c4878aSAndroid Build Coastguard Worker stream will contain a ``LogEntry`` message with the number of dropped logs. 243*61c4878aSAndroid Build Coastguard Worker E.g. 244*61c4878aSAndroid Build Coastguard Worker 245*61c4878aSAndroid Build Coastguard Worker Dropped 15 logs due to slow reader 246*61c4878aSAndroid Build Coastguard Worker 247*61c4878aSAndroid Build Coastguard Worker- There is an error creating or adding a new log entry, and the ring buffer is 248*61c4878aSAndroid Build Coastguard Worker notified that the log had to be dropped. The log stream will contain a 249*61c4878aSAndroid Build Coastguard Worker ``LogEntry`` message with the number of dropped logs. 250*61c4878aSAndroid Build Coastguard Worker E.g. 251*61c4878aSAndroid Build Coastguard Worker 252*61c4878aSAndroid Build Coastguard Worker Dropped 15 logs due to slow reader 253*61c4878aSAndroid Build Coastguard Worker 254*61c4878aSAndroid Build Coastguard Worker- A log entry is too large for the stack buffer. The log stream will contain 255*61c4878aSAndroid Build Coastguard Worker an error message with the drop count. Provide a log buffer that fits the 256*61c4878aSAndroid Build Coastguard Worker largest entry added to the MultiSink to avoid this error. 257*61c4878aSAndroid Build Coastguard Worker E.g. 258*61c4878aSAndroid Build Coastguard Worker 259*61c4878aSAndroid Build Coastguard Worker Dropped 1 log due to stack buffer too small 260*61c4878aSAndroid Build Coastguard Worker 261*61c4878aSAndroid Build Coastguard Worker- A log entry is too large for the outbound buffer. The log stream will contain 262*61c4878aSAndroid Build Coastguard Worker an error message with the drop count. Provide a log buffer that fits the 263*61c4878aSAndroid Build Coastguard Worker largest entry added to the MultiSink to avoid this error. 264*61c4878aSAndroid Build Coastguard Worker E.g. 265*61c4878aSAndroid Build Coastguard Worker 266*61c4878aSAndroid Build Coastguard Worker Dropped 1 log due to outbound buffer too small 267*61c4878aSAndroid Build Coastguard Worker 268*61c4878aSAndroid Build Coastguard Worker- There are detected errors transmitting log entries. The log stream will 269*61c4878aSAndroid Build Coastguard Worker contain a ``LogEntry`` with an error message and the number of dropped logs 270*61c4878aSAndroid Build Coastguard Worker the next time the stream is flushed only if the drain's error handling is set 271*61c4878aSAndroid Build Coastguard Worker to close the stream on error. 272*61c4878aSAndroid Build Coastguard Worker E.g. 273*61c4878aSAndroid Build Coastguard Worker 274*61c4878aSAndroid Build Coastguard Worker Dropped 10 logs due to writer error 275*61c4878aSAndroid Build Coastguard Worker 276*61c4878aSAndroid Build Coastguard Worker- There are undetected errors transmitting or receiving log entries, such as an 277*61c4878aSAndroid Build Coastguard Worker interface interruption. Clients can calculate the number of logs lost in 278*61c4878aSAndroid Build Coastguard Worker transit using the sequence ID and number of entries in each stream packet. 279*61c4878aSAndroid Build Coastguard Worker E.g. 280*61c4878aSAndroid Build Coastguard Worker 281*61c4878aSAndroid Build Coastguard Worker Dropped 50 logs due to transmission error 282*61c4878aSAndroid Build Coastguard Worker 283*61c4878aSAndroid Build Coastguard WorkerThe drop count is combined when possible, and reported only when an entry, that 284*61c4878aSAndroid Build Coastguard Workerpasses any filters, is going to be sent. 285*61c4878aSAndroid Build Coastguard Worker 286*61c4878aSAndroid Build Coastguard Worker------------- 287*61c4878aSAndroid Build Coastguard WorkerLog Filtering 288*61c4878aSAndroid Build Coastguard Worker------------- 289*61c4878aSAndroid Build Coastguard WorkerA ``Filter`` anywhere in the path of a ``LogEntry`` proto, for example, in the 290*61c4878aSAndroid Build Coastguard Worker``PW_LOG*`` macro implementation, or in an ``RpcLogDrain`` if using RPC logging. 291*61c4878aSAndroid Build Coastguard WorkerThe log filtering service provides read and modify access to the ``Filter``\s 292*61c4878aSAndroid Build Coastguard Workerregistered in the ``FilterMap``. 293*61c4878aSAndroid Build Coastguard Worker 294*61c4878aSAndroid Build Coastguard WorkerHow to Use 295*61c4878aSAndroid Build Coastguard Worker========== 296*61c4878aSAndroid Build Coastguard Worker1. Set up RPC 297*61c4878aSAndroid Build Coastguard Worker------------- 298*61c4878aSAndroid Build Coastguard WorkerSet up RPC for your target device. See :ref:`module-pw_rpc` for details. 299*61c4878aSAndroid Build Coastguard Worker 300*61c4878aSAndroid Build Coastguard Worker2. Create ``Filter``\s 301*61c4878aSAndroid Build Coastguard Worker---------------------- 302*61c4878aSAndroid Build Coastguard WorkerProvide each ``Filter`` with its own container for the ``FilterRules`` as big as 303*61c4878aSAndroid Build Coastguard Workerthe number of rules desired. These rules can be pre-poluated. 304*61c4878aSAndroid Build Coastguard Worker 305*61c4878aSAndroid Build Coastguard Worker3. Create a ``FilterMap`` and ``FilterService`` 306*61c4878aSAndroid Build Coastguard Worker----------------------------------------------- 307*61c4878aSAndroid Build Coastguard WorkerSet up the ``FilterMap`` with the filters than can be modified with the 308*61c4878aSAndroid Build Coastguard Worker``FilterService``. Register the service with the RPC server. 309*61c4878aSAndroid Build Coastguard Worker 310*61c4878aSAndroid Build Coastguard Worker4. Use RPCs to retrieve and modify filter rules 311*61c4878aSAndroid Build Coastguard Worker----------------------------------------------- 312*61c4878aSAndroid Build Coastguard Worker 313*61c4878aSAndroid Build Coastguard WorkerComponents Overview 314*61c4878aSAndroid Build Coastguard Worker=================== 315*61c4878aSAndroid Build Coastguard WorkerFilter::Rule 316*61c4878aSAndroid Build Coastguard Worker------------ 317*61c4878aSAndroid Build Coastguard WorkerContains a set of values that are compared against a log when set. All 318*61c4878aSAndroid Build Coastguard Workerconditions must be met for the rule to be met. 319*61c4878aSAndroid Build Coastguard Worker 320*61c4878aSAndroid Build Coastguard Worker- ``action``: drops or keeps the log if the other conditions match. 321*61c4878aSAndroid Build Coastguard Worker The rule is ignored when inactive. 322*61c4878aSAndroid Build Coastguard Worker 323*61c4878aSAndroid Build Coastguard Worker- ``any_flags_set``: the condition is met if this value is 0 or the log has any 324*61c4878aSAndroid Build Coastguard Worker of these flags set. 325*61c4878aSAndroid Build Coastguard Worker 326*61c4878aSAndroid Build Coastguard Worker- ``level_greater_than_or_equal``: the condition is met when the log level is 327*61c4878aSAndroid Build Coastguard Worker greater than or equal to this value. 328*61c4878aSAndroid Build Coastguard Worker 329*61c4878aSAndroid Build Coastguard Worker- ``module_equals``: the condition is met if this byte array is empty, or the 330*61c4878aSAndroid Build Coastguard Worker log module equals the contents of this byte array. 331*61c4878aSAndroid Build Coastguard Worker 332*61c4878aSAndroid Build Coastguard Worker- ``thread_equals``: the condition is met if this byte array is empty or the 333*61c4878aSAndroid Build Coastguard Worker log thread equals the contents of this byte array. 334*61c4878aSAndroid Build Coastguard Worker 335*61c4878aSAndroid Build Coastguard WorkerFilter 336*61c4878aSAndroid Build Coastguard Worker------ 337*61c4878aSAndroid Build Coastguard WorkerEncapsulates a collection of zero or more ``Filter::Rule``\s and has 338*61c4878aSAndroid Build Coastguard Workeran ID used to modify or retrieve its contents. 339*61c4878aSAndroid Build Coastguard Worker 340*61c4878aSAndroid Build Coastguard WorkerFilterMap 341*61c4878aSAndroid Build Coastguard Worker--------- 342*61c4878aSAndroid Build Coastguard WorkerProvides a convenient way to retrieve register filters by ID. 343*61c4878aSAndroid Build Coastguard Worker 344*61c4878aSAndroid Build Coastguard Worker---------------------------- 345*61c4878aSAndroid Build Coastguard WorkerLogging with filters example 346*61c4878aSAndroid Build Coastguard Worker---------------------------- 347*61c4878aSAndroid Build Coastguard WorkerThe following code shows a sample setup to defer the log handling to the 348*61c4878aSAndroid Build Coastguard Worker``RpcLogDrainThread`` to avoid having the log streaming block at the log 349*61c4878aSAndroid Build Coastguard Workercallsite. 350*61c4878aSAndroid Build Coastguard Worker 351*61c4878aSAndroid Build Coastguard Workermain.cc 352*61c4878aSAndroid Build Coastguard Worker======= 353*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp 354*61c4878aSAndroid Build Coastguard Worker 355*61c4878aSAndroid Build Coastguard Worker #include "foo/log.h" 356*61c4878aSAndroid Build Coastguard Worker #include "pw_log/log.h" 357*61c4878aSAndroid Build Coastguard Worker #include "pw_thread/detached_thread.h" 358*61c4878aSAndroid Build Coastguard Worker #include "pw_thread_stl/options.h" 359*61c4878aSAndroid Build Coastguard Worker 360*61c4878aSAndroid Build Coastguard Worker namespace { 361*61c4878aSAndroid Build Coastguard Worker 362*61c4878aSAndroid Build Coastguard Worker void RegisterServices() { 363*61c4878aSAndroid Build Coastguard Worker pw::rpc::system_server::Server().RegisterService(foo::log::log_service); 364*61c4878aSAndroid Build Coastguard Worker pw::rpc::system_server::Server().RegisterService(foo::log::filter_service); 365*61c4878aSAndroid Build Coastguard Worker } 366*61c4878aSAndroid Build Coastguard Worker } // namespace 367*61c4878aSAndroid Build Coastguard Worker 368*61c4878aSAndroid Build Coastguard Worker int main() { 369*61c4878aSAndroid Build Coastguard Worker PW_LOG_INFO("Deferred logging over RPC example"); 370*61c4878aSAndroid Build Coastguard Worker pw::rpc::system_server::Init(); 371*61c4878aSAndroid Build Coastguard Worker RegisterServices(); 372*61c4878aSAndroid Build Coastguard Worker pw::thread::DetachedThread(pw::thread::stl::Options(), foo::log::log_thread); 373*61c4878aSAndroid Build Coastguard Worker pw::rpc::system_server::Start(); 374*61c4878aSAndroid Build Coastguard Worker return 0; 375*61c4878aSAndroid Build Coastguard Worker } 376*61c4878aSAndroid Build Coastguard Worker 377*61c4878aSAndroid Build Coastguard Workerfoo/log.cc 378*61c4878aSAndroid Build Coastguard Worker========== 379*61c4878aSAndroid Build Coastguard WorkerExample of a log backend implementation, where logs enter the ``MultiSink`` and 380*61c4878aSAndroid Build Coastguard Workerlog drains and filters are set up. 381*61c4878aSAndroid Build Coastguard Worker 382*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp 383*61c4878aSAndroid Build Coastguard Worker 384*61c4878aSAndroid Build Coastguard Worker #include "foo/log.h" 385*61c4878aSAndroid Build Coastguard Worker 386*61c4878aSAndroid Build Coastguard Worker #include <array> 387*61c4878aSAndroid Build Coastguard Worker #include <cstdint> 388*61c4878aSAndroid Build Coastguard Worker 389*61c4878aSAndroid Build Coastguard Worker #include "pw_chrono/system_clock.h" 390*61c4878aSAndroid Build Coastguard Worker #include "pw_log/proto_utils.h" 391*61c4878aSAndroid Build Coastguard Worker #include "pw_log_rpc/log_filter.h" 392*61c4878aSAndroid Build Coastguard Worker #include "pw_log_rpc/log_filter_map.h" 393*61c4878aSAndroid Build Coastguard Worker #include "pw_log_rpc/log_filter_service.h" 394*61c4878aSAndroid Build Coastguard Worker #include "pw_log_rpc/log_service.h" 395*61c4878aSAndroid Build Coastguard Worker #include "pw_log_rpc/rpc_log_drain.h" 396*61c4878aSAndroid Build Coastguard Worker #include "pw_log_rpc/rpc_log_drain_map.h" 397*61c4878aSAndroid Build Coastguard Worker #include "pw_log_rpc/rpc_log_drain_thread.h" 398*61c4878aSAndroid Build Coastguard Worker #include "pw_rpc_system_server/rpc_server.h" 399*61c4878aSAndroid Build Coastguard Worker #include "pw_sync/interrupt_spin_lock.h" 400*61c4878aSAndroid Build Coastguard Worker #include "pw_sync/lock_annotations.h" 401*61c4878aSAndroid Build Coastguard Worker #include "pw_sync/mutex.h" 402*61c4878aSAndroid Build Coastguard Worker 403*61c4878aSAndroid Build Coastguard Worker namespace foo::log { 404*61c4878aSAndroid Build Coastguard Worker namespace { 405*61c4878aSAndroid Build Coastguard Worker constexpr size_t kLogBufferSize = 5000; 406*61c4878aSAndroid Build Coastguard Worker // Tokenized logs are typically 12-24 bytes. 407*61c4878aSAndroid Build Coastguard Worker constexpr size_t kMaxMessageSize = 32; 408*61c4878aSAndroid Build Coastguard Worker // kMaxLogEntrySize should be less than the MTU of the RPC channel output used 409*61c4878aSAndroid Build Coastguard Worker // by the provided server writer. 410*61c4878aSAndroid Build Coastguard Worker constexpr size_t kMaxLogEntrySize = 411*61c4878aSAndroid Build Coastguard Worker pw::log_rpc::RpcLogDrain::kMinEntrySizeWithoutPayload + kMaxMessageSize; 412*61c4878aSAndroid Build Coastguard Worker std::array<std::byte, kLogBufferSize> multisink_buffer; 413*61c4878aSAndroid Build Coastguard Worker 414*61c4878aSAndroid Build Coastguard Worker // To save RAM, share the mutex, since drains will be managed sequentially. 415*61c4878aSAndroid Build Coastguard Worker pw::sync::Mutex shared_mutex; 416*61c4878aSAndroid Build Coastguard Worker std::array<std::byte, kMaxEntrySize> client1_buffer 417*61c4878aSAndroid Build Coastguard Worker PW_GUARDED_BY(shared_mutex); 418*61c4878aSAndroid Build Coastguard Worker std::array<std::byte, kMaxEntrySize> client2_buffer 419*61c4878aSAndroid Build Coastguard Worker PW_GUARDED_BY(shared_mutex); 420*61c4878aSAndroid Build Coastguard Worker std::array<pw::log_rpc::RpcLogDrain, 2> drains = { 421*61c4878aSAndroid Build Coastguard Worker pw::log_rpc::RpcLogDrain( 422*61c4878aSAndroid Build Coastguard Worker 1, 423*61c4878aSAndroid Build Coastguard Worker client1_buffer, 424*61c4878aSAndroid Build Coastguard Worker shared_mutex, 425*61c4878aSAndroid Build Coastguard Worker RpcLogDrain::LogDrainErrorHandling::kIgnoreWriterErrors), 426*61c4878aSAndroid Build Coastguard Worker pw::log_rpc::RpcLogDrain( 427*61c4878aSAndroid Build Coastguard Worker 2, 428*61c4878aSAndroid Build Coastguard Worker client2_buffer, 429*61c4878aSAndroid Build Coastguard Worker shared_mutex, 430*61c4878aSAndroid Build Coastguard Worker RpcLogDrain::LogDrainErrorHandling::kIgnoreWriterErrors), 431*61c4878aSAndroid Build Coastguard Worker }; 432*61c4878aSAndroid Build Coastguard Worker 433*61c4878aSAndroid Build Coastguard Worker pw::sync::InterruptSpinLock log_encode_lock; 434*61c4878aSAndroid Build Coastguard Worker std::array<std::byte, kMaxLogEntrySize> log_encode_buffer 435*61c4878aSAndroid Build Coastguard Worker PW_GUARDED_BY(log_encode_lock); 436*61c4878aSAndroid Build Coastguard Worker 437*61c4878aSAndroid Build Coastguard Worker std::array<Filter::Rule, 2> logs_to_host_filter_rules; 438*61c4878aSAndroid Build Coastguard Worker std::array<Filter::Rule, 2> logs_to_server_filter_rules{{ 439*61c4878aSAndroid Build Coastguard Worker { 440*61c4878aSAndroid Build Coastguard Worker .action = Filter::Rule::Action::kKeep, 441*61c4878aSAndroid Build Coastguard Worker .level_greater_than_or_equal = pw::log::FilterRule::Level::INFO_LEVEL, 442*61c4878aSAndroid Build Coastguard Worker }, 443*61c4878aSAndroid Build Coastguard Worker { 444*61c4878aSAndroid Build Coastguard Worker .action = Filter::Rule::Action::kDrop, 445*61c4878aSAndroid Build Coastguard Worker }, 446*61c4878aSAndroid Build Coastguard Worker }}; 447*61c4878aSAndroid Build Coastguard Worker std::array<Filter, 2> filters{ 448*61c4878aSAndroid Build Coastguard Worker Filter(pw::as_bytes(pw::span("HOST", 4)), logs_to_host_filter_rules), 449*61c4878aSAndroid Build Coastguard Worker Filter(pw::as_bytes(pw::span("WEB", 3)), logs_to_server_filter_rules), 450*61c4878aSAndroid Build Coastguard Worker }; 451*61c4878aSAndroid Build Coastguard Worker pw::log_rpc::FilterMap filter_map(filters); 452*61c4878aSAndroid Build Coastguard Worker 453*61c4878aSAndroid Build Coastguard Worker extern "C" void pw_log_tokenized_HandleLog( 454*61c4878aSAndroid Build Coastguard Worker uint32_t metadata, const uint8_t message[], size_t size_bytes) { 455*61c4878aSAndroid Build Coastguard Worker int64_t timestamp = 456*61c4878aSAndroid Build Coastguard Worker pw::chrono::SystemClock::now().time_since_epoch().count(); 457*61c4878aSAndroid Build Coastguard Worker std::lock_guard lock(log_encode_lock); 458*61c4878aSAndroid Build Coastguard Worker pw::Result<pw::ConstByteSpan> encoded_log_result = 459*61c4878aSAndroid Build Coastguard Worker pw::log::EncodeTokenizedLog( 460*61c4878aSAndroid Build Coastguard Worker metadata, message, size_bytes, timestamp, log_encode_buffer); 461*61c4878aSAndroid Build Coastguard Worker 462*61c4878aSAndroid Build Coastguard Worker if (!encoded_log_result.ok()) { 463*61c4878aSAndroid Build Coastguard Worker GetMultiSink().HandleDropped(); 464*61c4878aSAndroid Build Coastguard Worker return; 465*61c4878aSAndroid Build Coastguard Worker } 466*61c4878aSAndroid Build Coastguard Worker GetMultiSink().HandleEntry(encoded_log_result.value()); 467*61c4878aSAndroid Build Coastguard Worker } 468*61c4878aSAndroid Build Coastguard Worker } // namespace 469*61c4878aSAndroid Build Coastguard Worker 470*61c4878aSAndroid Build Coastguard Worker pw::log_rpc::RpcLogDrainMap drain_map(drains); 471*61c4878aSAndroid Build Coastguard Worker pw::log_rpc::RpcLogDrainThread log_thread(GetMultiSink(), drain_map); 472*61c4878aSAndroid Build Coastguard Worker pw::log_rpc::LogService log_service(drain_map); 473*61c4878aSAndroid Build Coastguard Worker pw::log_rpc::FilterService filter_service(filter_map); 474*61c4878aSAndroid Build Coastguard Worker 475*61c4878aSAndroid Build Coastguard Worker pw::multisink::MultiSink& GetMultiSink() { 476*61c4878aSAndroid Build Coastguard Worker static pw::multisink::MultiSink multisink(multisink_buffer); 477*61c4878aSAndroid Build Coastguard Worker return multisink; 478*61c4878aSAndroid Build Coastguard Worker } 479*61c4878aSAndroid Build Coastguard Worker } // namespace foo::log 480*61c4878aSAndroid Build Coastguard Worker 481*61c4878aSAndroid Build Coastguard WorkerLogging in other source files 482*61c4878aSAndroid Build Coastguard Worker----------------------------- 483*61c4878aSAndroid Build Coastguard WorkerTo defer logging, other source files must simply include ``pw_log/log.h`` and 484*61c4878aSAndroid Build Coastguard Workeruse the :ref:`module-pw_log` APIs, as long as the source set that includes 485*61c4878aSAndroid Build Coastguard Worker``foo/log.cc`` is setup as the log backend. 486*61c4878aSAndroid Build Coastguard Worker 487*61c4878aSAndroid Build Coastguard Worker-------------------- 488*61c4878aSAndroid Build Coastguard Workerpw_log_rpc in Python 489*61c4878aSAndroid Build Coastguard Worker-------------------- 490*61c4878aSAndroid Build Coastguard Worker``pw_log_rpc`` provides client utilities for dealing with RPC logging. 491*61c4878aSAndroid Build Coastguard Worker 492*61c4878aSAndroid Build Coastguard WorkerThe ``LogStreamHandler`` offers APIs to start a log stream: ``start_logs``, 493*61c4878aSAndroid Build Coastguard Workerto handle RPC stream errors: ``handle_log_stream_error``, and RPC stream 494*61c4878aSAndroid Build Coastguard Workercompleted events: ``handle_log_stream_completed``. It uses a provided 495*61c4878aSAndroid Build Coastguard Worker``LogStreamDecoder`` to delegate log parsing to. 496*61c4878aSAndroid Build Coastguard Worker 497*61c4878aSAndroid Build Coastguard WorkerPython API 498*61c4878aSAndroid Build Coastguard Worker========== 499*61c4878aSAndroid Build Coastguard Worker 500*61c4878aSAndroid Build Coastguard Workerpw_log_rpc.rpc_log_stream 501*61c4878aSAndroid Build Coastguard Worker------------------------- 502*61c4878aSAndroid Build Coastguard Worker.. automodule:: pw_log_rpc.rpc_log_stream 503*61c4878aSAndroid Build Coastguard Worker :members: LogStreamHandler 504*61c4878aSAndroid Build Coastguard Worker :undoc-members: 505*61c4878aSAndroid Build Coastguard Worker :show-inheritance: 506