xref: /aosp_15_r20/external/abseil-cpp/absl/log/internal/vlog_config.h (revision 9356374a3709195abf420251b3e825997ff56c0f)
1*9356374aSAndroid Build Coastguard Worker // Copyright 2022 The Abseil Authors
2*9356374aSAndroid Build Coastguard Worker //
3*9356374aSAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
4*9356374aSAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
5*9356374aSAndroid Build Coastguard Worker // You may obtain a copy of the License at
6*9356374aSAndroid Build Coastguard Worker //
7*9356374aSAndroid Build Coastguard Worker //     https://www.apache.org/licenses/LICENSE-2.0
8*9356374aSAndroid Build Coastguard Worker //
9*9356374aSAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*9356374aSAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
11*9356374aSAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*9356374aSAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
13*9356374aSAndroid Build Coastguard Worker // limitations under the License.
14*9356374aSAndroid Build Coastguard Worker //
15*9356374aSAndroid Build Coastguard Worker // -----------------------------------------------------------------------------
16*9356374aSAndroid Build Coastguard Worker // vlog_config.h
17*9356374aSAndroid Build Coastguard Worker // -----------------------------------------------------------------------------
18*9356374aSAndroid Build Coastguard Worker //
19*9356374aSAndroid Build Coastguard Worker // This header file defines `VLogSite`, a public primitive that represents
20*9356374aSAndroid Build Coastguard Worker // a callsite for the `VLOG` family of macros and related libraries.
21*9356374aSAndroid Build Coastguard Worker // It also declares and defines multiple internal utilities used to implement
22*9356374aSAndroid Build Coastguard Worker // `VLOG`, such as `VLogSiteManager`.
23*9356374aSAndroid Build Coastguard Worker 
24*9356374aSAndroid Build Coastguard Worker #ifndef ABSL_LOG_INTERNAL_VLOG_CONFIG_H_
25*9356374aSAndroid Build Coastguard Worker #define ABSL_LOG_INTERNAL_VLOG_CONFIG_H_
26*9356374aSAndroid Build Coastguard Worker 
27*9356374aSAndroid Build Coastguard Worker // IWYU pragma: private, include "absl/log/log.h"
28*9356374aSAndroid Build Coastguard Worker 
29*9356374aSAndroid Build Coastguard Worker #include <atomic>
30*9356374aSAndroid Build Coastguard Worker #include <cstdint>
31*9356374aSAndroid Build Coastguard Worker #include <functional>
32*9356374aSAndroid Build Coastguard Worker #include <limits>
33*9356374aSAndroid Build Coastguard Worker #include <type_traits>
34*9356374aSAndroid Build Coastguard Worker 
35*9356374aSAndroid Build Coastguard Worker #include "absl/base/attributes.h"
36*9356374aSAndroid Build Coastguard Worker #include "absl/base/config.h"
37*9356374aSAndroid Build Coastguard Worker #include "absl/base/optimization.h"
38*9356374aSAndroid Build Coastguard Worker #include "absl/base/thread_annotations.h"
39*9356374aSAndroid Build Coastguard Worker #include "absl/strings/string_view.h"
40*9356374aSAndroid Build Coastguard Worker 
41*9356374aSAndroid Build Coastguard Worker namespace absl {
42*9356374aSAndroid Build Coastguard Worker ABSL_NAMESPACE_BEGIN
43*9356374aSAndroid Build Coastguard Worker namespace log_internal {
44*9356374aSAndroid Build Coastguard Worker 
45*9356374aSAndroid Build Coastguard Worker class SyntheticBinary;
46*9356374aSAndroid Build Coastguard Worker class VLogSite;
47*9356374aSAndroid Build Coastguard Worker 
48*9356374aSAndroid Build Coastguard Worker int RegisterAndInitialize(VLogSite* v);
49*9356374aSAndroid Build Coastguard Worker void UpdateVLogSites();
50*9356374aSAndroid Build Coastguard Worker constexpr int kUseFlag = (std::numeric_limits<int16_t>::min)();
51*9356374aSAndroid Build Coastguard Worker 
52*9356374aSAndroid Build Coastguard Worker // Represents a unique callsite for a `VLOG()` or `VLOG_IS_ON()` call.
53*9356374aSAndroid Build Coastguard Worker //
54*9356374aSAndroid Build Coastguard Worker // Libraries that provide `VLOG`-like functionality should use this to
55*9356374aSAndroid Build Coastguard Worker // efficiently handle --vmodule.
56*9356374aSAndroid Build Coastguard Worker //
57*9356374aSAndroid Build Coastguard Worker // VLogSite objects must not be destroyed until the program exits. Doing so will
58*9356374aSAndroid Build Coastguard Worker // probably yield nasty segfaults in VLogSiteManager::UpdateLogSites(). The
59*9356374aSAndroid Build Coastguard Worker // recommendation is to make all such objects function-local statics.
60*9356374aSAndroid Build Coastguard Worker class VLogSite final {
61*9356374aSAndroid Build Coastguard Worker  public:
62*9356374aSAndroid Build Coastguard Worker   // `f` must not be destroyed until the program exits.
VLogSite(const char * f)63*9356374aSAndroid Build Coastguard Worker   explicit constexpr VLogSite(const char* f)
64*9356374aSAndroid Build Coastguard Worker       : file_(f), v_(kUninitialized), next_(nullptr) {}
65*9356374aSAndroid Build Coastguard Worker   VLogSite(const VLogSite&) = delete;
66*9356374aSAndroid Build Coastguard Worker   VLogSite& operator=(const VLogSite&) = delete;
67*9356374aSAndroid Build Coastguard Worker 
68*9356374aSAndroid Build Coastguard Worker   // Inlining the function yields a ~3x performance improvement at the cost of a
69*9356374aSAndroid Build Coastguard Worker   // 1.5x code size increase at the call site.
70*9356374aSAndroid Build Coastguard Worker   // Takes locks but does not allocate memory.
71*9356374aSAndroid Build Coastguard Worker   ABSL_ATTRIBUTE_ALWAYS_INLINE
IsEnabled(int level)72*9356374aSAndroid Build Coastguard Worker   bool IsEnabled(int level) {
73*9356374aSAndroid Build Coastguard Worker     int stale_v = v_.load(std::memory_order_relaxed);
74*9356374aSAndroid Build Coastguard Worker     if (ABSL_PREDICT_TRUE(level > stale_v)) {
75*9356374aSAndroid Build Coastguard Worker       return false;
76*9356374aSAndroid Build Coastguard Worker     }
77*9356374aSAndroid Build Coastguard Worker 
78*9356374aSAndroid Build Coastguard Worker     // We put everything other than the fast path, i.e. vlogging is initialized
79*9356374aSAndroid Build Coastguard Worker     // but not on, behind an out-of-line function to reduce code size.
80*9356374aSAndroid Build Coastguard Worker     // "level" is almost always a call-site constant, so we can save a bit
81*9356374aSAndroid Build Coastguard Worker     // of code space by special-casing for a few common levels.
82*9356374aSAndroid Build Coastguard Worker #if ABSL_HAVE_BUILTIN(__builtin_constant_p) || defined(__GNUC__)
83*9356374aSAndroid Build Coastguard Worker     if (__builtin_constant_p(level)) {
84*9356374aSAndroid Build Coastguard Worker       if (level == 0) return SlowIsEnabled0(stale_v);
85*9356374aSAndroid Build Coastguard Worker       if (level == 1) return SlowIsEnabled1(stale_v);
86*9356374aSAndroid Build Coastguard Worker       if (level == 2) return SlowIsEnabled2(stale_v);
87*9356374aSAndroid Build Coastguard Worker       if (level == 3) return SlowIsEnabled3(stale_v);
88*9356374aSAndroid Build Coastguard Worker       if (level == 4) return SlowIsEnabled4(stale_v);
89*9356374aSAndroid Build Coastguard Worker       if (level == 5) return SlowIsEnabled5(stale_v);
90*9356374aSAndroid Build Coastguard Worker     }
91*9356374aSAndroid Build Coastguard Worker #endif
92*9356374aSAndroid Build Coastguard Worker     return SlowIsEnabled(stale_v, level);
93*9356374aSAndroid Build Coastguard Worker   }
94*9356374aSAndroid Build Coastguard Worker 
95*9356374aSAndroid Build Coastguard Worker  private:
96*9356374aSAndroid Build Coastguard Worker   friend int log_internal::RegisterAndInitialize(VLogSite* v);
97*9356374aSAndroid Build Coastguard Worker   friend void log_internal::UpdateVLogSites();
98*9356374aSAndroid Build Coastguard Worker   friend class log_internal::SyntheticBinary;
99*9356374aSAndroid Build Coastguard Worker   static constexpr int kUninitialized = (std::numeric_limits<int>::max)();
100*9356374aSAndroid Build Coastguard Worker 
101*9356374aSAndroid Build Coastguard Worker   // SlowIsEnabled performs slower checks to determine whether a log site is
102*9356374aSAndroid Build Coastguard Worker   // enabled. Because it is expected to be called somewhat rarely
103*9356374aSAndroid Build Coastguard Worker   // (comparatively), it is not inlined to save on code size.
104*9356374aSAndroid Build Coastguard Worker   //
105*9356374aSAndroid Build Coastguard Worker   // Prerequisites to calling SlowIsEnabled:
106*9356374aSAndroid Build Coastguard Worker   //   1) stale_v is uninitialized OR
107*9356374aSAndroid Build Coastguard Worker   //   2) stale_v is initialized and >= level (meaning we must log).
108*9356374aSAndroid Build Coastguard Worker   // Takes locks but does not allocate memory.
109*9356374aSAndroid Build Coastguard Worker   ABSL_ATTRIBUTE_NOINLINE
110*9356374aSAndroid Build Coastguard Worker   bool SlowIsEnabled(int stale_v, int level);
111*9356374aSAndroid Build Coastguard Worker   ABSL_ATTRIBUTE_NOINLINE bool SlowIsEnabled0(int stale_v);
112*9356374aSAndroid Build Coastguard Worker   ABSL_ATTRIBUTE_NOINLINE bool SlowIsEnabled1(int stale_v);
113*9356374aSAndroid Build Coastguard Worker   ABSL_ATTRIBUTE_NOINLINE bool SlowIsEnabled2(int stale_v);
114*9356374aSAndroid Build Coastguard Worker   ABSL_ATTRIBUTE_NOINLINE bool SlowIsEnabled3(int stale_v);
115*9356374aSAndroid Build Coastguard Worker   ABSL_ATTRIBUTE_NOINLINE bool SlowIsEnabled4(int stale_v);
116*9356374aSAndroid Build Coastguard Worker   ABSL_ATTRIBUTE_NOINLINE bool SlowIsEnabled5(int stale_v);
117*9356374aSAndroid Build Coastguard Worker 
118*9356374aSAndroid Build Coastguard Worker   // This object is too size-sensitive to use absl::string_view.
119*9356374aSAndroid Build Coastguard Worker   const char* const file_;
120*9356374aSAndroid Build Coastguard Worker   std::atomic<int> v_;
121*9356374aSAndroid Build Coastguard Worker   std::atomic<VLogSite*> next_;
122*9356374aSAndroid Build Coastguard Worker };
123*9356374aSAndroid Build Coastguard Worker static_assert(std::is_trivially_destructible<VLogSite>::value,
124*9356374aSAndroid Build Coastguard Worker               "VLogSite must be trivially destructible");
125*9356374aSAndroid Build Coastguard Worker 
126*9356374aSAndroid Build Coastguard Worker // Returns the current verbose log level of `file`.
127*9356374aSAndroid Build Coastguard Worker // Does not allocate memory.
128*9356374aSAndroid Build Coastguard Worker int VLogLevel(absl::string_view file);
129*9356374aSAndroid Build Coastguard Worker 
130*9356374aSAndroid Build Coastguard Worker // Registers a site `v` to get updated as `vmodule` and `v` change.  Also
131*9356374aSAndroid Build Coastguard Worker // initializes the site based on their current values, and returns that result.
132*9356374aSAndroid Build Coastguard Worker // Does not allocate memory.
133*9356374aSAndroid Build Coastguard Worker int RegisterAndInitialize(VLogSite* v);
134*9356374aSAndroid Build Coastguard Worker 
135*9356374aSAndroid Build Coastguard Worker // Allocates memory.
136*9356374aSAndroid Build Coastguard Worker void UpdateVLogSites();
137*9356374aSAndroid Build Coastguard Worker 
138*9356374aSAndroid Build Coastguard Worker // Completely overwrites the saved value of `vmodule`.
139*9356374aSAndroid Build Coastguard Worker // Allocates memory.
140*9356374aSAndroid Build Coastguard Worker void UpdateVModule(absl::string_view vmodule);
141*9356374aSAndroid Build Coastguard Worker 
142*9356374aSAndroid Build Coastguard Worker // Updates the global verbosity level to `v` and returns the prior value.
143*9356374aSAndroid Build Coastguard Worker // Allocates memory.
144*9356374aSAndroid Build Coastguard Worker int UpdateGlobalVLogLevel(int v);
145*9356374aSAndroid Build Coastguard Worker 
146*9356374aSAndroid Build Coastguard Worker // Atomically prepends `module_pattern=log_level` to the start of vmodule.
147*9356374aSAndroid Build Coastguard Worker // Returns the prior value for `module_pattern` if there was an exact match and
148*9356374aSAndroid Build Coastguard Worker // `global_v` otherwise.
149*9356374aSAndroid Build Coastguard Worker // Allocates memory.
150*9356374aSAndroid Build Coastguard Worker int PrependVModule(absl::string_view module_pattern, int log_level);
151*9356374aSAndroid Build Coastguard Worker 
152*9356374aSAndroid Build Coastguard Worker // Registers `on_update` to be called whenever `v` or `vmodule` change.
153*9356374aSAndroid Build Coastguard Worker // Allocates memory.
154*9356374aSAndroid Build Coastguard Worker void OnVLogVerbosityUpdate(std::function<void()> cb);
155*9356374aSAndroid Build Coastguard Worker 
156*9356374aSAndroid Build Coastguard Worker // Does not allocate memory.
157*9356374aSAndroid Build Coastguard Worker VLogSite* SetVModuleListHeadForTestOnly(VLogSite* v);
158*9356374aSAndroid Build Coastguard Worker 
159*9356374aSAndroid Build Coastguard Worker }  // namespace log_internal
160*9356374aSAndroid Build Coastguard Worker ABSL_NAMESPACE_END
161*9356374aSAndroid Build Coastguard Worker }  // namespace absl
162*9356374aSAndroid Build Coastguard Worker 
163*9356374aSAndroid Build Coastguard Worker #endif  // ABSL_LOG_INTERNAL_VLOG_CONFIG_H_
164