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 #pragma once
15
16 #include <string_view>
17
18 #include "pw_bytes/span.h"
19 #include "pw_log/levels.h"
20 #include "pw_log/proto/log.pwpb.h"
21 #include "pw_log_tokenized/metadata.h"
22 #include "pw_result/result.h"
23 #include "pw_status/try.h"
24
25 namespace pw::log {
26
27 // Packs line number and log level into a single uint32_t as dictated by the
28 // line_level field in the Log proto message.
29 //
30 // Note:
31 // line_number is restricted to 29 bits. Values beyond 536870911 will be lost.
32 // level is restricted to 3 bits. Values beyond 7 will be lost.
PackLineLevel(uint32_t line_number,uint8_t level)33 constexpr inline uint32_t PackLineLevel(uint32_t line_number, uint8_t level) {
34 return (level & PW_LOG_LEVEL_BITMASK) |
35 ((line_number << PW_LOG_LEVEL_BITS) & ~PW_LOG_LEVEL_BITMASK);
36 }
37
38 // Unpacks the line_level field as dictated by the Log proto message into line
39 // number (uint32_t) and level (uint8_t).
UnpackLineLevel(uint32_t line_and_level)40 constexpr inline std::tuple<uint32_t, uint8_t> UnpackLineLevel(
41 uint32_t line_and_level) {
42 return std::make_tuple(
43 (line_and_level & ~PW_LOG_LEVEL_BITMASK) >> PW_LOG_LEVEL_BITS,
44 line_and_level & PW_LOG_LEVEL_BITMASK);
45 }
46
47 // Convenience functions to encode multiple log attributes as a log proto
48 // message.
49 //
50 // Returns:
51 // OK - A byte span containing the encoded log proto.
52 // INVALID_ARGUMENT - `message` argument is zero-length.
53 // RESOURCE_EXHAUSTED - The provided buffer was not large enough to encode the
54 // proto.
55 Result<ConstByteSpan> EncodeLog(int level,
56 unsigned int flags,
57 std::string_view module_name,
58 std::string_view thread_name,
59 std::string_view file_name,
60 int line_number,
61 int64_t ticks_since_epoch,
62 std::string_view message,
63 ByteSpan encode_buffer);
64
65 // Encodes tokenized message and metadata, with a timestamp as a log proto.
66 // Extra fields can be encoded into the returned encoder. The caller must check
67 // the encoder status.
68 LogEntry::MemoryEncoder CreateEncoderAndEncodeTokenizedLog(
69 log_tokenized::Metadata metadata,
70 ConstByteSpan tokenized_data,
71 int64_t ticks_since_epoch,
72 ByteSpan encode_buffer);
73
74 // Convenience functions to convert from tokenized metadata to the log proto
75 // format.
76 //
77 // Returns:
78 // OK - A byte span containing the encoded log proto.
79 // RESOURCE_EXHAUSTED - The provided buffer was not large enough to store the
80 // proto.
EncodeTokenizedLog(log_tokenized::Metadata metadata,ConstByteSpan tokenized_data,int64_t ticks_since_epoch,ByteSpan encode_buffer)81 inline Result<ConstByteSpan> EncodeTokenizedLog(
82 log_tokenized::Metadata metadata,
83 ConstByteSpan tokenized_data,
84 int64_t ticks_since_epoch,
85 ByteSpan encode_buffer) {
86 LogEntry::MemoryEncoder encoder = CreateEncoderAndEncodeTokenizedLog(
87 metadata, tokenized_data, ticks_since_epoch, encode_buffer);
88 PW_TRY(encoder.status());
89 return ConstByteSpan(encoder);
90 }
91
EncodeTokenizedLog(log_tokenized::Metadata metadata,const uint8_t * tokenized_data,size_t tokenized_data_size,int64_t ticks_since_epoch,ByteSpan encode_buffer)92 inline Result<ConstByteSpan> EncodeTokenizedLog(
93 log_tokenized::Metadata metadata,
94 const uint8_t* tokenized_data,
95 size_t tokenized_data_size,
96 int64_t ticks_since_epoch,
97 ByteSpan encode_buffer) {
98 return EncodeTokenizedLog(
99 metadata,
100 std::as_bytes(std::span(tokenized_data, tokenized_data_size)),
101 ticks_since_epoch,
102 encode_buffer);
103 }
104
105 // Encodes tokenized message (passed as pointer and size), tokenized metadata,
106 // timestamp, and thread name as a log proto.
107 //
108 // Returns:
109 // OK - A byte span containing the encoded log proto.
110 // RESOURCE_EXHAUSTED - The provided buffer was not large enough to store the
111 // proto.
EncodeTokenizedLog(log_tokenized::Metadata metadata,const uint8_t * tokenized_data,size_t tokenized_data_size,int64_t ticks_since_epoch,ConstByteSpan thread_name,ByteSpan encode_buffer)112 inline Result<ConstByteSpan> EncodeTokenizedLog(
113 log_tokenized::Metadata metadata,
114 const uint8_t* tokenized_data,
115 size_t tokenized_data_size,
116 int64_t ticks_since_epoch,
117 ConstByteSpan thread_name,
118 ByteSpan encode_buffer) {
119 LogEntry::MemoryEncoder encoder = CreateEncoderAndEncodeTokenizedLog(
120 metadata,
121 std::as_bytes(std::span(tokenized_data, tokenized_data_size)),
122 ticks_since_epoch,
123 encode_buffer);
124 if (!thread_name.empty()) {
125 encoder.WriteThread(thread_name).IgnoreError();
126 }
127 PW_TRY(encoder.status());
128 return ConstByteSpan(encoder);
129 }
130
131 // Encodes tokenized message (passed as a byte span), tokenized metadata,
132 // timestamp, and thread name as a log proto.
133 //
134 // Returns:
135 // OK - A byte span containing the encoded log proto.
136 // RESOURCE_EXHAUSTED - The provided buffer was not large enough to store the
137 // proto.
EncodeTokenizedLog(log_tokenized::Metadata metadata,ConstByteSpan tokenized_data,int64_t ticks_since_epoch,ConstByteSpan thread_name,ByteSpan encode_buffer)138 inline Result<ConstByteSpan> EncodeTokenizedLog(
139 log_tokenized::Metadata metadata,
140 ConstByteSpan tokenized_data,
141 int64_t ticks_since_epoch,
142 ConstByteSpan thread_name,
143 ByteSpan encode_buffer) {
144 LogEntry::MemoryEncoder encoder = CreateEncoderAndEncodeTokenizedLog(
145 metadata, tokenized_data, ticks_since_epoch, encode_buffer);
146 if (!thread_name.empty()) {
147 encoder.WriteThread(thread_name).IgnoreError();
148 }
149 PW_TRY(encoder.status());
150 return ConstByteSpan(encoder);
151 }
152 } // namespace pw::log
153