1 // Copyright 2020 The Pigweed Authors
3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4 // use this file except in compliance with the License. You may obtain a copy of
7 // https://www.apache.org/licenses/LICENSE-2.0
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 // License for the specific language governing permissions and limitations under
15 #include "pw_log_rpc/log_queue.h"
17 #include "pw_log/levels.h"
18 #include "pw_log_rpc_proto/log.pwpb.h"
19 #include "pw_protobuf/wire_format.h"
20 #include "pw_status/try.h"
22 namespace pw::log_rpc {
25 using pw::protobuf::WireType;
26 constexpr std::byte kLogKey = static_cast<std::byte>(pw::protobuf::MakeKey(
27 static_cast<uint32_t>(pw::log_rpc::Log::Fields::ENTRIES),
28 WireType::kDelimited));
32 Status LogQueue::PushTokenizedMessage(ConstByteSpan message,
38 pw::protobuf::NestedEncoder nested_encoder(encode_buffer_);
39 LogEntry::Encoder encoder(&nested_encoder);
42 encoder.WriteMessageTokenized(message);
43 encoder.WriteLineLevel(
44 (level & PW_LOG_LEVEL_BITMASK) |
45 ((line << PW_LOG_LEVEL_BITWIDTH) & ~PW_LOG_LEVEL_BITMASK));
46 encoder.WriteFlags(flags);
47 encoder.WriteThreadTokenized(thread);
49 // TODO(prashanthsw): Add support for delta encoding of the timestamp.
50 encoder.WriteTimestamp(timestamp);
52 if (dropped_entries_ > 0) {
53 encoder.WriteDropped(dropped_entries_);
56 ConstByteSpan log_entry;
57 status = nested_encoder.Encode(&log_entry);
59 // When encoding failures occur, map the error to INTERNAL, as the
60 // underlying allocation of this encode buffer and the nested encoding
61 // sequencing are not the caller's responsibility.
62 status = PW_STATUS_INTERNAL;
64 // Try to push back the encoded log entry.
65 status = ring_buffer_.TryPushBack(log_entry, std::byte(kLogKey));
69 // The ring buffer may hit the RESOURCE_EXHAUSTED state, causing us
70 // to drop packets. However, this check captures all failures from
71 // Encode and TryPushBack, as any failure here causes packet drop.
73 latest_dropped_timestamp_ = timestamp;
81 Result<ConstByteSpan> LogQueue::Pop(ByteSpan entry_buffer) {
82 size_t ring_buffer_entry_size = 0;
83 PW_TRY(ring_buffer_.PeekFrontWithPreamble(entry_buffer,
84 &ring_buffer_entry_size));
85 PW_DCHECK_OK(ring_buffer_.PopFront());
86 return ConstByteSpan(entry_buffer.first(ring_buffer_entry_size));
89 Result<ConstByteSpan> LogQueue::PopMultiple(ByteSpan entries_buffer) {
91 while (ring_buffer_.EntryCount() > 0 &&
92 (entries_buffer.size_bytes() - offset) >
93 ring_buffer_.FrontEntryTotalSizeBytes()) {
94 const Result<ConstByteSpan> result = Pop(entries_buffer.subspan(offset));
98 offset += result.value().size_bytes();
100 return ConstByteSpan(entries_buffer.first(offset));
103 } // namespace pw::log_rpc