1 // Copyright 2021 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
15 #include "pw_system_private/log.h"
16
17 #include <array>
18 #include <cstddef>
19
20 #include "pw_log_rpc/rpc_log_drain.h"
21 #include "pw_log_rpc/rpc_log_drain_map.h"
22 #include "pw_multisink/multisink.h"
23 #include "pw_sync/lock_annotations.h"
24 #include "pw_sync/mutex.h"
25 #include "pw_system/config.h"
26 #include "pw_system/rpc_server.h"
27
28 namespace pw::system {
29 namespace {
30
31 using log_rpc::RpcLogDrain;
32
33 // Storage container for MultiSink used for deferred logging.
34 std::array<std::byte, PW_SYSTEM_LOG_BUFFER_SIZE> log_buffer;
35
36 // To save RAM, share the mutex and buffer between drains, since drains are
37 // flushed sequentially.
38 sync::Mutex drains_mutex;
39
40 // Buffer to decode and remove entries from log buffer, to send to a drain.
41 //
42 // TODO(amontanez): pw_log_rpc should provide a helper for this since there's
43 // proto encoding overhead unaccounted for here.
44 static_assert(rpc::MaxSafePayloadSize() >= PW_SYSTEM_MAX_LOG_ENTRY_SIZE);
45 std::array<std::byte, PW_SYSTEM_MAX_LOG_ENTRY_SIZE> log_decode_buffer
46 PW_GUARDED_BY(drains_mutex);
47
48 std::array<RpcLogDrain, 1> drains{{
49 RpcLogDrain(kDefaultRpcChannelId,
50 log_decode_buffer,
51 drains_mutex,
52 RpcLogDrain::LogDrainErrorHandling::kIgnoreWriterErrors),
53 }};
54
55 log_rpc::RpcLogDrainMap drain_map(drains);
56
57 constexpr size_t kMaxPackedLogMessagesSize = rpc::MaxSafePayloadSize();
58 std::array<std::byte, kMaxPackedLogMessagesSize> log_packing_buffer;
59
60 } // namespace
61
62 // Deferred log buffer, for storing log entries while logging_thread_ streams
63 // them independently.
GetMultiSink()64 multisink::MultiSink& GetMultiSink() {
65 static multisink::MultiSink multisink(log_buffer);
66 return multisink;
67 }
68
GetLogThread()69 log_rpc::RpcLogDrainThread& GetLogThread() {
70 static log_rpc::RpcLogDrainThread logging_thread(
71 GetMultiSink(), drain_map, log_packing_buffer);
72 return logging_thread;
73 }
74
GetLogService()75 log_rpc::LogService& GetLogService() {
76 static log_rpc::LogService log_service(drain_map);
77 return log_service;
78 }
79
80 } // namespace pw::system
81