1 // Copyright 2010-2018, Google Inc. 2 // All rights reserved. 3 // 4 // Redistribution and use in source and binary forms, with or without 5 // modification, are permitted provided that the following conditions are 6 // met: 7 // 8 // * Redistributions of source code must retain the above copyright 9 // notice, this list of conditions and the following disclaimer. 10 // * Redistributions in binary form must reproduce the above 11 // copyright notice, this list of conditions and the following disclaimer 12 // in the documentation and/or other materials provided with the 13 // distribution. 14 // * Neither the name of Google Inc. nor the names of its 15 // contributors may be used to endorse or promote products derived from 16 // this software without specific prior written permission. 17 // 18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 30 #ifndef MOZC_BASE_LOGGING_H_ 31 #define MOZC_BASE_LOGGING_H_ 32 33 34 #include <iostream> 35 #include <string> 36 37 #include "base/flags.h" 38 #include "base/port.h" 39 40 namespace mozc { 41 42 enum LogSeverity { 43 #ifdef OS_ANDROID 44 // Defined in <android/log.h> 45 LOG_UNKNOWN = 0, // ANDROID_LOG_UNKNOWN 46 LOG_DEFAULT = 1, // ANDROID_LOG_DEFAULT 47 LOG_VERBOSE = 2, // ANDROID_LOG_VERBOSE 48 LOG_DEBUG = 3, // ANDROID_LOG_DEBUG 49 LOG_INFO = 4, // ANDROID_LOG_INFO 50 LOG_WARNING = 5, // ANDROID_LOG_WARN 51 LOG_ERROR = 6, // ANDROID_LOG_ERROR 52 LOG_FATAL = 7, // ANDROID_LOG_FATAL 53 LOG_SILENT = 8, // ANDROID_LOG_SILENT 54 LOG_SEVERITY_SIZE = 9, 55 #else 56 LOG_INFO = 0, 57 LOG_WARNING = 1, 58 LOG_ERROR = 2, 59 // Special hack for Windows build, where ERROR is defined as 0 in wingdi.h. 60 #ifdef OS_WIN 61 LOG_0 = LOG_ERROR, 62 #endif // OS_WIN 63 LOG_FATAL = 3, 64 LOG_SEVERITY_SIZE = 4, 65 #endif 66 }; 67 68 // DFATAL is FATAL in debug mode, ERROR in normal mode 69 #ifdef DEBUG 70 #define LOG_DFATAL LOG_FATAL 71 #else 72 #define LOG_DFATAL LOG_ERROR 73 #endif // DEBUG 74 75 class NullLogStream; 76 77 class Logging { 78 public: 79 // Initializes log stream with the output file path and --logtostderr. 80 static void InitLogStream(const string &log_file_path); 81 82 // Closes the logging stream 83 static void CloseLogStream(); 84 85 // Gets working log stream. The log message can be written to the stream. 86 // The stream must be finalized by FinalizeWorkingLogStream(). 87 static std::ostream &GetWorkingLogStream(); 88 89 // Finalizes the working stream. 90 // - Appends std::endl to working stream. 91 // - Writes the content to real backing logging stream, which is initialized 92 // by InitLogStream(). 93 // - Deletes the working stream object. 94 static void FinalizeWorkingLogStream(LogSeverity, std::ostream*); 95 96 // Gets NullLogStream for NO_LOGGING mode 97 static NullLogStream &GetNullLogStream(); 98 99 // Converts LogSeverity to the string name 100 static const char *GetLogSeverityName(LogSeverity severity); 101 102 // Returns "YYYY-MM-DD HH:MM:SS PID TID", e.g. "2008 11-16 19:40:21 100 20" 103 static string GetLogMessageHeader(); 104 105 // Returns FLAGS_v 106 static int GetVerboseLevel(); 107 108 // Sets FLAGS_v 109 static void SetVerboseLevel(int verboselevel); 110 111 // Sets Verbose Level for Config. 112 // Since Config dialog will overwrite -v option, we separate 113 // config_verbose_level and FLAGS_v. 114 // real_config_level = max(FLAGS_v, config_verbose_level); 115 static void SetConfigVerboseLevel(int verboselevel); 116 117 // Gets an escape sequence to colorize log messages on tty devices. 118 static const char *GetBeginColorEscapeSequence(LogSeverity severity); 119 static const char *GetEndColorEscapeSequence(); 120 121 private: 122 DISALLOW_IMPLICIT_CONSTRUCTORS(Logging); 123 }; 124 125 // Finalizer to flush/delete working log stream. 126 // Finalizer takes woking log stream instance through operator&() 127 // and finalizes it in destructor. 128 class LogFinalizer { 129 public: 130 explicit LogFinalizer(LogSeverity severity); 131 ~LogFinalizer(); 132 133 // Google's C++ style guide requires reference argument to be const. 134 // Here we need non-const reference in order to delete working stream object. 135 void operator&(std::ostream&); 136 137 private: 138 const LogSeverity severity_; 139 std::ostream *working_stream_; 140 }; 141 142 // When using NullLogStream, all debug message will be stripped 143 class NullLogStream { 144 public: 145 template <typename T> 146 NullLogStream& operator<<(const T &value) { 147 return *this; 148 } 149 NullLogStream& operator<<(std::ostream& (*pfunc)(std::ostream&) ) { 150 return *this; 151 } 152 }; 153 154 class NullLogFinalizer { 155 public: NullLogFinalizer(LogSeverity severity)156 explicit NullLogFinalizer(LogSeverity severity) 157 : severity_(severity) {} 158 ~NullLogFinalizer()159 ~NullLogFinalizer() { 160 if (severity_ >= LOG_FATAL) { 161 OnFatal(); 162 } 163 } 164 165 void operator&(NullLogStream&) {} 166 167 private: 168 static void OnFatal(); 169 170 const LogSeverity severity_; 171 }; 172 173 } // namespace mozc 174 175 // ad-hoc porting of google-glog 176 #ifdef NO_LOGGING // don't use logging feature. 177 178 // in release binary, we don't want to evaluate the outputs for logging. 179 // LOG(FATAL) is an exception. 180 #define LOG(severity) \ 181 (mozc::LOG_##severity < mozc::LOG_FATAL) ? (void) 0 : \ 182 mozc::NullLogFinalizer(mozc::LOG_##severity) & \ 183 mozc::Logging::GetNullLogStream() 184 185 // To suppress the "statement has no effect" waring, (void) is 186 // inserted. This technique is suggested by the gcc manual 187 // -Wunused-variable section. 188 #define LOG_IF(severity, condition) \ 189 (mozc::LOG_##severity < mozc::LOG_FATAL || !(condition)) ? (void) 0 : \ 190 mozc::NullLogFinalizer(mozc::LOG_##severity) & \ 191 mozc::Logging::GetNullLogStream() 192 193 #define CHECK(condition) \ 194 (condition) ? (void) 0 : \ 195 mozc::NullLogFinalizer(mozc::LOG_FATAL) & mozc::Logging::GetNullLogStream() 196 197 #else // NO_LOGGING 198 199 #define LOG(severity) \ 200 mozc::LogFinalizer(mozc::LOG_##severity) & \ 201 mozc::Logging::GetWorkingLogStream() \ 202 << mozc::Logging::GetLogMessageHeader() << " " \ 203 << __FILE__ << "(" << __LINE__ << ") " \ 204 << mozc::Logging::GetBeginColorEscapeSequence(mozc::LOG_##severity) \ 205 << "LOG(" << mozc::Logging::GetLogSeverityName(mozc::LOG_##severity) << ")" \ 206 << mozc::Logging::GetEndColorEscapeSequence() << " " \ 207 208 #define LOG_IF(severity, condition) \ 209 (!(condition)) ? (void) 0 : \ 210 mozc::LogFinalizer(mozc::LOG_##severity) & \ 211 mozc::Logging::GetWorkingLogStream() \ 212 << mozc::Logging::GetLogMessageHeader() << " " \ 213 << __FILE__ << "(" << __LINE__ << ") " \ 214 << mozc::Logging::GetBeginColorEscapeSequence(mozc::LOG_##severity) \ 215 << "LOG(" << mozc::Logging::GetLogSeverityName(mozc::LOG_##severity) << ")" \ 216 << mozc::Logging::GetEndColorEscapeSequence() \ 217 << " [" << #condition << "] " 218 219 #define CHECK(condition) \ 220 (condition) ? (void) 0 : \ 221 mozc::LogFinalizer(mozc::LOG_FATAL) & \ 222 mozc::Logging::GetWorkingLogStream() \ 223 << mozc::Logging::GetLogMessageHeader() << " " \ 224 << __FILE__ << "(" << __LINE__ << ") " \ 225 << mozc::Logging::GetBeginColorEscapeSequence(mozc::LOG_FATAL) \ 226 << "CHECK" \ 227 << mozc::Logging::GetEndColorEscapeSequence() \ 228 << " [" << #condition << "] " 229 #endif // end NO_LOGGING 230 231 #define VLOG_IS_ON(verboselevel) \ 232 (mozc::Logging::GetVerboseLevel() >= verboselevel) 233 234 #define VLOG(verboselevel) LOG_IF(INFO, VLOG_IS_ON(verboselevel)) 235 236 #define VLOG_IF(verboselevel, condition) \ 237 LOG_IF(INFO, ((condition) && VLOG_IS_ON(verboselevel))) 238 239 #define CHECK_EQ(a, b) CHECK((a) == (b)) 240 #define CHECK_NE(a, b) CHECK((a) != (b)) 241 #define CHECK_GE(a, b) CHECK((a) >= (b)) 242 #define CHECK_LE(a, b) CHECK((a) <= (b)) 243 #define CHECK_GT(a, b) CHECK((a) > (b)) 244 #define CHECK_LT(a, b) CHECK((a) < (b)) 245 246 // Debug build 247 #if defined(DEBUG) || defined(_DEBUG) 248 249 #define DLOG(severity) LOG(severity) 250 #define DLOG_IF(severity, condition) LOG_IF(severity, condition) 251 #define DCHECK(condition) CHECK(condition) 252 #define DCHECK_EQ(a, b) CHECK_EQ(a, b) 253 #define DCHECK_NE(a, b) CHECK_NE(a, b) 254 #define DCHECK_GE(a, b) CHECK_GE(a, b) 255 #define DCHECK_LE(a, b) CHECK_LE(a, b) 256 #define DCHECK_GT(a, b) CHECK_GT(a, b) 257 #define DCHECK_LT(a, b) CHECK_LT(a, b) 258 259 #else // opt build 260 261 #define DLOG(severity) \ 262 mozc::NullLogFinalizer(mozc::LOG_##severity) & \ 263 mozc::Logging::GetNullLogStream() 264 265 #define DLOG_IF(severity, condition) \ 266 (true || !(condition)) ? (void) 0 : \ 267 mozc::NullLogFinalizer(mozc::LOG_##severity) \ 268 & mozc::Logging::GetNullLogStream() 269 270 #define DCHECK(condition) while (false) CHECK(condition) 271 #define DCHECK_EQ(a, b) while (false) CHECK_EQ(a, b) 272 #define DCHECK_NE(a, b) while (false) CHECK_NE(a, b) 273 #define DCHECK_GE(a, b) while (false) CHECK_GE(a, b) 274 #define DCHECK_LE(a, b) while (false) CHECK_LE(a, b) 275 #define DCHECK_GT(a, b) while (false) CHECK_GT(a, b) 276 #define DCHECK_LT(a, b) while (false) CHECK_LT(a, b) 277 278 #endif // DEBUG 279 280 #define DVLOG(verboselevel) DLOG_IF(INFO, VLOG_IS_ON(verboselevel)) 281 282 DECLARE_bool(logtostderr); 283 284 285 #ifndef DVLOG_IF 286 #define DVLOG_IF(verboselevel, condition) \ 287 DLOG_IF(INFO, (condition) && VLOG_IS_ON(verboselevel)) 288 #endif 289 290 #endif // MOZC_BASE_LOGGING_H_ 291