• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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