YugabyteDB (2.13.1.0-b60, 21121d69985fbf76aa6958d8f04a9bfa936293b5)

Coverage Report

Created: 2022-03-22 16:43

/Users/deen/code/yugabyte-db/src/yb/util/debug/trace_logging.h
Line
Count
Source
1
// Licensed to the Apache Software Foundation (ASF) under one
2
// or more contributor license agreements.  See the NOTICE file
3
// distributed with this work for additional information
4
// regarding copyright ownership.  The ASF licenses this file
5
// to you under the Apache License, Version 2.0 (the
6
// "License"); you may not use this file except in compliance
7
// with the License.  You may obtain a copy of the License at
8
//
9
//   http://www.apache.org/licenses/LICENSE-2.0
10
//
11
// Unless required by applicable law or agreed to in writing,
12
// software distributed under the License is distributed on an
13
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
// KIND, either express or implied.  See the License for the
15
// specific language governing permissions and limitations
16
// under the License.
17
//
18
// The following only applies to changes made to this file as part of YugaByte development.
19
//
20
// Portions Copyright (c) YugaByte, Inc.
21
//
22
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
23
// in compliance with the License.  You may obtain a copy of the License at
24
//
25
// http://www.apache.org/licenses/LICENSE-2.0
26
//
27
// Unless required by applicable law or agreed to in writing, software distributed under the License
28
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
29
// or implied.  See the License for the specific language governing permissions and limitations
30
// under the License.
31
//
32
// This header defines the following macro:
33
//
34
// VLOG_AND_TRACE(category, vlevel)
35
//
36
//   Write a log message to VLOG(vlevel) as well as the current
37
//   trace event buffer as an "INSTANT" trace event type. If the
38
//   given vlog level is not enabled, this will still result in a
39
//   trace buffer entry.
40
//
41
//   The provided 'category' should be a trace event category, which
42
//   allows the users to filter which trace events to enable.
43
//   For example:
44
//
45
//    VLOG_AND_TRACE("my_subsystem", 1) << "This always shows up in trace buffers "
46
//        << "but only shows up in the log if VLOG(1) level logging is enabled.";
47
//
48
//   Most VLOG(1) level log messages are reasonable to use this macro.
49
//   Note that there is slightly more overhead to this macro as opposed
50
//   to just using VLOG(1).
51
//
52
//   Note that, like VLOG(n), this macro avoids evaluating its arguments unless
53
//   either trace recording or VLOG(n) is enabled. In the case that both are enabled,
54
//   the arguments are only evaluated once.
55
//
56
#ifndef YB_DEBUG_TRACE_LOGGING_H
57
#define YB_DEBUG_TRACE_LOGGING_H
58
59
#include <glog/logging.h>
60
#include <string>
61
62
#include "yb/gutil/macros.h"
63
#include "yb/util/debug/trace_event.h"
64
65
// The inner workings of these macros are a bit arcane:
66
// - We make use of the fact that a block can be embedded within a ternary expression.
67
//   This allows us to determine whether the trace event is enabled before we decide
68
//   to evaluate the arguments.
69
// - We have to use google::LogMessageVoidify so that we can put 'void(0)' on one side
70
//   of the ternary expression and the log stream on the other. This technique is
71
//   cribbed from glog/logging.h.
72
#define VLOG_AND_TRACE_INTERNAL(category, vlevel) \
73
29.9M
  yb::debug::TraceVLog(__FILE__, __LINE__, category, VLOG_IS_ON(vlevel)).stream()
74
#define VLOG_AND_TRACE(category, vlevel)                              \
75
29.9M
  !( {                                                                \
76
29.9M
      bool enabled;                                                   \
77
29.9M
      TRACE_EVENT_CATEGORY_GROUP_ENABLED(category, &enabled);         \
78
29.9M
      enabled || VLOG_IS_ON(vlevel);                                  \
79
29.9M
    } ) ? static_cast<void>(0) :                                      \
80
18.4E
          google::LogMessageVoidify() & 
VLOG_AND_TRACE_INTERNAL29.9M
(category, vlevel)
81
82
namespace yb {
83
namespace debug {
84
85
class TraceVLog {
86
 public:
87
  TraceVLog(const char* file, int line, const char* category, bool do_vlog)
88
    : sink_(category),
89
4
      google_msg_(file, line, google::GLOG_INFO, &sink_, do_vlog) {
90
4
  }
91
92
4
  std::ostream& stream() {
93
4
    return google_msg_.stream();
94
4
  }
95
96
 private:
97
  class TraceLogSink : public google::LogSink {
98
   public:
99
4
    explicit TraceLogSink(const char* category) : category_(category) {}
100
    void send(google::LogSeverity severity, const char* full_filename,
101
              const char* base_filename, int line,
102
              const struct ::tm* tm_time, const char* message,
103
4
              size_t message_len) override {
104
      // Rather than calling TRACE_EVENT_INSTANT here, we have to do it from
105
      // the destructor. This is because glog holds its internal mutex while
106
      // calling send(). So, if we try to use TRACE_EVENT here, and --trace_to_console
107
      // is enabled, then we'd end up calling back into glog when its lock is already
108
      // held. glog isn't re-entrant, so that causes a crash.
109
      //
110
      // By just storing the string here, and then emitting the trace in the dtor,
111
      // we defer the tracing until the google::LogMessage has destructed and the
112
      // glog lock is available again.
113
4
      str_ = ToString(severity, base_filename, line,
114
4
                      tm_time, message, message_len);
115
4
    }
116
4
    virtual ~TraceLogSink() {
117
4
      TRACE_EVENT_INSTANT1(category_, "vlog", TRACE_EVENT_SCOPE_THREAD,
118
4
                           "msg", str_);
119
4
    }
120
121
   private:
122
    const char* const category_;
123
    std::string str_;
124
  };
125
126
  TraceLogSink sink_;
127
  google::LogMessage google_msg_;
128
};
129
130
} // namespace debug
131
} // namespace yb
132
#endif /* YB_DEBUG_TRACE_LOGGING_H */