blob: 191c4773d65b722deaea6c73b7d32eb1e175f5c6 [file] [log] [blame]
Prashanth Swaminathanfce26ba2020-09-25 13:36:07 -07001// Copyright 2020 The Pigweed Authors
2//
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
5// the License at
6//
7// https://www.apache.org/licenses/LICENSE-2.0
8//
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
13// the License.
14
Prashanth Swaminathan5ef2aa22020-11-10 09:57:46 -080015#include "pw_log_multisink/log_queue.h"
Prashanth Swaminathanfce26ba2020-09-25 13:36:07 -070016
Wyatt Heplerf298de42021-03-19 15:06:36 -070017#include "pw_assert/check.h"
Prashanth Swaminathanfce26ba2020-09-25 13:36:07 -070018#include "pw_log/levels.h"
Prashanth Swaminathan652977d2020-10-16 13:18:05 -070019#include "pw_log_proto/log.pwpb.h"
Prashanth Swaminathanfce26ba2020-09-25 13:36:07 -070020#include "pw_protobuf/wire_format.h"
21#include "pw_status/try.h"
22
23namespace pw::log_rpc {
24namespace {
25
26using pw::protobuf::WireType;
Prashanth Swaminathan44202c92021-03-03 13:23:54 -080027constexpr uint32_t kLogKey = pw::protobuf::MakeKey(
Prashanth Swaminathan652977d2020-10-16 13:18:05 -070028 static_cast<uint32_t>(pw::log::LogEntries::Fields::ENTRIES),
Prashanth Swaminathan44202c92021-03-03 13:23:54 -080029 WireType::kDelimited);
Prashanth Swaminathanfce26ba2020-09-25 13:36:07 -070030
31} // namespace
32
33Status LogQueue::PushTokenizedMessage(ConstByteSpan message,
34 uint32_t flags,
35 uint32_t level,
36 uint32_t line,
37 uint32_t thread,
38 int64_t timestamp) {
39 pw::protobuf::NestedEncoder nested_encoder(encode_buffer_);
Prashanth Swaminathan652977d2020-10-16 13:18:05 -070040 pw::log::LogEntry::Encoder encoder(&nested_encoder);
Prashanth Swaminathanfce26ba2020-09-25 13:36:07 -070041 Status status;
42
43 encoder.WriteMessageTokenized(message);
44 encoder.WriteLineLevel(
45 (level & PW_LOG_LEVEL_BITMASK) |
46 ((line << PW_LOG_LEVEL_BITWIDTH) & ~PW_LOG_LEVEL_BITMASK));
47 encoder.WriteFlags(flags);
48 encoder.WriteThreadTokenized(thread);
49
50 // TODO(prashanthsw): Add support for delta encoding of the timestamp.
51 encoder.WriteTimestamp(timestamp);
52
53 if (dropped_entries_ > 0) {
54 encoder.WriteDropped(dropped_entries_);
55 }
56
57 ConstByteSpan log_entry;
58 status = nested_encoder.Encode(&log_entry);
Prashanth Swaminathan652977d2020-10-16 13:18:05 -070059 if (!status.ok() || log_entry.size_bytes() > max_log_entry_size_) {
60 // If an encoding failure occurs or the constructed log entry is larger
61 // than the configured max size, map the error to INTERNAL. If the
62 // underlying allocation of this encode buffer or the nested encoding
63 // sequencing are at fault, they are not the caller's responsibility. If
64 // the log entry is larger than the max allowed size, the log is dropped
65 // intentionally, and it is expected that the caller accepts this
66 // possibility.
Prashanth Swaminathanfce26ba2020-09-25 13:36:07 -070067 status = PW_STATUS_INTERNAL;
68 } else {
69 // Try to push back the encoded log entry.
Prashanth Swaminathan44202c92021-03-03 13:23:54 -080070 status = ring_buffer_.TryPushBack(log_entry, kLogKey);
Prashanth Swaminathanfce26ba2020-09-25 13:36:07 -070071 }
72
73 if (!status.ok()) {
74 // The ring buffer may hit the RESOURCE_EXHAUSTED state, causing us
75 // to drop packets. However, this check captures all failures from
76 // Encode and TryPushBack, as any failure here causes packet drop.
77 dropped_entries_++;
78 latest_dropped_timestamp_ = timestamp;
79 return status;
80 }
81
82 dropped_entries_ = 0;
Wyatt Hepler1b3da3a2021-01-07 13:26:57 -080083 return OkStatus();
Prashanth Swaminathanfce26ba2020-09-25 13:36:07 -070084}
85
Prashanth Swaminathan652977d2020-10-16 13:18:05 -070086Result<LogEntries> LogQueue::Pop(LogEntriesBuffer entry_buffer) {
Prashanth Swaminathanfce26ba2020-09-25 13:36:07 -070087 size_t ring_buffer_entry_size = 0;
Prashanth Swaminathan652977d2020-10-16 13:18:05 -070088 PW_TRY(pop_status_for_test_);
89 // The caller must provide a buffer that is at minimum max_log_entry_size, to
90 // ensure that the front entry of the ring buffer can be popped.
91 PW_DCHECK_UINT_GE(entry_buffer.size_bytes(), max_log_entry_size_);
Prashanth Swaminathanfce26ba2020-09-25 13:36:07 -070092 PW_TRY(ring_buffer_.PeekFrontWithPreamble(entry_buffer,
93 &ring_buffer_entry_size));
94 PW_DCHECK_OK(ring_buffer_.PopFront());
Prashanth Swaminathan652977d2020-10-16 13:18:05 -070095
96 return LogEntries{
97 .entries = ConstByteSpan(entry_buffer.first(ring_buffer_entry_size)),
98 .entry_count = 1};
Prashanth Swaminathanfce26ba2020-09-25 13:36:07 -070099}
100
Prashanth Swaminathan652977d2020-10-16 13:18:05 -0700101LogEntries LogQueue::PopMultiple(LogEntriesBuffer entries_buffer) {
Prashanth Swaminathanfce26ba2020-09-25 13:36:07 -0700102 size_t offset = 0;
Prashanth Swaminathan652977d2020-10-16 13:18:05 -0700103 size_t entry_count = 0;
104
105 // The caller must provide a buffer that is at minimum max_log_entry_size, to
106 // ensure that the front entry of the ring buffer can be popped.
107 PW_DCHECK_UINT_GE(entries_buffer.size_bytes(), max_log_entry_size_);
108
Prashanth Swaminathanfce26ba2020-09-25 13:36:07 -0700109 while (ring_buffer_.EntryCount() > 0 &&
Prashanth Swaminathan652977d2020-10-16 13:18:05 -0700110 (entries_buffer.size_bytes() - offset) > max_log_entry_size_) {
111 const Result<LogEntries> result = Pop(entries_buffer.subspan(offset));
Prashanth Swaminathanfce26ba2020-09-25 13:36:07 -0700112 if (!result.ok()) {
113 break;
114 }
Prashanth Swaminathan652977d2020-10-16 13:18:05 -0700115 offset += result.value().entries.size_bytes();
116 entry_count += result.value().entry_count;
Prashanth Swaminathanfce26ba2020-09-25 13:36:07 -0700117 }
Prashanth Swaminathan652977d2020-10-16 13:18:05 -0700118
119 return LogEntries{.entries = ConstByteSpan(entries_buffer.first(offset)),
120 .entry_count = entry_count};
Prashanth Swaminathanfce26ba2020-09-25 13:36:07 -0700121}
122
123} // namespace pw::log_rpc