Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(760)

Unified Diff: base/logging.cc

Issue 2034393004: Allow multiple logging::LogMessage{Handler,Listener}s Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: address comments, deque for listeners, reentrant test Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: base/logging.cc
diff --git a/base/logging.cc b/base/logging.cc
index 0771b47c182e5c18c868f1124a0784bf411d74a9..6fc00675b9c021cbea36bd2402df81c0cabbfb62 100644
--- a/base/logging.cc
+++ b/base/logging.cc
@@ -49,6 +49,7 @@ typedef pthread_mutex_t* MutexHandle;
#include <algorithm>
#include <cstring>
#include <ctime>
+#include <deque>
#include <iomanip>
#include <ostream>
#include <string>
@@ -58,6 +59,7 @@ typedef pthread_mutex_t* MutexHandle;
#include "base/debug/alias.h"
#include "base/debug/debugger.h"
#include "base/debug/stack_trace.h"
+#include "base/lazy_instance.h"
#include "base/posix/eintr_wrapper.h"
#include "base/strings/string_piece.h"
#include "base/strings/string_util.h"
@@ -65,6 +67,7 @@ typedef pthread_mutex_t* MutexHandle;
#include "base/strings/sys_string_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "base/synchronization/lock_impl.h"
+#include "base/synchronization/read_write_lock.h"
#include "base/threading/platform_thread.h"
#include "base/vlog.h"
#if defined(OS_POSIX)
@@ -123,8 +126,17 @@ bool show_error_dialogs = false;
// An assert handler override specified by the client to be called instead of
// the debug message dialog and process termination.
LogAssertHandlerFunction log_assert_handler = nullptr;
-// A log message handler that gets notified of every log message we process.
-LogMessageHandlerFunction log_message_handler = nullptr;
+// Log message handlers that get notified of every log message we process.
+base::LazyInstance<std::deque<LogMessageHandler*>>::Leaky log_message_handlers =
+ LAZY_INSTANCE_INITIALIZER;
+base::LazyInstance<base::subtle::ReadWriteLock>::Leaky
+ log_message_handler_lock = LAZY_INSTANCE_INITIALIZER;
+// Log message listeners that get notified of every log message we process
+// before log message handlers.
+base::LazyInstance<std::deque<LogMessageListener*>>::Leaky
+ log_message_listeners = LAZY_INSTANCE_INITIALIZER;
+base::LazyInstance<base::subtle::ReadWriteLock>::Leaky
+ log_message_listener_lock = LAZY_INSTANCE_INITIALIZER;
// Helper functions to wrap platform differences.
@@ -342,6 +354,44 @@ void CloseLogFileUnlocked() {
} // namespace
+LogMessageHandler::LogMessageHandler() {
+ base::subtle::AutoWriteLock lock(log_message_handler_lock.Get());
+ log_message_handlers.Get().push_front(this);
+}
+
+LogMessageHandler::~LogMessageHandler() {
+ base::subtle::AutoWriteLock lock(log_message_handler_lock.Get());
+ auto& handlers = log_message_handlers.Get();
+ size_t count = handlers.size();
+ handlers.erase(std::remove(handlers.begin(), handlers.end(), this),
+ handlers.end());
+ DCHECK_EQ(count - 1, handlers.size());
+}
+
+size_t LogMessageHandlerCountForTesting() {
+ base::subtle::AutoReadLock lock(log_message_handler_lock.Get());
+ return log_message_handlers.Get().size();
+}
+
+LogMessageListener::LogMessageListener() {
Mark Mentovai 2016/11/14 14:40:43 So much duplication…
wychen 2016/11/18 21:13:59 No more. :)
+ base::subtle::AutoWriteLock lock(log_message_listener_lock.Get());
+ log_message_listeners.Get().push_front(this);
+}
+
+LogMessageListener::~LogMessageListener() {
+ base::subtle::AutoWriteLock lock(log_message_listener_lock.Get());
+ auto& listeners = log_message_listeners.Get();
+ size_t count = listeners.size();
+ listeners.erase(std::remove(listeners.begin(), listeners.end(), this),
+ listeners.end());
+ DCHECK_EQ(count - 1, listeners.size());
+}
+
+size_t LogMessageListenerCountForTesting() {
+ base::subtle::AutoReadLock lock(log_message_listener_lock.Get());
+ return log_message_listeners.Get().size();
+}
+
LoggingSettings::LoggingSettings()
: logging_dest(LOG_DEFAULT),
log_file(nullptr),
@@ -409,8 +459,17 @@ bool ShouldCreateLogMessage(int severity) {
// Return true here unless we know ~LogMessage won't do anything. Note that
// ~LogMessage writes to stderr if severity_ >= kAlwaysPrintErrorLevel, even
// when g_logging_destination is LOG_NONE.
- return g_logging_destination != LOG_NONE || log_message_handler ||
- severity >= kAlwaysPrintErrorLevel;
+ bool handlers_empty, listeners_empty;
+ {
+ base::subtle::AutoReadLock lock(log_message_handler_lock.Get());
+ handlers_empty = log_message_handlers.Get().empty();
+ }
+ {
+ base::subtle::AutoReadLock lock(log_message_listener_lock.Get());
+ listeners_empty = log_message_listeners.Get().empty();
+ }
+ return g_logging_destination != LOG_NONE || !handlers_empty ||
+ !listeners_empty || severity >= kAlwaysPrintErrorLevel;
}
int GetVlogVerbosity() {
@@ -443,14 +502,6 @@ void SetLogAssertHandler(LogAssertHandlerFunction handler) {
log_assert_handler = handler;
}
-void SetLogMessageHandler(LogMessageHandlerFunction handler) {
- log_message_handler = handler;
-}
-
-LogMessageHandlerFunction GetLogMessageHandler() {
- return log_message_handler;
-}
-
// Explicit instantiations for commonly used comparisons.
template std::string* MakeCheckOpString<int, int>(
const int&, const int&, const char* names);
@@ -537,12 +588,24 @@ LogMessage::~LogMessage() {
stream_ << std::endl;
std::string str_newline(stream_.str());
- // Give any log message handler first dibs on the message.
- if (log_message_handler &&
- log_message_handler(severity_, file_, line_,
- message_start_, str_newline)) {
- // The handler took care of it, no further processing.
- return;
+ {
+ base::subtle::AutoReadLock lock(log_message_listener_lock.Get());
+ // Broadcast to log message listeners first.
+ for (auto* listener : log_message_listeners.Get()) {
+ listener->OnMessage(severity_, file_, line_, message_start_, str_newline);
+ }
+ }
+
+ {
+ base::subtle::AutoReadLock lock(log_message_handler_lock.Get());
+ // Give log message handlers first dibs on the message.
+ for (auto* handler : log_message_handlers.Get()) {
+ if (handler->OnMessage(severity_, file_, line_, message_start_,
+ str_newline)) {
+ // The handler took care of it, no further processing.
+ return;
+ }
+ }
}
if ((g_logging_destination & LOG_TO_SYSTEM_DEBUG_LOG) != 0) {

Powered by Google App Engine
This is Rietveld 408576698