Skip to content

Commit 6e70150

Browse files
suertreuscopybara-github
authored andcommitted
Encode some additional metadata when writing protobuf-encoded logs.
PiperOrigin-RevId: 649138261 Change-Id: I8687eb7b06cc9e96779d1d3e98b44b4f643c95a8
1 parent 0d9c2fc commit 6e70150

File tree

8 files changed

+692
-615
lines changed

8 files changed

+692
-615
lines changed

absl/log/internal/log_message.cc

Lines changed: 76 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include <algorithm>
2828
#include <array>
2929
#include <atomic>
30+
#include <ios>
3031
#include <memory>
3132
#include <ostream>
3233
#include <string>
@@ -67,7 +68,14 @@ namespace log_internal {
6768
namespace {
6869
// message `logging.proto.Event`
6970
enum EventTag : uint8_t {
71+
kFileName = 2,
72+
kFileLine = 3,
73+
kTimeNsecs = 4,
74+
kSeverity = 5,
75+
kThreadId = 6,
7076
kValue = 7,
77+
kSequenceNumber = 9,
78+
kThreadName = 10,
7179
};
7280

7381
// message `logging.proto.Value`
@@ -100,6 +108,23 @@ bool PrintValue(absl::Span<char>& dst, absl::Span<const char> buf) {
100108
return true;
101109
}
102110

111+
// See `logging.proto.Severity`
112+
int32_t ProtoSeverity(absl::LogSeverity severity, int verbose_level) {
113+
switch (severity) {
114+
case absl::LogSeverity::kInfo:
115+
if (verbose_level == absl::LogEntry::kNoVerbosityLevel) return 800;
116+
return 600 - verbose_level;
117+
case absl::LogSeverity::kWarning:
118+
return 900;
119+
case absl::LogSeverity::kError:
120+
return 950;
121+
case absl::LogSeverity::kFatal:
122+
return 1100;
123+
default:
124+
return 800;
125+
}
126+
}
127+
103128
absl::string_view Basename(absl::string_view filepath) {
104129
#ifdef _WIN32
105130
size_t path = filepath.find_last_of("/\\");
@@ -145,26 +170,37 @@ struct LogMessage::LogMessageData final {
145170

146171
// A `logging.proto.Event` proto message is built into `encoded_buf`.
147172
std::array<char, kLogMessageBufferSize> encoded_buf;
148-
// `encoded_remaining` is the suffix of `encoded_buf` that has not been filled
149-
// yet. If a datum to be encoded does not fit into `encoded_remaining` and
150-
// cannot be truncated to fit, the size of `encoded_remaining` will be zeroed
151-
// to prevent encoding of any further data. Note that in this case its data()
152-
// pointer will not point past the end of `encoded_buf`.
153-
absl::Span<char> encoded_remaining;
173+
// `encoded_remaining()` is the suffix of `encoded_buf` that has not been
174+
// filled yet. If a datum to be encoded does not fit into
175+
// `encoded_remaining()` and cannot be truncated to fit, the size of
176+
// `encoded_remaining()` will be zeroed to prevent encoding of any further
177+
// data. Note that in this case its `data()` pointer will not point past the
178+
// end of `encoded_buf`.
179+
// The first use of `encoded_remaining()` is our chance to record metadata
180+
// after any modifications (e.g. by `AtLocation()`) but before any data have
181+
// been recorded. We want to record metadata before data so that data are
182+
// preferentially truncated if we run out of buffer.
183+
absl::Span<char>& encoded_remaining() {
184+
if (encoded_remaining_actual_do_not_use_directly.data() == nullptr) {
185+
encoded_remaining_actual_do_not_use_directly =
186+
absl::MakeSpan(encoded_buf);
187+
InitializeEncodingAndFormat();
188+
}
189+
return encoded_remaining_actual_do_not_use_directly;
190+
}
191+
absl::Span<char> encoded_remaining_actual_do_not_use_directly;
154192

155193
// A formatted string message is built in `string_buf`.
156194
std::array<char, kLogMessageBufferSize> string_buf;
157195

196+
void InitializeEncodingAndFormat();
158197
void FinalizeEncodingAndFormat();
159198
};
160199

161200
LogMessage::LogMessageData::LogMessageData(const char* file, int line,
162201
absl::LogSeverity severity,
163202
absl::Time timestamp)
164-
: extra_sinks_only(false),
165-
manipulated(nullptr),
166-
// This `absl::MakeSpan` silences spurious -Wuninitialized from GCC:
167-
encoded_remaining(absl::MakeSpan(encoded_buf)) {
203+
: extra_sinks_only(false), manipulated(nullptr) {
168204
// Legacy defaults for LOG's ostream:
169205
manipulated.setf(std::ios_base::showbase | std::ios_base::boolalpha);
170206
entry.full_filename_ = file;
@@ -177,13 +213,25 @@ LogMessage::LogMessageData::LogMessageData(const char* file, int line,
177213
entry.tid_ = absl::base_internal::GetCachedTID();
178214
}
179215

216+
void LogMessage::LogMessageData::InitializeEncodingAndFormat() {
217+
EncodeStringTruncate(EventTag::kFileName, entry.source_filename(),
218+
&encoded_remaining());
219+
EncodeVarint(EventTag::kFileLine, entry.source_line(), &encoded_remaining());
220+
EncodeVarint(EventTag::kTimeNsecs, absl::ToUnixNanos(entry.timestamp()),
221+
&encoded_remaining());
222+
EncodeVarint(EventTag::kSeverity,
223+
ProtoSeverity(entry.log_severity(), entry.verbosity()),
224+
&encoded_remaining());
225+
EncodeVarint(EventTag::kThreadId, entry.tid(), &encoded_remaining());
226+
}
227+
180228
void LogMessage::LogMessageData::FinalizeEncodingAndFormat() {
181-
// Note that `encoded_remaining` may have zero size without pointing past the
182-
// end of `encoded_buf`, so the difference between `data()` pointers is used
183-
// to compute the size of `encoded_data`.
229+
// Note that `encoded_remaining()` may have zero size without pointing past
230+
// the end of `encoded_buf`, so the difference between `data()` pointers is
231+
// used to compute the size of `encoded_data`.
184232
absl::Span<const char> encoded_data(
185233
encoded_buf.data(),
186-
static_cast<size_t>(encoded_remaining.data() - encoded_buf.data()));
234+
static_cast<size_t>(encoded_remaining().data() - encoded_buf.data()));
187235
// `string_remaining` is the suffix of `string_buf` that has not been filled
188236
// yet.
189237
absl::Span<char> string_remaining(string_buf);
@@ -211,7 +259,6 @@ void LogMessage::LogMessageData::FinalizeEncodingAndFormat() {
211259
if (PrintValue(string_remaining, field.bytes_value())) continue;
212260
break;
213261
}
214-
break;
215262
}
216263
auto chars_written =
217264
static_cast<size_t>(string_remaining.data() - string_buf.data());
@@ -413,15 +460,15 @@ void LogMessage::Flush() {
413460
data_->FinalizeEncodingAndFormat();
414461
data_->entry.encoding_ =
415462
absl::string_view(data_->encoded_buf.data(),
416-
static_cast<size_t>(data_->encoded_remaining.data() -
463+
static_cast<size_t>(data_->encoded_remaining().data() -
417464
data_->encoded_buf.data()));
418465
SendToLog();
419466
}
420467

421468
void LogMessage::SetFailQuietly() { data_->fail_quietly = true; }
422469

423470
LogMessage::OstreamView::OstreamView(LogMessageData& message_data)
424-
: data_(message_data), encoded_remaining_copy_(data_.encoded_remaining) {
471+
: data_(message_data), encoded_remaining_copy_(data_.encoded_remaining()) {
425472
// This constructor sets the `streambuf` up so that streaming into an attached
426473
// ostream encodes string data in-place. To do that, we write appropriate
427474
// headers into the buffer using a copy of the buffer view so that we can
@@ -444,8 +491,8 @@ LogMessage::OstreamView::~OstreamView() {
444491
if (!string_start_.data()) {
445492
// The second field header didn't fit. Whether the first one did or not, we
446493
// shouldn't commit `encoded_remaining_copy_`, and we also need to zero the
447-
// size of `data_->encoded_remaining` so that no more data are encoded.
448-
data_.encoded_remaining.remove_suffix(data_.encoded_remaining.size());
494+
// size of `data_->encoded_remaining()` so that no more data are encoded.
495+
data_.encoded_remaining().remove_suffix(data_.encoded_remaining().size());
449496
return;
450497
}
451498
const absl::Span<const char> contents(pbase(),
@@ -454,7 +501,7 @@ LogMessage::OstreamView::~OstreamView() {
454501
encoded_remaining_copy_.remove_prefix(contents.size());
455502
EncodeMessageLength(string_start_, &encoded_remaining_copy_);
456503
EncodeMessageLength(message_start_, &encoded_remaining_copy_);
457-
data_.encoded_remaining = encoded_remaining_copy_;
504+
data_.encoded_remaining() = encoded_remaining_copy_;
458505
}
459506

460507
std::ostream& LogMessage::OstreamView::stream() { return data_.manipulated; }
@@ -521,13 +568,13 @@ void LogMessage::LogBacktraceIfNeeded() {
521568
view.stream() << ") ";
522569
}
523570

524-
// Encodes into `data_->encoded_remaining` a partial `logging.proto.Event`
571+
// Encodes into `data_->encoded_remaining()` a partial `logging.proto.Event`
525572
// containing the specified string data using a `Value` field appropriate to
526573
// `str_type`. Truncates `str` if necessary, but emits nothing and marks the
527574
// buffer full if even the field headers do not fit.
528575
template <LogMessage::StringType str_type>
529576
void LogMessage::CopyToEncodedBuffer(absl::string_view str) {
530-
auto encoded_remaining_copy = data_->encoded_remaining;
577+
auto encoded_remaining_copy = data_->encoded_remaining();
531578
auto start = EncodeMessageStart(
532579
EventTag::kValue, BufferSizeFor(WireType::kLengthDelimited) + str.size(),
533580
&encoded_remaining_copy);
@@ -540,11 +587,11 @@ void LogMessage::CopyToEncodedBuffer(absl::string_view str) {
540587
str, &encoded_remaining_copy)) {
541588
// The string may have been truncated, but the field header fit.
542589
EncodeMessageLength(start, &encoded_remaining_copy);
543-
data_->encoded_remaining = encoded_remaining_copy;
590+
data_->encoded_remaining() = encoded_remaining_copy;
544591
} else {
545-
// The field header(s) did not fit; zero `encoded_remaining` so we don't
592+
// The field header(s) did not fit; zero `encoded_remaining()` so we don't
546593
// write anything else later.
547-
data_->encoded_remaining.remove_suffix(data_->encoded_remaining.size());
594+
data_->encoded_remaining().remove_suffix(data_->encoded_remaining().size());
548595
}
549596
}
550597
template void LogMessage::CopyToEncodedBuffer<LogMessage::StringType::kLiteral>(
@@ -553,7 +600,7 @@ template void LogMessage::CopyToEncodedBuffer<
553600
LogMessage::StringType::kNotLiteral>(absl::string_view str);
554601
template <LogMessage::StringType str_type>
555602
void LogMessage::CopyToEncodedBuffer(char ch, size_t num) {
556-
auto encoded_remaining_copy = data_->encoded_remaining;
603+
auto encoded_remaining_copy = data_->encoded_remaining();
557604
auto value_start = EncodeMessageStart(
558605
EventTag::kValue, BufferSizeFor(WireType::kLengthDelimited) + num,
559606
&encoded_remaining_copy);
@@ -566,11 +613,11 @@ void LogMessage::CopyToEncodedBuffer(char ch, size_t num) {
566613
log_internal::AppendTruncated(ch, num, encoded_remaining_copy);
567614
EncodeMessageLength(str_start, &encoded_remaining_copy);
568615
EncodeMessageLength(value_start, &encoded_remaining_copy);
569-
data_->encoded_remaining = encoded_remaining_copy;
616+
data_->encoded_remaining() = encoded_remaining_copy;
570617
} else {
571-
// The field header(s) did not fit; zero `encoded_remaining` so we don't
618+
// The field header(s) did not fit; zero `encoded_remaining()` so we don't
572619
// write anything else later.
573-
data_->encoded_remaining.remove_suffix(data_->encoded_remaining.size());
620+
data_->encoded_remaining().remove_suffix(data_->encoded_remaining().size());
574621
}
575622
}
576623
template void LogMessage::CopyToEncodedBuffer<LogMessage::StringType::kLiteral>(

absl/log/internal/test_matchers.cc

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include "absl/base/attributes.h"
2727
#include "absl/base/config.h"
2828
#include "absl/log/internal/test_helpers.h"
29+
#include "absl/log/log_entry.h"
2930
#include "absl/strings/string_view.h"
3031
#include "absl/time/clock.h"
3132
#include "absl/time/time.h"
@@ -131,11 +132,9 @@ Matcher<const absl::LogEntry&> Timestamp(
131132
return Property("timestamp", &absl::LogEntry::timestamp, timestamp);
132133
}
133134

134-
Matcher<const absl::LogEntry&> TimestampInMatchWindow() {
135-
return Property("timestamp", &absl::LogEntry::timestamp,
136-
AllOf(Ge(absl::Now()), Truly([](absl::Time arg) {
137-
return arg <= absl::Now();
138-
})));
135+
Matcher<absl::Time> InMatchWindow() {
136+
return AllOf(Ge(absl::Now()),
137+
Truly([](absl::Time arg) { return arg <= absl::Now(); }));
139138
}
140139

141140
Matcher<const absl::LogEntry&> ThreadID(

absl/log/internal/test_matchers.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ ::testing::Matcher<const absl::LogEntry&> Timestamp(
6262
const ::testing::Matcher<absl::Time>& timestamp);
6363
// Matches if the `LogEntry`'s timestamp falls after the instantiation of this
6464
// matcher and before its execution, as is normal when used with EXPECT_CALL.
65-
::testing::Matcher<const absl::LogEntry&> TimestampInMatchWindow();
65+
::testing::Matcher<absl::Time> InMatchWindow();
6666
::testing::Matcher<const absl::LogEntry&> ThreadID(
6767
const ::testing::Matcher<absl::LogEntry::tid_t>&);
6868
::testing::Matcher<const absl::LogEntry&> TextMessageWithPrefixAndNewline(

0 commit comments

Comments
 (0)