1 /* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef ART_LIBARTBASE_BASE_LOGGING_H_ 18 #define ART_LIBARTBASE_BASE_LOGGING_H_ 19 20 #include <sstream> 21 #include <variant> 22 23 #include "android-base/logging.h" 24 #include "macros.h" 25 26 namespace art { 27 28 // Make libbase's LogSeverity more easily available. 29 using ::android::base::LogSeverity; 30 using ::android::base::ScopedLogSeverity; 31 32 // Abort function. 33 using AbortFunction = void(const char*); 34 35 // The members of this struct are the valid arguments to VLOG and VLOG_IS_ON in code, 36 // and the "-verbose:" command line argument. 37 struct LogVerbosity { 38 bool class_linker; // Enabled with "-verbose:class". 39 bool collector; 40 bool compiler; 41 bool deopt; 42 bool gc; 43 bool heap; 44 bool interpreter; // Enabled with "-verbose:interpreter". 45 bool jdwp; 46 bool jit; 47 bool jni; 48 bool monitor; 49 bool oat; 50 bool profiler; 51 bool signals; 52 bool simulator; 53 bool startup; 54 bool third_party_jni; // Enabled with "-verbose:third-party-jni". 55 bool threads; 56 bool verifier; 57 bool verifier_debug; // Only works in debug builds. 58 bool image; 59 bool systrace_lock_logging; // Enabled with "-verbose:sys-locks". 60 bool agents; 61 bool dex; // Some dex access output etc. 62 bool plugin; // Used by some plugins. 63 }; 64 65 // Global log verbosity setting, initialized by InitLogging. 66 extern LogVerbosity gLogVerbosity; 67 68 // Configure logging based on ANDROID_LOG_TAGS environment variable. 69 // We need to parse a string that looks like 70 // 71 // *:v jdwp:d dalvikvm:d dalvikvm-gc:i dalvikvmi:i 72 // 73 // The tag (or '*' for the global level) comes first, followed by a colon 74 // and a letter indicating the minimum priority level we're expected to log. 75 // This can be used to reveal or conceal logs with specific tags. 76 extern void InitLogging(char* argv[], AbortFunction& default_aborter); 77 78 // Returns the command line used to invoke the current tool or null if InitLogging hasn't been 79 // performed. 80 extern const char* GetCmdLine(); 81 82 // The command used to start the ART runtime, such as "/apex/com.android.art/bin/dalvikvm". If 83 // InitLogging hasn't been performed then just returns "art". 84 extern const char* ProgramInvocationName(); 85 86 // A short version of the command used to start the ART runtime, such as "dalvikvm". If InitLogging 87 // hasn't been performed then just returns "art". 88 extern const char* ProgramInvocationShortName(); 89 90 class LogHelper { 91 public: 92 // A logging helper for logging a single line. Can be used with little stack. 93 static void LogLineLowStack(const char* file, 94 unsigned int line, 95 android::base::LogSeverity severity, 96 const char* msg); 97 98 private: 99 DISALLOW_ALLOCATION(); 100 DISALLOW_COPY_AND_ASSIGN(LogHelper); 101 }; 102 103 // Copy the contents of file_name to the log stream for level. 104 bool PrintFileToLog(const std::string& file_name, android::base::LogSeverity level); 105 106 // Is verbose logging enabled for the given module? Where the module is defined in LogVerbosity. 107 #define VLOG_IS_ON(module) UNLIKELY(::art::gLogVerbosity.module) 108 109 // Variant of LOG that logs when verbose logging is enabled for a module. For example, 110 // VLOG(jni) << "A JNI operation was performed"; 111 #define VLOG(module) if (VLOG_IS_ON(module)) LOG(INFO) 112 113 // Holder to implement VLOG_STREAM. 114 class VlogMessage { 115 public: 116 // TODO Taken from android_base. VlogMessage(bool enable,const char * file,unsigned int line,::android::base::LogSeverity severity,const char * tag,int error)117 VlogMessage(bool enable, 118 const char* file, 119 unsigned int line, 120 ::android::base::LogSeverity severity, 121 const char* tag, 122 int error) 123 : msg_(std::in_place_type<std::ostringstream>) { 124 if (enable) { 125 msg_.emplace<::android::base::LogMessage>(file, line, severity, tag, error); 126 } 127 } 128 stream()129 std::ostream& stream() { 130 if (std::holds_alternative<std::ostringstream>(msg_)) { 131 return std::get<std::ostringstream>(msg_); 132 } else { 133 return std::get<::android::base::LogMessage>(msg_).stream(); 134 } 135 } 136 137 private: 138 std::variant<::android::base::LogMessage, std::ostringstream> msg_; 139 }; 140 141 // Return the stream associated with logging for the given module. NB Unlike VLOG function calls 142 // will still be performed. Output will be suppressed if the module is not on. 143 #define VLOG_STREAM(module) \ 144 ::art::VlogMessage(VLOG_IS_ON(module), \ 145 __FILE__, \ 146 __LINE__, \ 147 ::android::base::INFO, \ 148 _LOG_TAG_INTERNAL, \ 149 -1) \ 150 .stream() 151 152 // Check whether an implication holds between x and y, LOG(FATAL) if not. The value 153 // of the expressions x and y is evaluated once. Extra logging can be appended 154 // using << after. For example: 155 // 156 // CHECK_IMPLIES(1==1, 0==1) results in 157 // "Check failed: 1==1 (true) implies 0==1 (false) ". 158 // clang-format off 159 #define CHECK_IMPLIES(LHS, RHS) \ 160 LIKELY(!(LHS) || (RHS)) || ABORT_AFTER_LOG_FATAL_EXPR(false) || \ 161 ::android::base::LogMessage(__FILE__, __LINE__, ::android::base::FATAL, _LOG_TAG_INTERNAL, \ 162 -1) \ 163 .stream() \ 164 << "Check failed: " #LHS << " (true) implies " #RHS << " (false)" 165 // clang-format on 166 167 #define DCHECK_IMPLIES(a, b) \ 168 if (::android::base::kEnableDChecks) CHECK_IMPLIES(a, b) 169 170 } // namespace art 171 172 #endif // ART_LIBARTBASE_BASE_LOGGING_H_ 173