| // Copyright 2018 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "remoting/client/in_memory_log_handler.h" |
| |
| #include "base/check.h" |
| #include "base/containers/ring_buffer.h" |
| #include "base/logging.h" |
| #include "base/synchronization/lock.h" |
| |
| namespace remoting { |
| |
| namespace { |
| |
| constexpr size_t kMaxNumberOfLogs = 1000; |
| |
| struct LogHandlerContext { |
| base::Lock lock; |
| base::RingBuffer<std::string, kMaxNumberOfLogs> buffer; |
| }; |
| |
| // Leaky. |
| LogHandlerContext* g_log_handler_context = nullptr; |
| |
| bool HandleLogMessage(int severity, |
| const char* file, |
| int line, |
| size_t message_start, |
| const std::string& str) { |
| base::AutoLock auto_lock(g_log_handler_context->lock); |
| g_log_handler_context->buffer.SaveToBuffer(str); |
| |
| // Pass log messages through the default logging pipeline. |
| return false; |
| } |
| |
| } // namespace |
| |
| // static |
| void InMemoryLogHandler::Register() { |
| DCHECK(!g_log_handler_context); |
| DCHECK(!logging::GetLogMessageHandler()) |
| << "Log message handler has already been set."; |
| |
| g_log_handler_context = new LogHandlerContext(); |
| |
| base::AutoLock auto_lock(g_log_handler_context->lock); |
| logging::SetLogMessageHandler(&HandleLogMessage); |
| } |
| |
| // static |
| std::string InMemoryLogHandler::GetInMemoryLogs() { |
| std::string output; |
| |
| base::AutoLock auto_lock(g_log_handler_context->lock); |
| |
| for (auto iter = g_log_handler_context->buffer.Begin(); iter; ++iter) { |
| if (iter != g_log_handler_context->buffer.Begin()) { |
| output += '\n'; |
| } |
| // *iter returns a const std::string*. |
| output += **iter; |
| } |
| return output; |
| } |
| |
| } // namespace remoting |