10e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org/* 20e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * libjingle 30e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * Copyright 2004--2005, Google Inc. 40e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * 50e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * Redistribution and use in source and binary forms, with or without 60e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * modification, are permitted provided that the following conditions are met: 70e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * 80e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * 1. Redistributions of source code must retain the above copyright notice, 90e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * this list of conditions and the following disclaimer. 100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * 2. Redistributions in binary form must reproduce the above copyright notice, 110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * this list of conditions and the following disclaimer in the documentation 120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * and/or other materials provided with the distribution. 130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * 3. The name of the author may not be used to endorse or promote products 140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * derived from this software without specific prior written permission. 150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * 160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org */ 270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// LOG(...) an ostream target that can be used to send formatted 290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// output to a variety of logging targets, such as debugger console, stderr, 300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// file, or any StreamInterface. 310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// The severity level passed as the first argument to the LOGging 320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// functions is used as a filter, to limit the verbosity of the logging. 330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// Static members of LogMessage documented below are used to control the 340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// verbosity and target of the output. 350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// There are several variations on the LOG macro which facilitate logging 360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// of common error conditions, detailed below. 370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// LOG(sev) logs the given stream at severity "sev", which must be a 390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// compile-time constant of the LoggingSeverity type, without the namespace 400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// prefix. 410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// LOG_V(sev) Like LOG(), but sev is a run-time variable of the LoggingSeverity 420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// type (basically, it just doesn't prepend the namespace). 430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// LOG_F(sev) Like LOG(), but includes the name of the current function. 44861d07361a4559a72e96236f27b758a56f6f59f0wu@webrtc.org// LOG_T(sev) Like LOG(), but includes the this pointer. 45861d07361a4559a72e96236f27b758a56f6f59f0wu@webrtc.org// LOG_T_F(sev) Like LOG_F(), but includes the this pointer. 460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// LOG_GLE(M)(sev [, mod]) attempt to add a string description of the 470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// HRESULT returned by GetLastError. The "M" variant allows searching of a 480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// DLL's string table for the error description. 490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// LOG_ERRNO(sev) attempts to add a string description of an errno-derived 500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// error. errno and associated facilities exist on both Windows and POSIX, 510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// but on Windows they only apply to the C/C++ runtime. 520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// LOG_ERR(sev) is an alias for the platform's normal error system, i.e. _GLE on 530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// Windows and _ERRNO on POSIX. 540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// (The above three also all have _EX versions that let you specify the error 550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// code, rather than using the last one.) 560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// LOG_E(sev, ctx, err, ...) logs a detailed error interpreted using the 570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// specified context. 580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// LOG_CHECK_LEVEL(sev) (and LOG_CHECK_LEVEL_V(sev)) can be used as a test 590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// before performing expensive or sensitive operations whose sole purpose is 600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// to output logging data at the desired level. 610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// Lastly, PLOG(sev, err) is an alias for LOG_ERR_EX. 620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#ifndef TALK_BASE_LOGGING_H_ 640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#define TALK_BASE_LOGGING_H_ 650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#ifdef HAVE_CONFIG_H 670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "config.h" // NOLINT 680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#endif 690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include <list> 710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include <sstream> 720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include <string> 730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include <utility> 740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "talk/base/basictypes.h" 750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "talk/base/criticalsection.h" 760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgnamespace talk_base { 780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgclass StreamInterface; 800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org/////////////////////////////////////////////////////////////////////////////// 820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// ConstantLabel can be used to easily generate string names from constant 830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// values. This can be useful for logging descriptive names of error messages. 840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// Usage: 850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// const ConstantLabel LIBRARY_ERRORS[] = { 860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// KLABEL(SOME_ERROR), 870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// KLABEL(SOME_OTHER_ERROR), 880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// ... 890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// LASTLABEL 900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// } 910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// 920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// int err = LibraryFunc(); 930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// LOG(LS_ERROR) << "LibraryFunc returned: " 940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// << ErrorName(err, LIBRARY_ERRORS); 950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgstruct ConstantLabel { int value; const char * label; }; 970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#define KLABEL(x) { x, #x } 980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#define TLABEL(x, y) { x, y } 990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#define LASTLABEL { 0, 0 } 1000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 1010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgconst char * FindLabel(int value, const ConstantLabel entries[]); 1020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgstd::string ErrorName(int err, const ConstantLabel* err_table); 1030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 1040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org////////////////////////////////////////////////////////////////////// 1050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 1060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// Note that the non-standard LoggingSeverity aliases exist because they are 1070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// still in broad use. The meanings of the levels are: 1080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// LS_SENSITIVE: Information which should only be logged with the consent 1090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// of the user, due to privacy concerns. 1100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// LS_VERBOSE: This level is for data which we do not want to appear in the 1110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// normal debug log, but should appear in diagnostic logs. 1120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// LS_INFO: Chatty level used in debugging for all sorts of things, the default 1130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// in debug builds. 1140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// LS_WARNING: Something that may warrant investigation. 1150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// LS_ERROR: Something that should not have occurred. 1160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgenum LoggingSeverity { LS_SENSITIVE, LS_VERBOSE, LS_INFO, LS_WARNING, LS_ERROR, 1170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org INFO = LS_INFO, 1180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org WARNING = LS_WARNING, 1190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LERROR = LS_ERROR }; 1200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 1210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// LogErrorContext assists in interpreting the meaning of an error value. 1220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgenum LogErrorContext { 1230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org ERRCTX_NONE, 1240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org ERRCTX_ERRNO, // System-local errno 1250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org ERRCTX_HRESULT, // Windows HRESULT 1260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org ERRCTX_OSSTATUS, // MacOS OSStatus 1270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 1280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Abbreviations for LOG_E macro 1290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org ERRCTX_EN = ERRCTX_ERRNO, // LOG_E(sev, EN, x) 1300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org ERRCTX_HR = ERRCTX_HRESULT, // LOG_E(sev, HR, x) 1310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org ERRCTX_OS = ERRCTX_OSSTATUS, // LOG_E(sev, OS, x) 1320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}; 1330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 1340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgclass LogMessage { 1350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org public: 1360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org static const int NO_LOGGING; 1370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org static const uint32 WARN_SLOW_LOGS_DELAY = 50; // ms 1380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 1390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LogMessage(const char* file, int line, LoggingSeverity sev, 1400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LogErrorContext err_ctx = ERRCTX_NONE, int err = 0, 1410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org const char* module = NULL); 1420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org ~LogMessage(); 1430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 1440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org static inline bool Loggable(LoggingSeverity sev) { return (sev >= min_sev_); } 1450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org std::ostream& stream() { return print_stream_; } 1460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 1470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Returns the time at which this function was called for the first time. 1480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // The time will be used as the logging start time. 1490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // If this is not called externally, the LogMessage ctor also calls it, in 1500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // which case the logging start time will be the time of the first LogMessage 1510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // instance is created. 1520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org static uint32 LogStartTime(); 1530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 1540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Returns the wall clock equivalent of |LogStartTime|, in seconds from the 1550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // epoch. 1560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org static uint32 WallClockStartTime(); 1570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 1580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // These are attributes which apply to all logging channels 1590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // LogContext: Display the file and line number of the message 1600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org static void LogContext(int min_sev); 1610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // LogThreads: Display the thread identifier of the current thread 1620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org static void LogThreads(bool on = true); 1630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // LogTimestamps: Display the elapsed time of the program 1640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org static void LogTimestamps(bool on = true); 1650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 1660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // These are the available logging channels 1670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Debug: Debug console on Windows, otherwise stderr 1680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org static void LogToDebug(int min_sev); 1690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org static int GetLogToDebug() { return dbg_sev_; } 1700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 1710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Stream: Any non-blocking stream interface. LogMessage takes ownership of 1720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // the stream. Multiple streams may be specified by using AddLogToStream. 1730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // LogToStream is retained for backwards compatibility; when invoked, it 1740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // will discard any previously set streams and install the specified stream. 1750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // GetLogToStream gets the severity for the specified stream, of if none 1760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // is specified, the minimum stream severity. 1770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // RemoveLogToStream removes the specified stream, without destroying it. 1780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org static void LogToStream(StreamInterface* stream, int min_sev); 1790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org static int GetLogToStream(StreamInterface* stream = NULL); 1800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org static void AddLogToStream(StreamInterface* stream, int min_sev); 1810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org static void RemoveLogToStream(StreamInterface* stream); 1820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 1830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Testing against MinLogSeverity allows code to avoid potentially expensive 1840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // logging operations by pre-checking the logging level. 1850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org static int GetMinLogSeverity() { return min_sev_; } 1860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 1870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org static void SetDiagnosticMode(bool f) { is_diagnostic_mode_ = f; } 1880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org static bool IsDiagnosticMode() { return is_diagnostic_mode_; } 1890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 1900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Parses the provided parameter stream to configure the options above. 1910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Useful for configuring logging from the command line. If file logging 1920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // is enabled, it is output to the specified filename. 1930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org static void ConfigureLogging(const char* params, const char* filename); 1940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 1950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Convert the string to a LS_ value; also accept numeric values. 1960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org static int ParseLogSeverity(const std::string& value); 1970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 1980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org private: 1990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org typedef std::list<std::pair<StreamInterface*, int> > StreamList; 2000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 2010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Updates min_sev_ appropriately when debug sinks change. 2020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org static void UpdateMinLogSeverity(); 2030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 2040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // These assist in formatting some parts of the debug output. 2050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org static const char* Describe(LoggingSeverity sev); 2060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org static const char* DescribeFile(const char* file); 2070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 2080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // These write out the actual log messages. 2090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org static void OutputToDebug(const std::string& msg, LoggingSeverity severity_); 2100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org static void OutputToStream(StreamInterface* stream, const std::string& msg); 2110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 2120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // The ostream that buffers the formatted message before output 2130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org std::ostringstream print_stream_; 2140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 2150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // The severity level of this message 2160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LoggingSeverity severity_; 2170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 2180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // String data generated in the constructor, that should be appended to 2190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // the message before output. 2200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org std::string extra_; 2210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 2220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // If time it takes to write to stream is more than this, log one 2230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // additional warning about it. 2240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org uint32 warn_slow_logs_delay_; 2250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 2260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Global lock for the logging subsystem 2270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org static CriticalSection crit_; 2280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 2290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // dbg_sev_ is the thresholds for those output targets 2300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // min_sev_ is the minimum (most verbose) of those levels, and is used 2310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // as a short-circuit in the logging macros to identify messages that won't 2320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // be logged. 2330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // ctx_sev_ is the minimum level at which file context is displayed 2340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org static int min_sev_, dbg_sev_, ctx_sev_; 2350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 2360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // The output streams and their associated severities 2370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org static StreamList streams_; 2380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 2390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Flags for formatting options 2400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org static bool thread_, timestamp_; 2410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 2420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // are we in diagnostic mode (as defined by the app)? 2430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org static bool is_diagnostic_mode_; 2440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 2450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org DISALLOW_EVIL_CONSTRUCTORS(LogMessage); 2460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}; 2470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 2480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org////////////////////////////////////////////////////////////////////// 2490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// Logging Helpers 2500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org////////////////////////////////////////////////////////////////////// 2510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 2520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgclass LogMultilineState { 2530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org public: 2540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org size_t unprintable_count_[2]; 2550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LogMultilineState() { 2560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org unprintable_count_[0] = unprintable_count_[1] = 0; 2570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 2580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}; 2590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 2600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// When possible, pass optional state variable to track various data across 2610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// multiple calls to LogMultiline. Otherwise, pass NULL. 2620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid LogMultiline(LoggingSeverity level, const char* label, bool input, 2630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org const void* data, size_t len, bool hex_mode, 2640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LogMultilineState* state); 2650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 2660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org////////////////////////////////////////////////////////////////////// 2670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// Macros which automatically disable logging when LOGGING == 0 2680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org////////////////////////////////////////////////////////////////////// 2690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 2700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// If LOGGING is not explicitly defined, default to enabled in debug mode 2710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#if !defined(LOGGING) 2720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#if defined(_DEBUG) && !defined(NDEBUG) 2730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#define LOGGING 1 2740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#else 2750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#define LOGGING 0 2760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#endif 2770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#endif // !defined(LOGGING) 2780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 2790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#ifndef LOG 2800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#if LOGGING 2810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 2820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// The following non-obvious technique for implementation of a 2830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// conditional log stream was stolen from google3/base/logging.h. 2840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 2850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// This class is used to explicitly ignore values in the conditional 2860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// logging macros. This avoids compiler warnings like "value computed 2870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// is not used" and "statement has no effect". 2880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 2890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgclass LogMessageVoidify { 2900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org public: 2910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LogMessageVoidify() { } 2920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // This has to be an operator with a precedence lower than << but 2930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // higher than ?: 2940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org void operator&(std::ostream&) { } 2950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}; 2960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 2970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#define LOG_SEVERITY_PRECONDITION(sev) \ 2980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org !(talk_base::LogMessage::Loggable(sev)) \ 2990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org ? (void) 0 \ 3000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org : talk_base::LogMessageVoidify() & 3010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 3020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#define LOG(sev) \ 3030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG_SEVERITY_PRECONDITION(talk_base::sev) \ 3040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org talk_base::LogMessage(__FILE__, __LINE__, talk_base::sev).stream() 3050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 3060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// The _V version is for when a variable is passed in. It doesn't do the 3070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// namespace concatination. 3080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#define LOG_V(sev) \ 3090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG_SEVERITY_PRECONDITION(sev) \ 3100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org talk_base::LogMessage(__FILE__, __LINE__, sev).stream() 3110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 3120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// The _F version prefixes the message with the current function name. 3130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#if (defined(__GNUC__) && defined(_DEBUG)) || defined(WANT_PRETTY_LOG_F) 3140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#define LOG_F(sev) LOG(sev) << __PRETTY_FUNCTION__ << ": " 315d1f631d5ec5c25dd0a63ed70d0ffa66037d8aa6awu@webrtc.org#define LOG_T_F(sev) LOG(sev) << this << ": " << __PRETTY_FUNCTION__ << ": " 3160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#else 3170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#define LOG_F(sev) LOG(sev) << __FUNCTION__ << ": " 318d1f631d5ec5c25dd0a63ed70d0ffa66037d8aa6awu@webrtc.org#define LOG_T_F(sev) LOG(sev) << this << ": " << __FUNCTION__ << ": " 3190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#endif 3200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 3210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#define LOG_CHECK_LEVEL(sev) \ 3220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org talk_base::LogCheckLevel(talk_base::sev) 3230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#define LOG_CHECK_LEVEL_V(sev) \ 3240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org talk_base::LogCheckLevel(sev) 3250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orginline bool LogCheckLevel(LoggingSeverity sev) { 3260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return (LogMessage::GetMinLogSeverity() <= sev); 3270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 3280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 3290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#define LOG_E(sev, ctx, err, ...) \ 3300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG_SEVERITY_PRECONDITION(talk_base::sev) \ 3310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org talk_base::LogMessage(__FILE__, __LINE__, talk_base::sev, \ 3320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org talk_base::ERRCTX_ ## ctx, err , ##__VA_ARGS__) \ 3330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org .stream() 3340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 335861d07361a4559a72e96236f27b758a56f6f59f0wu@webrtc.org#define LOG_T(sev) LOG(sev) << this << ": " 336861d07361a4559a72e96236f27b758a56f6f59f0wu@webrtc.org 3370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#else // !LOGGING 3380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 3390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// Hopefully, the compiler will optimize away some of this code. 3400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// Note: syntax of "1 ? (void)0 : LogMessage" was causing errors in g++, 3410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// converted to "while (false)" 3420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#define LOG(sev) \ 3430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org while (false)talk_base:: LogMessage(NULL, 0, talk_base::sev).stream() 3440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#define LOG_V(sev) \ 3450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org while (false) talk_base::LogMessage(NULL, 0, sev).stream() 3460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#define LOG_F(sev) LOG(sev) << __FUNCTION__ << ": " 3470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#define LOG_CHECK_LEVEL(sev) \ 3480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org false 3490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#define LOG_CHECK_LEVEL_V(sev) \ 3500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org false 3510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 3520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#define LOG_E(sev, ctx, err, ...) \ 3530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org while (false) talk_base::LogMessage(__FILE__, __LINE__, talk_base::sev, \ 3540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org talk_base::ERRCTX_ ## ctx, err , ##__VA_ARGS__) \ 3550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org .stream() 3560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 357861d07361a4559a72e96236f27b758a56f6f59f0wu@webrtc.org#define LOG_T(sev) LOG(sev) << this << ": " 358d1f631d5ec5c25dd0a63ed70d0ffa66037d8aa6awu@webrtc.org#define LOG_T_F(sev) LOG(sev) << this << ": " << __FUNCTION__ << 3590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#endif // !LOGGING 3600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 3610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#define LOG_ERRNO_EX(sev, err) \ 3620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG_E(sev, ERRNO, err) 3630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#define LOG_ERRNO(sev) \ 3640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG_ERRNO_EX(sev, errno) 3650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 3660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#ifdef WIN32 3670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#define LOG_GLE_EX(sev, err) \ 3680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG_E(sev, HRESULT, err) 3690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#define LOG_GLE(sev) \ 3700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG_GLE_EX(sev, GetLastError()) 3710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#define LOG_GLEM(sev, mod) \ 3720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG_E(sev, HRESULT, GetLastError(), mod) 3730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#define LOG_ERR_EX(sev, err) \ 3740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG_GLE_EX(sev, err) 3750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#define LOG_ERR(sev) \ 3760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG_GLE(sev) 3770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#define LAST_SYSTEM_ERROR \ 3780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org (::GetLastError()) 3798485ec698cd13d65354e2f81132b5763a3d216a4henrika@webrtc.org#elif __native_client__ 3808485ec698cd13d65354e2f81132b5763a3d216a4henrika@webrtc.org#define LOG_ERR_EX(sev, err) \ 3818485ec698cd13d65354e2f81132b5763a3d216a4henrika@webrtc.org LOG(sev) 3828485ec698cd13d65354e2f81132b5763a3d216a4henrika@webrtc.org#define LOG_ERR(sev) \ 3838485ec698cd13d65354e2f81132b5763a3d216a4henrika@webrtc.org LOG(sev) 3848485ec698cd13d65354e2f81132b5763a3d216a4henrika@webrtc.org#define LAST_SYSTEM_ERROR \ 3858485ec698cd13d65354e2f81132b5763a3d216a4henrika@webrtc.org (0) 3860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#elif POSIX 3870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#define LOG_ERR_EX(sev, err) \ 3880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG_ERRNO_EX(sev, err) 3890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#define LOG_ERR(sev) \ 3900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG_ERRNO(sev) 3910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#define LAST_SYSTEM_ERROR \ 3920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org (errno) 3930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#endif // WIN32 3940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 3950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#define PLOG(sev, err) \ 3960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG_ERR_EX(sev, err) 3970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 3980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// TODO(?): Add an "assert" wrapper that logs in the same manner. 3990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 4000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#endif // LOG 4010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 4020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} // namespace talk_base 4030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 4040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#endif // TALK_BASE_LOGGING_H_ 405