blob: be8488ab65eaa78084b6c2936f7d4508215439e5 [file] [log] [blame]
// 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