1 /* 2 * libjingle 3 * Copyright 2004--2005, Google Inc. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, 9 * this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright notice, 11 * this list of conditions and the following disclaimer in the documentation 12 * and/or other materials provided with the distribution. 13 * 3. The name of the author may not be used to endorse or promote products 14 * derived from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 // LOG(...) an ostream target that can be used to send formatted 29 // output to a variety of logging targets, such as debugger console, stderr, 30 // file, or any StreamInterface. 31 // The severity level passed as the first argument to the LOGging 32 // functions is used as a filter, to limit the verbosity of the logging. 33 // Static members of LogMessage documented below are used to control the 34 // verbosity and target of the output. 35 // There are several variations on the LOG macro which facilitate logging 36 // of common error conditions, detailed below. 37 38 // LOG(sev) logs the given stream at severity "sev", which must be a 39 // compile-time constant of the LoggingSeverity type, without the namespace 40 // prefix. 41 // LOG_V(sev) Like LOG(), but sev is a run-time variable of the LoggingSeverity 42 // type (basically, it just doesn't prepend the namespace). 43 // LOG_F(sev) Like LOG(), but includes the name of the current function. 44 // LOG_GLE(M)(sev [, mod]) attempt to add a string description of the 45 // HRESULT returned by GetLastError. The "M" variant allows searching of a 46 // DLL's string table for the error description. 47 // LOG_ERRNO(sev) attempts to add a string description of an errno-derived 48 // error. errno and associated facilities exist on both Windows and POSIX, 49 // but on Windows they only apply to the C/C++ runtime. 50 // LOG_ERR(sev) is an alias for the platform's normal error system, i.e. _GLE on 51 // Windows and _ERRNO on POSIX. 52 // (The above three also all have _EX versions that let you specify the error 53 // code, rather than using the last one.) 54 // LOG_E(sev, ctx, err, ...) logs a detailed error interpreted using the 55 // specified context. 56 // LOG_CHECK_LEVEL(sev) (and LOG_CHECK_LEVEL_V(sev)) can be used as a test 57 // before performing expensive or sensitive operations whose sole purpose is 58 // to output logging data at the desired level. 59 // Lastly, PLOG(sev, err) is an alias for LOG_ERR_EX. 60 61 #ifndef TALK_BASE_LOGGING_H_ 62 #define TALK_BASE_LOGGING_H_ 63 64 #ifdef HAVE_CONFIG_H 65 #include "config.h" // NOLINT 66 #endif 67 68 #include <list> 69 #include <sstream> 70 #include <string> 71 #include <utility> 72 #include "talk/base/basictypes.h" 73 #include "talk/base/criticalsection.h" 74 75 namespace talk_base { 76 77 class StreamInterface; 78 79 /////////////////////////////////////////////////////////////////////////////// 80 // ConstantLabel can be used to easily generate string names from constant 81 // values. This can be useful for logging descriptive names of error messages. 82 // Usage: 83 // const ConstantLabel LIBRARY_ERRORS[] = { 84 // KLABEL(SOME_ERROR), 85 // KLABEL(SOME_OTHER_ERROR), 86 // ... 87 // LASTLABEL 88 // } 89 // 90 // int err = LibraryFunc(); 91 // LOG(LS_ERROR) << "LibraryFunc returned: " 92 // << ErrorName(err, LIBRARY_ERRORS); 93 94 struct ConstantLabel { int value; const char * label; }; 95 #define KLABEL(x) { x, #x } 96 #define TLABEL(x, y) { x, y } 97 #define LASTLABEL { 0, 0 } 98 99 const char * FindLabel(int value, const ConstantLabel entries[]); 100 std::string ErrorName(int err, const ConstantLabel* err_table); 101 102 ////////////////////////////////////////////////////////////////////// 103 104 // Note that the non-standard LoggingSeverity aliases exist because they are 105 // still in broad use. The meanings of the levels are: 106 // LS_SENSITIVE: Information which should only be logged with the consent 107 // of the user, due to privacy concerns. 108 // LS_VERBOSE: This level is for data which we do not want to appear in the 109 // normal debug log, but should appear in diagnostic logs. 110 // LS_INFO: Chatty level used in debugging for all sorts of things, the default 111 // in debug builds. 112 // LS_WARNING: Something that may warrant investigation. 113 // LS_ERROR: Something that should not have occurred. 114 enum LoggingSeverity { LS_SENSITIVE, LS_VERBOSE, LS_INFO, LS_WARNING, LS_ERROR, 115 INFO = LS_INFO, 116 WARNING = LS_WARNING, 117 LERROR = LS_ERROR }; 118 119 // LogErrorContext assists in interpreting the meaning of an error value. 120 enum LogErrorContext { 121 ERRCTX_NONE, 122 ERRCTX_ERRNO, // System-local errno 123 ERRCTX_HRESULT, // Windows HRESULT 124 ERRCTX_OSSTATUS, // MacOS OSStatus 125 126 // Abbreviations for LOG_E macro 127 ERRCTX_EN = ERRCTX_ERRNO, // LOG_E(sev, EN, x) 128 ERRCTX_HR = ERRCTX_HRESULT, // LOG_E(sev, HR, x) 129 ERRCTX_OS = ERRCTX_OSSTATUS, // LOG_E(sev, OS, x) 130 }; 131 132 class LogMessage { 133 public: 134 static const int NO_LOGGING; 135 static const uint32 WARN_SLOW_LOGS_DELAY = 50; // ms 136 137 LogMessage(const char* file, int line, LoggingSeverity sev, 138 LogErrorContext err_ctx = ERRCTX_NONE, int err = 0, 139 const char* module = NULL); 140 ~LogMessage(); 141 142 static inline bool Loggable(LoggingSeverity sev) { return (sev >= min_sev_); } 143 std::ostream& stream() { return print_stream_; } 144 145 // Returns the time at which this function was called for the first time. 146 // The time will be used as the logging start time. 147 // If this is not called externally, the LogMessage ctor also calls it, in 148 // which case the logging start time will be the time of the first LogMessage 149 // instance is created. 150 static uint32 LogStartTime(); 151 152 // Returns the wall clock equivalent of |LogStartTime|, in seconds from the 153 // epoch. 154 static uint32 WallClockStartTime(); 155 156 // These are attributes which apply to all logging channels 157 // LogContext: Display the file and line number of the message 158 static void LogContext(int min_sev); 159 // LogThreads: Display the thread identifier of the current thread 160 static void LogThreads(bool on = true); 161 // LogTimestamps: Display the elapsed time of the program 162 static void LogTimestamps(bool on = true); 163 164 // These are the available logging channels 165 // Debug: Debug console on Windows, otherwise stderr 166 static void LogToDebug(int min_sev); 167 static int GetLogToDebug() { return dbg_sev_; } 168 169 // Stream: Any non-blocking stream interface. LogMessage takes ownership of 170 // the stream. Multiple streams may be specified by using AddLogToStream. 171 // LogToStream is retained for backwards compatibility; when invoked, it 172 // will discard any previously set streams and install the specified stream. 173 // GetLogToStream gets the severity for the specified stream, of if none 174 // is specified, the minimum stream severity. 175 // RemoveLogToStream removes the specified stream, without destroying it. 176 static void LogToStream(StreamInterface* stream, int min_sev); 177 static int GetLogToStream(StreamInterface* stream = NULL); 178 static void AddLogToStream(StreamInterface* stream, int min_sev); 179 static void RemoveLogToStream(StreamInterface* stream); 180 181 // Testing against MinLogSeverity allows code to avoid potentially expensive 182 // logging operations by pre-checking the logging level. 183 static int GetMinLogSeverity() { return min_sev_; } 184 185 static void SetDiagnosticMode(bool f) { is_diagnostic_mode_ = f; } 186 static bool IsDiagnosticMode() { return is_diagnostic_mode_; } 187 188 // Parses the provided parameter stream to configure the options above. 189 // Useful for configuring logging from the command line. If file logging 190 // is enabled, it is output to the specified filename. 191 static void ConfigureLogging(const char* params, const char* filename); 192 193 // Convert the string to a LS_ value; also accept numeric values. 194 static int ParseLogSeverity(const std::string& value); 195 196 private: 197 typedef std::list<std::pair<StreamInterface*, int> > StreamList; 198 199 // Updates min_sev_ appropriately when debug sinks change. 200 static void UpdateMinLogSeverity(); 201 202 // These assist in formatting some parts of the debug output. 203 static const char* Describe(LoggingSeverity sev); 204 static const char* DescribeFile(const char* file); 205 206 // These write out the actual log messages. 207 static void OutputToDebug(const std::string& msg, LoggingSeverity severity_); 208 static void OutputToStream(StreamInterface* stream, const std::string& msg); 209 210 // The ostream that buffers the formatted message before output 211 std::ostringstream print_stream_; 212 213 // The severity level of this message 214 LoggingSeverity severity_; 215 216 // String data generated in the constructor, that should be appended to 217 // the message before output. 218 std::string extra_; 219 220 // If time it takes to write to stream is more than this, log one 221 // additional warning about it. 222 uint32 warn_slow_logs_delay_; 223 224 // Global lock for the logging subsystem 225 static CriticalSection crit_; 226 227 // dbg_sev_ is the thresholds for those output targets 228 // min_sev_ is the minimum (most verbose) of those levels, and is used 229 // as a short-circuit in the logging macros to identify messages that won't 230 // be logged. 231 // ctx_sev_ is the minimum level at which file context is displayed 232 static int min_sev_, dbg_sev_, ctx_sev_; 233 234 // The output streams and their associated severities 235 static StreamList streams_; 236 237 // Flags for formatting options 238 static bool thread_, timestamp_; 239 240 // are we in diagnostic mode (as defined by the app)? 241 static bool is_diagnostic_mode_; 242 243 DISALLOW_EVIL_CONSTRUCTORS(LogMessage); 244 }; 245 246 ////////////////////////////////////////////////////////////////////// 247 // Logging Helpers 248 ////////////////////////////////////////////////////////////////////// 249 250 class LogMultilineState { 251 public: 252 size_t unprintable_count_[2]; 253 LogMultilineState() { 254 unprintable_count_[0] = unprintable_count_[1] = 0; 255 } 256 }; 257 258 // When possible, pass optional state variable to track various data across 259 // multiple calls to LogMultiline. Otherwise, pass NULL. 260 void LogMultiline(LoggingSeverity level, const char* label, bool input, 261 const void* data, size_t len, bool hex_mode, 262 LogMultilineState* state); 263 264 ////////////////////////////////////////////////////////////////////// 265 // Macros which automatically disable logging when LOGGING == 0 266 ////////////////////////////////////////////////////////////////////// 267 268 // If LOGGING is not explicitly defined, default to enabled in debug mode 269 #if !defined(LOGGING) 270 #if defined(_DEBUG) && !defined(NDEBUG) 271 #define LOGGING 1 272 #else 273 #define LOGGING 0 274 #endif 275 #endif // !defined(LOGGING) 276 277 #ifndef LOG 278 #if LOGGING 279 280 // The following non-obvious technique for implementation of a 281 // conditional log stream was stolen from google3/base/logging.h. 282 283 // This class is used to explicitly ignore values in the conditional 284 // logging macros. This avoids compiler warnings like "value computed 285 // is not used" and "statement has no effect". 286 287 class LogMessageVoidify { 288 public: 289 LogMessageVoidify() { } 290 // This has to be an operator with a precedence lower than << but 291 // higher than ?: 292 void operator&(std::ostream&) { } 293 }; 294 295 #define LOG_SEVERITY_PRECONDITION(sev) \ 296 !(talk_base::LogMessage::Loggable(sev)) \ 297 ? (void) 0 \ 298 : talk_base::LogMessageVoidify() & 299 300 #define LOG(sev) \ 301 LOG_SEVERITY_PRECONDITION(talk_base::sev) \ 302 talk_base::LogMessage(__FILE__, __LINE__, talk_base::sev).stream() 303 304 // The _V version is for when a variable is passed in. It doesn't do the 305 // namespace concatination. 306 #define LOG_V(sev) \ 307 LOG_SEVERITY_PRECONDITION(sev) \ 308 talk_base::LogMessage(__FILE__, __LINE__, sev).stream() 309 310 // The _F version prefixes the message with the current function name. 311 #if (defined(__GNUC__) && defined(_DEBUG)) || defined(WANT_PRETTY_LOG_F) 312 #define LOG_F(sev) LOG(sev) << __PRETTY_FUNCTION__ << ": " 313 #else 314 #define LOG_F(sev) LOG(sev) << __FUNCTION__ << ": " 315 #endif 316 317 #define LOG_CHECK_LEVEL(sev) \ 318 talk_base::LogCheckLevel(talk_base::sev) 319 #define LOG_CHECK_LEVEL_V(sev) \ 320 talk_base::LogCheckLevel(sev) 321 inline bool LogCheckLevel(LoggingSeverity sev) { 322 return (LogMessage::GetMinLogSeverity() <= sev); 323 } 324 325 #define LOG_E(sev, ctx, err, ...) \ 326 LOG_SEVERITY_PRECONDITION(talk_base::sev) \ 327 talk_base::LogMessage(__FILE__, __LINE__, talk_base::sev, \ 328 talk_base::ERRCTX_ ## ctx, err , ##__VA_ARGS__) \ 329 .stream() 330 331 #else // !LOGGING 332 333 // Hopefully, the compiler will optimize away some of this code. 334 // Note: syntax of "1 ? (void)0 : LogMessage" was causing errors in g++, 335 // converted to "while (false)" 336 #define LOG(sev) \ 337 while (false)talk_base:: LogMessage(NULL, 0, talk_base::sev).stream() 338 #define LOG_V(sev) \ 339 while (false) talk_base::LogMessage(NULL, 0, sev).stream() 340 #define LOG_F(sev) LOG(sev) << __FUNCTION__ << ": " 341 #define LOG_CHECK_LEVEL(sev) \ 342 false 343 #define LOG_CHECK_LEVEL_V(sev) \ 344 false 345 346 #define LOG_E(sev, ctx, err, ...) \ 347 while (false) talk_base::LogMessage(__FILE__, __LINE__, talk_base::sev, \ 348 talk_base::ERRCTX_ ## ctx, err , ##__VA_ARGS__) \ 349 .stream() 350 351 #endif // !LOGGING 352 353 #define LOG_ERRNO_EX(sev, err) \ 354 LOG_E(sev, ERRNO, err) 355 #define LOG_ERRNO(sev) \ 356 LOG_ERRNO_EX(sev, errno) 357 358 #ifdef WIN32 359 #define LOG_GLE_EX(sev, err) \ 360 LOG_E(sev, HRESULT, err) 361 #define LOG_GLE(sev) \ 362 LOG_GLE_EX(sev, GetLastError()) 363 #define LOG_GLEM(sev, mod) \ 364 LOG_E(sev, HRESULT, GetLastError(), mod) 365 #define LOG_ERR_EX(sev, err) \ 366 LOG_GLE_EX(sev, err) 367 #define LOG_ERR(sev) \ 368 LOG_GLE(sev) 369 #define LAST_SYSTEM_ERROR \ 370 (::GetLastError()) 371 #elif POSIX 372 #define LOG_ERR_EX(sev, err) \ 373 LOG_ERRNO_EX(sev, err) 374 #define LOG_ERR(sev) \ 375 LOG_ERRNO(sev) 376 #define LAST_SYSTEM_ERROR \ 377 (errno) 378 #endif // WIN32 379 380 #define PLOG(sev, err) \ 381 LOG_ERR_EX(sev, err) 382 383 // TODO(?): Add an "assert" wrapper that logs in the same manner. 384 385 #endif // LOG 386 387 } // namespace talk_base 388 389 #endif // TALK_BASE_LOGGING_H_ 390