27
27
#include < algorithm>
28
28
#include < array>
29
29
#include < atomic>
30
+ #include < ios>
30
31
#include < memory>
31
32
#include < ostream>
32
33
#include < string>
@@ -67,7 +68,14 @@ namespace log_internal {
67
68
namespace {
68
69
// message `logging.proto.Event`
69
70
enum EventTag : uint8_t {
71
+ kFileName = 2 ,
72
+ kFileLine = 3 ,
73
+ kTimeNsecs = 4 ,
74
+ kSeverity = 5 ,
75
+ kThreadId = 6 ,
70
76
kValue = 7 ,
77
+ kSequenceNumber = 9 ,
78
+ kThreadName = 10 ,
71
79
};
72
80
73
81
// message `logging.proto.Value`
@@ -100,6 +108,23 @@ bool PrintValue(absl::Span<char>& dst, absl::Span<const char> buf) {
100
108
return true ;
101
109
}
102
110
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
+
103
128
absl::string_view Basename (absl::string_view filepath) {
104
129
#ifdef _WIN32
105
130
size_t path = filepath.find_last_of (" /\\ " );
@@ -145,26 +170,37 @@ struct LogMessage::LogMessageData final {
145
170
146
171
// A `logging.proto.Event` proto message is built into `encoded_buf`.
147
172
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;
154
192
155
193
// A formatted string message is built in `string_buf`.
156
194
std::array<char , kLogMessageBufferSize > string_buf;
157
195
196
+ void InitializeEncodingAndFormat ();
158
197
void FinalizeEncodingAndFormat ();
159
198
};
160
199
161
200
LogMessage::LogMessageData::LogMessageData (const char * file, int line,
162
201
absl::LogSeverity severity,
163
202
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 ) {
168
204
// Legacy defaults for LOG's ostream:
169
205
manipulated.setf (std::ios_base::showbase | std::ios_base::boolalpha);
170
206
entry.full_filename_ = file;
@@ -177,13 +213,25 @@ LogMessage::LogMessageData::LogMessageData(const char* file, int line,
177
213
entry.tid_ = absl::base_internal::GetCachedTID ();
178
214
}
179
215
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
+
180
228
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`.
184
232
absl::Span<const char > encoded_data (
185
233
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 ()));
187
235
// `string_remaining` is the suffix of `string_buf` that has not been filled
188
236
// yet.
189
237
absl::Span<char > string_remaining (string_buf);
@@ -211,7 +259,6 @@ void LogMessage::LogMessageData::FinalizeEncodingAndFormat() {
211
259
if (PrintValue (string_remaining, field.bytes_value ())) continue ;
212
260
break ;
213
261
}
214
- break ;
215
262
}
216
263
auto chars_written =
217
264
static_cast <size_t >(string_remaining.data () - string_buf.data ());
@@ -413,15 +460,15 @@ void LogMessage::Flush() {
413
460
data_->FinalizeEncodingAndFormat ();
414
461
data_->entry .encoding_ =
415
462
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 () -
417
464
data_->encoded_buf .data ()));
418
465
SendToLog ();
419
466
}
420
467
421
468
void LogMessage::SetFailQuietly () { data_->fail_quietly = true ; }
422
469
423
470
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() ) {
425
472
// This constructor sets the `streambuf` up so that streaming into an attached
426
473
// ostream encodes string data in-place. To do that, we write appropriate
427
474
// headers into the buffer using a copy of the buffer view so that we can
@@ -444,8 +491,8 @@ LogMessage::OstreamView::~OstreamView() {
444
491
if (!string_start_.data ()) {
445
492
// The second field header didn't fit. Whether the first one did or not, we
446
493
// 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 ());
449
496
return ;
450
497
}
451
498
const absl::Span<const char > contents (pbase (),
@@ -454,7 +501,7 @@ LogMessage::OstreamView::~OstreamView() {
454
501
encoded_remaining_copy_.remove_prefix (contents.size ());
455
502
EncodeMessageLength (string_start_, &encoded_remaining_copy_);
456
503
EncodeMessageLength (message_start_, &encoded_remaining_copy_);
457
- data_.encoded_remaining = encoded_remaining_copy_;
504
+ data_.encoded_remaining () = encoded_remaining_copy_;
458
505
}
459
506
460
507
std::ostream& LogMessage::OstreamView::stream () { return data_.manipulated ; }
@@ -521,13 +568,13 @@ void LogMessage::LogBacktraceIfNeeded() {
521
568
view.stream () << " ) " ;
522
569
}
523
570
524
- // Encodes into `data_->encoded_remaining` a partial `logging.proto.Event`
571
+ // Encodes into `data_->encoded_remaining() ` a partial `logging.proto.Event`
525
572
// containing the specified string data using a `Value` field appropriate to
526
573
// `str_type`. Truncates `str` if necessary, but emits nothing and marks the
527
574
// buffer full if even the field headers do not fit.
528
575
template <LogMessage::StringType str_type>
529
576
void LogMessage::CopyToEncodedBuffer (absl::string_view str) {
530
- auto encoded_remaining_copy = data_->encoded_remaining ;
577
+ auto encoded_remaining_copy = data_->encoded_remaining () ;
531
578
auto start = EncodeMessageStart (
532
579
EventTag::kValue , BufferSizeFor (WireType::kLengthDelimited ) + str.size (),
533
580
&encoded_remaining_copy);
@@ -540,11 +587,11 @@ void LogMessage::CopyToEncodedBuffer(absl::string_view str) {
540
587
str, &encoded_remaining_copy)) {
541
588
// The string may have been truncated, but the field header fit.
542
589
EncodeMessageLength (start, &encoded_remaining_copy);
543
- data_->encoded_remaining = encoded_remaining_copy;
590
+ data_->encoded_remaining () = encoded_remaining_copy;
544
591
} 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
546
593
// write anything else later.
547
- data_->encoded_remaining .remove_suffix (data_->encoded_remaining .size ());
594
+ data_->encoded_remaining () .remove_suffix (data_->encoded_remaining () .size ());
548
595
}
549
596
}
550
597
template void LogMessage::CopyToEncodedBuffer<LogMessage::StringType::kLiteral >(
@@ -553,7 +600,7 @@ template void LogMessage::CopyToEncodedBuffer<
553
600
LogMessage::StringType::kNotLiteral >(absl::string_view str);
554
601
template <LogMessage::StringType str_type>
555
602
void LogMessage::CopyToEncodedBuffer (char ch, size_t num) {
556
- auto encoded_remaining_copy = data_->encoded_remaining ;
603
+ auto encoded_remaining_copy = data_->encoded_remaining () ;
557
604
auto value_start = EncodeMessageStart (
558
605
EventTag::kValue , BufferSizeFor (WireType::kLengthDelimited ) + num,
559
606
&encoded_remaining_copy);
@@ -566,11 +613,11 @@ void LogMessage::CopyToEncodedBuffer(char ch, size_t num) {
566
613
log_internal::AppendTruncated (ch, num, encoded_remaining_copy);
567
614
EncodeMessageLength (str_start, &encoded_remaining_copy);
568
615
EncodeMessageLength (value_start, &encoded_remaining_copy);
569
- data_->encoded_remaining = encoded_remaining_copy;
616
+ data_->encoded_remaining () = encoded_remaining_copy;
570
617
} 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
572
619
// write anything else later.
573
- data_->encoded_remaining .remove_suffix (data_->encoded_remaining .size ());
620
+ data_->encoded_remaining () .remove_suffix (data_->encoded_remaining () .size ());
574
621
}
575
622
}
576
623
template void LogMessage::CopyToEncodedBuffer<LogMessage::StringType::kLiteral >(
0 commit comments