diff --git a/talk/app/webrtc/java/jni/peerconnection_jni.cc b/talk/app/webrtc/java/jni/peerconnection_jni.cc index 9e1ce74e1e..bf41119961 100644 --- a/talk/app/webrtc/java/jni/peerconnection_jni.cc +++ b/talk/app/webrtc/java/jni/peerconnection_jni.cc @@ -907,7 +907,10 @@ JOW(void, Logging_nativeEnableTracing)( } #endif } - rtc::LogMessage::LogToDebug(nativeSeverity); + if (nativeSeverity >= rtc::LS_SENSITIVE && nativeSeverity <= rtc::LS_ERROR) { + rtc::LogMessage::LogToDebug( + static_cast(nativeSeverity)); + } } JOW(void, PeerConnection_freePeerConnection)(JNIEnv*, jclass, jlong j_p) { diff --git a/talk/media/webrtc/webrtcvoiceengine_unittest.cc b/talk/media/webrtc/webrtcvoiceengine_unittest.cc index 8b65fbf50d..7d1fb500c4 100644 --- a/talk/media/webrtc/webrtcvoiceengine_unittest.cc +++ b/talk/media/webrtc/webrtcvoiceengine_unittest.cc @@ -3203,30 +3203,6 @@ TEST(WebRtcVoiceEngineTest, StartupShutdown) { engine.Terminate(); } -// Tests that the logging from the library is cleartext. -TEST(WebRtcVoiceEngineTest, DISABLED_HasUnencryptedLogging) { - cricket::WebRtcVoiceEngine engine; - rtc::scoped_ptr stream( - new rtc::MemoryStream); - size_t size = 0; - bool cleartext = true; - rtc::LogMessage::AddLogToStream(stream.get(), rtc::LS_VERBOSE); - engine.SetLogging(rtc::LS_VERBOSE, ""); - EXPECT_TRUE(engine.Init(rtc::Thread::Current())); - EXPECT_TRUE(stream->GetSize(&size)); - EXPECT_GT(size, 0U); - engine.Terminate(); - rtc::LogMessage::RemoveLogToStream(stream.get()); - const char* buf = stream->GetBuffer(); - for (size_t i = 0; i < size && cleartext; ++i) { - int ch = static_cast(buf[i]); - ASSERT_GE(ch, 0) << "Out of bounds character in WebRtc VoE log: " - << std::hex << ch; - cleartext = (isprint(ch) || isspace(ch)); - } - EXPECT_TRUE(cleartext); -} - // Tests that the library is configured with the codecs we want. TEST(WebRtcVoiceEngineTest, HasCorrectCodecs) { cricket::WebRtcVoiceEngine engine; diff --git a/webrtc/base/httpbase_unittest.cc b/webrtc/base/httpbase_unittest.cc index fd5f867331..d4dd7750a6 100644 --- a/webrtc/base/httpbase_unittest.cc +++ b/webrtc/base/httpbase_unittest.cc @@ -404,7 +404,7 @@ TEST_F(HttpBaseTest, SupportsReceiveViaStreamPull) { TEST_F(HttpBaseTest, DISABLED_AllowsCloseStreamBeforeDocumentIsComplete) { // TODO: Remove extra logging once test failure is understood - int old_sev = rtc::LogMessage::GetLogToDebug(); + LoggingSeverity old_sev = rtc::LogMessage::GetLogToDebug(); rtc::LogMessage::LogToDebug(LS_VERBOSE); diff --git a/webrtc/base/logging.cc b/webrtc/base/logging.cc index 2cf567c552..ea7c0ff00f 100644 --- a/webrtc/base/logging.cc +++ b/webrtc/base/logging.cc @@ -35,7 +35,7 @@ static const int kMaxLogLineSize = 1024 - 60; #include #include "webrtc/base/logging.h" -#include "webrtc/base/stream.h" +#include "webrtc/base/scoped_ptr.h" #include "webrtc/base/stringencode.h" #include "webrtc/base/stringutils.h" #include "webrtc/base/timeutils.h" @@ -73,24 +73,18 @@ std::string ErrorName(int err, const ConstantLabel * err_table) { // LogMessage ///////////////////////////////////////////////////////////////////////////// -const int LogMessage::NO_LOGGING = LS_ERROR + 1; - +// By default, release builds don't log, debug builds at info level #if _DEBUG -static const int LOG_DEFAULT = LS_INFO; +LoggingSeverity LogMessage::min_sev_ = LS_INFO; +LoggingSeverity LogMessage::dbg_sev_ = LS_INFO; #else // !_DEBUG -static const int LOG_DEFAULT = LogMessage::NO_LOGGING; +LoggingSeverity LogMessage::min_sev_ = LS_NONE; +LoggingSeverity LogMessage::dbg_sev_ = LS_NONE; #endif // !_DEBUG // Global lock for log subsystem, only needed to serialize access to streams_. CriticalSection LogMessage::crit_; -// By default, release builds don't log, debug builds at info level -int LogMessage::min_sev_ = LOG_DEFAULT; -int LogMessage::dbg_sev_ = LOG_DEFAULT; - -// Don't bother printing context for the ubiquitous INFO log messages -int LogMessage::ctx_sev_ = LS_WARNING; - // The list of logging streams currently configured. // Note: we explicitly do not clean this up, because of the uncertain ordering // of destructors at program exit. Let the person who sets the stream trigger @@ -121,12 +115,7 @@ LogMessage::LogMessage(const char* file, int line, LoggingSeverity sev, #if defined(WEBRTC_WIN) DWORD id = GetCurrentThreadId(); print_stream_ << "[" << std::hex << id << std::dec << "] "; -#endif // WEBRTC_WIN - } - - if (severity_ >= ctx_sev_) { - print_stream_ << Describe(sev) << "(" << DescribeFile(file) - << ":" << line << "): "; +#endif // WEBRTC_WIN } if (err_ctx != ERRCTX_NONE) { @@ -155,7 +144,7 @@ LogMessage::LogMessage(const char* file, int line, LoggingSeverity sev, } break; } -#endif // WEBRTC_WIN +#endif // WEBRTC_WIN #if defined(WEBRTC_MAC) && !defined(WEBRTC_IOS) case ERRCTX_OSSTATUS: { tmp << " " << nonnull(GetMacOSStatusErrorString(err), "Unknown error"); @@ -187,7 +176,7 @@ LogMessage::~LogMessage() { CritScope cs(&crit_); for (StreamList::iterator it = streams_.begin(); it != streams_.end(); ++it) { if (severity_ >= it->second) { - OutputToStream(it->first, str); + it->first->OnLogMessage(str); } } uint32 delay = TimeSince(before); @@ -213,10 +202,6 @@ uint32 LogMessage::WallClockStartTime() { return g_start_wallclock; } -void LogMessage::LogContext(int min_sev) { - ctx_sev_ = min_sev; -} - void LogMessage::LogThreads(bool on) { thread_ = on; } @@ -225,12 +210,12 @@ void LogMessage::LogTimestamps(bool on) { timestamp_ = on; } -void LogMessage::LogToDebug(int min_sev) { +void LogMessage::LogToDebug(LoggingSeverity min_sev) { dbg_sev_ = min_sev; UpdateMinLogSeverity(); } -void LogMessage::LogToStream(StreamInterface* stream, int min_sev) { +void LogMessage::LogToStream(LogSink* stream, LoggingSeverity min_sev) { CritScope cs(&crit_); // Discard and delete all previously installed streams for (StreamList::iterator it = streams_.begin(); it != streams_.end(); ++it) { @@ -243,9 +228,9 @@ void LogMessage::LogToStream(StreamInterface* stream, int min_sev) { } } -int LogMessage::GetLogToStream(StreamInterface* stream) { +int LogMessage::GetLogToStream(LogSink* stream) { CritScope cs(&crit_); - int sev = NO_LOGGING; + LoggingSeverity sev = LS_NONE; for (StreamList::iterator it = streams_.begin(); it != streams_.end(); ++it) { if (!stream || stream == it->first) { sev = std::min(sev, it->second); @@ -254,13 +239,13 @@ int LogMessage::GetLogToStream(StreamInterface* stream) { return sev; } -void LogMessage::AddLogToStream(StreamInterface* stream, int min_sev) { +void LogMessage::AddLogToStream(LogSink* stream, LoggingSeverity min_sev) { CritScope cs(&crit_); streams_.push_back(std::make_pair(stream, min_sev)); UpdateMinLogSeverity(); } -void LogMessage::RemoveLogToStream(StreamInterface* stream) { +void LogMessage::RemoveLogToStream(LogSink* stream) { CritScope cs(&crit_); for (StreamList::iterator it = streams_.begin(); it != streams_.end(); ++it) { if (stream == it->first) { @@ -271,48 +256,45 @@ void LogMessage::RemoveLogToStream(StreamInterface* stream) { UpdateMinLogSeverity(); } -void LogMessage::ConfigureLogging(const char* params, const char* filename) { - int current_level = LS_VERBOSE; - int debug_level = GetLogToDebug(); - int file_level = GetLogToStream(); +void LogMessage::ConfigureLogging(const char* params) { + LoggingSeverity current_level = LS_VERBOSE; + LoggingSeverity debug_level = GetLogToDebug(); std::vector tokens; tokenize(params, ' ', &tokens); - for (size_t i = 0; i < tokens.size(); ++i) { - if (tokens[i].empty()) + for (const std::string& token : tokens) { + if (token.empty()) continue; // Logging features - if (tokens[i] == "tstamp") { + if (token == "tstamp") { LogTimestamps(); - } else if (tokens[i] == "thread") { + } else if (token == "thread") { LogThreads(); // Logging levels - } else if (tokens[i] == "sensitive") { + } else if (token == "sensitive") { current_level = LS_SENSITIVE; - } else if (tokens[i] == "verbose") { + } else if (token == "verbose") { current_level = LS_VERBOSE; - } else if (tokens[i] == "info") { + } else if (token == "info") { current_level = LS_INFO; - } else if (tokens[i] == "warning") { + } else if (token == "warning") { current_level = LS_WARNING; - } else if (tokens[i] == "error") { + } else if (token == "error") { current_level = LS_ERROR; - } else if (tokens[i] == "none") { - current_level = NO_LOGGING; + } else if (token == "none") { + current_level = LS_NONE; // Logging targets - } else if (tokens[i] == "file") { - file_level = current_level; - } else if (tokens[i] == "debug") { + } else if (token == "debug") { debug_level = current_level; } } #if defined(WEBRTC_WIN) - if ((NO_LOGGING != debug_level) && !::IsDebuggerPresent()) { + if ((LS_NONE != debug_level) && !::IsDebuggerPresent()) { // First, attempt to attach to our parent's console... so if you invoke // from the command line, we'll see the output there. Otherwise, create // our own console window. @@ -331,69 +313,19 @@ void LogMessage::ConfigureLogging(const char* params, const char* filename) { ::AllocConsole(); } } -#endif // WEBRTC_WIN +#endif // WEBRTC_WIN LogToDebug(debug_level); - -#if !defined(__native_client__) // No logging to file in NaCl. - scoped_ptr stream; - if (NO_LOGGING != file_level) { - stream.reset(new FileStream); - if (!stream->Open(filename, "wb", NULL) || !stream->DisableBuffering()) { - stream.reset(); - } - } - - LogToStream(stream.release(), file_level); -#endif -} - -int LogMessage::ParseLogSeverity(const std::string& value) { - int level = NO_LOGGING; - if (value == "LS_SENSITIVE") { - level = LS_SENSITIVE; - } else if (value == "LS_VERBOSE") { - level = LS_VERBOSE; - } else if (value == "LS_INFO") { - level = LS_INFO; - } else if (value == "LS_WARNING") { - level = LS_WARNING; - } else if (value == "LS_ERROR") { - level = LS_ERROR; - } else if (isdigit(value[0])) { - level = atoi(value.c_str()); // NOLINT - } - return level; } void LogMessage::UpdateMinLogSeverity() { - int min_sev = dbg_sev_; + LoggingSeverity min_sev = dbg_sev_; for (StreamList::iterator it = streams_.begin(); it != streams_.end(); ++it) { min_sev = std::min(dbg_sev_, it->second); } min_sev_ = min_sev; } -const char* LogMessage::Describe(LoggingSeverity sev) { - switch (sev) { - case LS_SENSITIVE: return "Sensitive"; - case LS_VERBOSE: return "Verbose"; - case LS_INFO: return "Info"; - case LS_WARNING: return "Warning"; - case LS_ERROR: return "Error"; - default: return ""; - } -} - -const char* LogMessage::DescribeFile(const char* file) { - const char* end1 = ::strrchr(file, '/'); - const char* end2 = ::strrchr(file, '\\'); - if (!end1 && !end2) - return file; - else - return (end1 > end2) ? end1 + 1 : end2 + 1; -} - void LogMessage::OutputToDebug(const std::string& str, LoggingSeverity severity) { bool log_to_stderr = true; @@ -430,7 +362,7 @@ void LogMessage::OutputToDebug(const std::string& str, &written, 0); } } -#endif // WEBRTC_WIN +#endif // WEBRTC_WIN #if defined(WEBRTC_ANDROID) // Android's logging facility uses severity to log messages but we // need to map libjingle's severity levels to Android ones first. @@ -487,12 +419,6 @@ void LogMessage::OutputToDebug(const std::string& str, } } -void LogMessage::OutputToStream(StreamInterface* stream, - const std::string& str) { - // If write isn't fully successful, what are we going to do, log it? :) - stream->WriteAll(str.data(), str.size(), NULL, NULL); -} - ////////////////////////////////////////////////////////////////////// // Logging Helpers ////////////////////////////////////////////////////////////////////// diff --git a/webrtc/base/logging.h b/webrtc/base/logging.h index c1315aef59..2fb6f3ee7d 100644 --- a/webrtc/base/logging.h +++ b/webrtc/base/logging.h @@ -10,7 +10,7 @@ // LOG(...) an ostream target that can be used to send formatted // output to a variety of logging targets, such as debugger console, stderr, -// file, or any StreamInterface. +// or any LogSink. // The severity level passed as the first argument to the LOGging // functions is used as a filter, to limit the verbosity of the logging. // Static members of LogMessage documented below are used to control the @@ -59,8 +59,6 @@ namespace rtc { -class StreamInterface; - /////////////////////////////////////////////////////////////////////////////// // ConstantLabel can be used to easily generate string names from constant // values. This can be useful for logging descriptive names of error messages. @@ -96,10 +94,18 @@ std::string ErrorName(int err, const ConstantLabel* err_table); // in debug builds. // LS_WARNING: Something that may warrant investigation. // LS_ERROR: Something that should not have occurred. -enum LoggingSeverity { LS_SENSITIVE, LS_VERBOSE, LS_INFO, LS_WARNING, LS_ERROR, - INFO = LS_INFO, - WARNING = LS_WARNING, - LERROR = LS_ERROR }; +// LS_NONE: Don't log. +enum LoggingSeverity { + LS_SENSITIVE, + LS_VERBOSE, + LS_INFO, + LS_WARNING, + LS_ERROR, + LS_NONE, + INFO = LS_INFO, + WARNING = LS_WARNING, + LERROR = LS_ERROR +}; // LogErrorContext assists in interpreting the meaning of an error value. enum LogErrorContext { @@ -114,9 +120,16 @@ enum LogErrorContext { ERRCTX_OS = ERRCTX_OSSTATUS, // LOG_E(sev, OS, x) }; +// Virtual sink interface that can receive log messages. +class LogSink { + public: + LogSink() {} + virtual ~LogSink() {} + virtual void OnLogMessage(const std::string& message) = 0; +}; + class LogMessage { public: - static const int NO_LOGGING; static const uint32 WARN_SLOW_LOGS_DELAY = 50; // ms LogMessage(const char* file, int line, LoggingSeverity sev, @@ -138,9 +151,6 @@ class LogMessage { // epoch. static uint32 WallClockStartTime(); - // These are attributes which apply to all logging channels - // LogContext: Display the file and line number of the message - static void LogContext(int min_sev); // LogThreads: Display the thread identifier of the current thread static void LogThreads(bool on = true); // LogTimestamps: Display the elapsed time of the program @@ -148,8 +158,8 @@ class LogMessage { // These are the available logging channels // Debug: Debug console on Windows, otherwise stderr - static void LogToDebug(int min_sev); - static int GetLogToDebug() { return dbg_sev_; } + static void LogToDebug(LoggingSeverity min_sev); + static LoggingSeverity GetLogToDebug() { return dbg_sev_; } // Stream: Any non-blocking stream interface. LogMessage takes ownership of // the stream. Multiple streams may be specified by using AddLogToStream. @@ -158,10 +168,10 @@ class LogMessage { // GetLogToStream gets the severity for the specified stream, of if none // is specified, the minimum stream severity. // RemoveLogToStream removes the specified stream, without destroying it. - static void LogToStream(StreamInterface* stream, int min_sev); - static int GetLogToStream(StreamInterface* stream = NULL); - static void AddLogToStream(StreamInterface* stream, int min_sev); - static void RemoveLogToStream(StreamInterface* stream); + static void LogToStream(LogSink* stream, LoggingSeverity min_sev); + static int GetLogToStream(LogSink* stream = NULL); + static void AddLogToStream(LogSink* stream, LoggingSeverity min_sev); + static void RemoveLogToStream(LogSink* stream); // Testing against MinLogSeverity allows code to avoid potentially expensive // logging operations by pre-checking the logging level. @@ -171,26 +181,18 @@ class LogMessage { static bool IsDiagnosticMode() { return is_diagnostic_mode_; } // Parses the provided parameter stream to configure the options above. - // Useful for configuring logging from the command line. If file logging - // is enabled, it is output to the specified filename. - static void ConfigureLogging(const char* params, const char* filename); - - // Convert the string to a LS_ value; also accept numeric values. - static int ParseLogSeverity(const std::string& value); + // Useful for configuring logging from the command line. + static void ConfigureLogging(const char* params); private: - typedef std::list > StreamList; + typedef std::pair StreamAndSeverity; + typedef std::list StreamList; // Updates min_sev_ appropriately when debug sinks change. static void UpdateMinLogSeverity(); - // These assist in formatting some parts of the debug output. - static const char* Describe(LoggingSeverity sev); - static const char* DescribeFile(const char* file); - // These write out the actual log messages. static void OutputToDebug(const std::string& msg, LoggingSeverity severity_); - static void OutputToStream(StreamInterface* stream, const std::string& msg); // The ostream that buffers the formatted message before output std::ostringstream print_stream_; @@ -214,7 +216,7 @@ class LogMessage { // as a short-circuit in the logging macros to identify messages that won't // be logged. // ctx_sev_ is the minimum level at which file context is displayed - static int min_sev_, dbg_sev_, ctx_sev_; + static LoggingSeverity min_sev_, dbg_sev_, ctx_sev_; // The output streams and their associated severities static StreamList streams_; @@ -335,7 +337,7 @@ inline bool LogCheckLevel(LoggingSeverity sev) { LOG_ERRNO(sev) #define LAST_SYSTEM_ERROR \ (errno) -#endif // WEBRTC_WIN +#endif // WEBRTC_WIN #define PLOG(sev, err) \ LOG_ERR_EX(sev, err) diff --git a/webrtc/base/logging_unittest.cc b/webrtc/base/logging_unittest.cc index 7d7c97ec5e..db744b57bc 100644 --- a/webrtc/base/logging_unittest.cc +++ b/webrtc/base/logging_unittest.cc @@ -18,13 +18,35 @@ namespace rtc { +template +class LogSinkImpl + : public LogSink, + public Base { + public: + LogSinkImpl() {} + + // The non-const reference constructor is required because of StringStream. + // TODO(tommi): Fix StringStream to accept a pointer for non-const. + template + explicit LogSinkImpl(P& p) : Base(p) {} + + template + explicit LogSinkImpl(const P& p) : Base(p) {} + + private: + void OnLogMessage(const std::string& message) override { + static_cast(this)->WriteAll( + message.data(), message.size(), nullptr, nullptr); + } +}; + // Test basic logging operation. We should get the INFO log but not the VERBOSE. // We should restore the correct global state at the end. TEST(LogTest, SingleStream) { int sev = LogMessage::GetLogToStream(NULL); std::string str; - StringStream stream(str); + LogSinkImpl stream(str); LogMessage::AddLogToStream(&stream, LS_INFO); EXPECT_EQ(LS_INFO, LogMessage::GetLogToStream(&stream)); @@ -34,7 +56,7 @@ TEST(LogTest, SingleStream) { EXPECT_EQ(std::string::npos, str.find("VERBOSE")); LogMessage::RemoveLogToStream(&stream); - EXPECT_EQ(LogMessage::NO_LOGGING, LogMessage::GetLogToStream(&stream)); + EXPECT_EQ(LS_NONE, LogMessage::GetLogToStream(&stream)); EXPECT_EQ(sev, LogMessage::GetLogToStream(NULL)); } @@ -46,7 +68,7 @@ TEST(LogTest, MultipleStreams) { int sev = LogMessage::GetLogToStream(NULL); std::string str1, str2; - StringStream stream1(str1), stream2(str2); + LogSinkImpl stream1(str1), stream2(str2); LogMessage::AddLogToStream(&stream1, LS_INFO); LogMessage::AddLogToStream(&stream2, LS_VERBOSE); EXPECT_EQ(LS_INFO, LogMessage::GetLogToStream(&stream1)); @@ -62,8 +84,8 @@ TEST(LogTest, MultipleStreams) { LogMessage::RemoveLogToStream(&stream2); LogMessage::RemoveLogToStream(&stream1); - EXPECT_EQ(LogMessage::NO_LOGGING, LogMessage::GetLogToStream(&stream2)); - EXPECT_EQ(LogMessage::NO_LOGGING, LogMessage::GetLogToStream(&stream1)); + EXPECT_EQ(LS_NONE, LogMessage::GetLogToStream(&stream2)); + EXPECT_EQ(LS_NONE, LogMessage::GetLogToStream(&stream1)); EXPECT_EQ(sev, LogMessage::GetLogToStream(NULL)); } @@ -91,7 +113,7 @@ TEST(LogTest, MultipleThreads) { thread2.Start(); thread3.Start(); - NullStream stream1, stream2, stream3; + LogSinkImpl stream1, stream2, stream3; for (int i = 0; i < 1000; ++i) { LogMessage::AddLogToStream(&stream1, LS_INFO); LogMessage::AddLogToStream(&stream2, LS_VERBOSE); @@ -117,7 +139,7 @@ TEST(LogTest, Perf) { EXPECT_TRUE(Filesystem::GetTemporaryFolder(path, true, NULL)); path.SetPathname(Filesystem::TempFilename(path, "ut")); - FileStream stream; + LogSinkImpl stream; EXPECT_TRUE(stream.Open(path.pathname(), "wb", NULL)); stream.DisableBuffering(); LogMessage::AddLogToStream(&stream, LS_SENSITIVE); diff --git a/webrtc/base/unittest_main.cc b/webrtc/base/unittest_main.cc index c9864fe08b..e243c52e2c 100644 --- a/webrtc/base/unittest_main.cc +++ b/webrtc/base/unittest_main.cc @@ -51,7 +51,7 @@ int TestCrtReportHandler(int report_type, char* msg, int* retval) { return TRUE; } } -#endif // WEBRTC_WIN +#endif // WEBRTC_WIN int main(int argc, char** argv) { testing::InitGoogleTest(&argc, argv); @@ -75,7 +75,7 @@ int main(int argc, char** argv) { _crtBreakAlloc = FLAG_crt_break_alloc; } #endif // _DEBUG -#endif // WEBRTC_WIN +#endif // WEBRTC_WIN rtc::Filesystem::SetOrganizationName("google"); rtc::Filesystem::SetApplicationName("unittest"); @@ -83,7 +83,7 @@ int main(int argc, char** argv) { // By default, log timestamps. Allow overrides by used of a --log flag. rtc::LogMessage::LogTimestamps(); if (*FLAG_log != '\0') { - rtc::LogMessage::ConfigureLogging(FLAG_log, "unittest.log"); + rtc::LogMessage::ConfigureLogging(FLAG_log); } // Initialize SSL which are used by several tests. @@ -94,7 +94,7 @@ int main(int argc, char** argv) { rtc::CleanupSSL(); // clean up logging so we don't appear to leak memory. - rtc::LogMessage::ConfigureLogging("", ""); + rtc::LogMessage::ConfigureLogging(""); #if defined(WEBRTC_WIN) // Unhook crt function so that we don't ever log after statics have been