globals.cc (5431B)
1 // Copyright 2022 The Abseil Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of 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, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #include "absl/log/globals.h" 16 17 #include <atomic> 18 #include <cstddef> 19 #include <cstdint> 20 #include <cstdlib> 21 #include <cstring> 22 #include <string> 23 24 #include "absl/base/attributes.h" 25 #include "absl/base/config.h" 26 #include "absl/base/internal/atomic_hook.h" 27 #include "absl/base/internal/raw_logging.h" 28 #include "absl/base/log_severity.h" 29 #include "absl/hash/hash.h" 30 #include "absl/strings/string_view.h" 31 32 namespace absl { 33 ABSL_NAMESPACE_BEGIN 34 namespace { 35 36 // These atomics represent logging library configuration. 37 // Integer types are used instead of absl::LogSeverity to ensure that a 38 // lock-free std::atomic is used when possible. 39 ABSL_CONST_INIT std::atomic<int> min_log_level{ 40 static_cast<int>(absl::LogSeverityAtLeast::kInfo)}; 41 ABSL_CONST_INIT std::atomic<int> stderrthreshold{ 42 static_cast<int>(absl::LogSeverityAtLeast::kError)}; 43 // We evaluate this value as a hash comparison to avoid having to 44 // hold a mutex or make a copy (to access the value of a string-typed flag) in 45 // very hot codepath. 46 ABSL_CONST_INIT std::atomic<size_t> log_backtrace_at_hash{0}; 47 ABSL_CONST_INIT std::atomic<bool> prepend_log_prefix{true}; 48 49 constexpr char kDefaultAndroidTag[] = "native"; 50 ABSL_CONST_INIT std::atomic<const char*> android_log_tag{kDefaultAndroidTag}; 51 52 ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES 53 absl::base_internal::AtomicHook<log_internal::LoggingGlobalsListener> 54 logging_globals_listener; 55 56 size_t HashSiteForLogBacktraceAt(absl::string_view file, int line) { 57 return absl::HashOf(file, line); 58 } 59 60 void TriggerLoggingGlobalsListener() { 61 auto* listener = logging_globals_listener.Load(); 62 if (listener != nullptr) listener(); 63 } 64 65 } // namespace 66 67 namespace log_internal { 68 69 void RawSetMinLogLevel(absl::LogSeverityAtLeast severity) { 70 min_log_level.store(static_cast<int>(severity), std::memory_order_release); 71 } 72 73 void RawSetStderrThreshold(absl::LogSeverityAtLeast severity) { 74 stderrthreshold.store(static_cast<int>(severity), std::memory_order_release); 75 } 76 77 void RawEnableLogPrefix(bool on_off) { 78 prepend_log_prefix.store(on_off, std::memory_order_release); 79 } 80 81 void SetLoggingGlobalsListener(LoggingGlobalsListener l) { 82 logging_globals_listener.Store(l); 83 } 84 85 } // namespace log_internal 86 87 absl::LogSeverityAtLeast MinLogLevel() { 88 return static_cast<absl::LogSeverityAtLeast>( 89 min_log_level.load(std::memory_order_acquire)); 90 } 91 92 void SetMinLogLevel(absl::LogSeverityAtLeast severity) { 93 log_internal::RawSetMinLogLevel(severity); 94 TriggerLoggingGlobalsListener(); 95 } 96 97 namespace log_internal { 98 99 ScopedMinLogLevel::ScopedMinLogLevel(absl::LogSeverityAtLeast severity) 100 : saved_severity_(absl::MinLogLevel()) { 101 absl::SetMinLogLevel(severity); 102 } 103 ScopedMinLogLevel::~ScopedMinLogLevel() { 104 absl::SetMinLogLevel(saved_severity_); 105 } 106 107 } // namespace log_internal 108 109 absl::LogSeverityAtLeast StderrThreshold() { 110 return static_cast<absl::LogSeverityAtLeast>( 111 stderrthreshold.load(std::memory_order_acquire)); 112 } 113 114 void SetStderrThreshold(absl::LogSeverityAtLeast severity) { 115 log_internal::RawSetStderrThreshold(severity); 116 TriggerLoggingGlobalsListener(); 117 } 118 119 ScopedStderrThreshold::ScopedStderrThreshold(absl::LogSeverityAtLeast severity) 120 : saved_severity_(absl::StderrThreshold()) { 121 absl::SetStderrThreshold(severity); 122 } 123 124 ScopedStderrThreshold::~ScopedStderrThreshold() { 125 absl::SetStderrThreshold(saved_severity_); 126 } 127 128 namespace log_internal { 129 130 const char* GetAndroidNativeTag() { 131 return android_log_tag.load(std::memory_order_acquire); 132 } 133 134 } // namespace log_internal 135 136 void SetAndroidNativeTag(const char* tag) { 137 ABSL_CONST_INIT static std::atomic<const std::string*> user_log_tag(nullptr); 138 ABSL_INTERNAL_CHECK(tag, "tag must be non-null."); 139 140 const std::string* tag_str = new std::string(tag); 141 ABSL_INTERNAL_CHECK( 142 android_log_tag.exchange(tag_str->c_str(), std::memory_order_acq_rel) == 143 kDefaultAndroidTag, 144 "SetAndroidNativeTag() must only be called once per process!"); 145 user_log_tag.store(tag_str, std::memory_order_relaxed); 146 } 147 148 namespace log_internal { 149 150 bool ShouldLogBacktraceAt(absl::string_view file, int line) { 151 const size_t flag_hash = 152 log_backtrace_at_hash.load(std::memory_order_relaxed); 153 154 return flag_hash != 0 && flag_hash == HashSiteForLogBacktraceAt(file, line); 155 } 156 157 } // namespace log_internal 158 159 void SetLogBacktraceLocation(absl::string_view file, int line) { 160 log_backtrace_at_hash.store(HashSiteForLogBacktraceAt(file, line), 161 std::memory_order_relaxed); 162 } 163 164 void ClearLogBacktraceLocation() { 165 log_backtrace_at_hash.store(0, std::memory_order_relaxed); 166 } 167 168 bool ShouldPrependLogPrefix() { 169 return prepend_log_prefix.load(std::memory_order_acquire); 170 } 171 172 void EnableLogPrefix(bool on_off) { 173 log_internal::RawEnableLogPrefix(on_off); 174 TriggerLoggingGlobalsListener(); 175 } 176 177 ABSL_NAMESPACE_END 178 } // namespace absl