blob: b11e599a8ce24ae12e5773deb0c9143e0f3b8ad8 [file] [log] [blame]
// Copyright 2016 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 <chrono>
#include "mojo/public/cpp/application/connect.h"
#include "mojo/services/flog/cpp/flog.h"
namespace mojo {
namespace flog {
// static
void Flog::Initialize(Shell* shell, const std::string& label) {
MOJO_DCHECK(!logger_);
FlogServicePtr flog_service;
ConnectToService(shell, "mojo:flog", GetProxy(&flog_service));
// TODO(dalesat): Need a thread-safe proxy.
FlogLoggerPtr flog_logger;
flog_service->CreateLogger(GetProxy(&flog_logger), label);
logger_ = flog_logger.Pass();
fallback_logger_ = Environment::GetDefaultLogger();
Environment::SetDefaultLogger(&kMojoLogger);
}
// static
void Flog::LogChannelCreation(uint32_t channel_id,
const char* channel_type_name,
uint64_t subject_address) {
if (!logger_) {
return;
}
logger_->LogChannelCreation(GetTime(), channel_id, channel_type_name,
subject_address);
}
// static
void Flog::LogChannelMessage(uint32_t channel_id, Message* message) {
if (!logger_) {
return;
}
Array<uint8_t> array = Array<uint8_t>::New(message->data_num_bytes());
memcpy(array.data(), message->data(), message->data_num_bytes());
logger_->LogChannelMessage(GetTime(), channel_id, array.Pass());
}
// static
void Flog::LogChannelDeletion(uint32_t channel_id) {
if (!logger_) {
return;
}
logger_->LogChannelDeletion(GetTime(), channel_id);
}
// static
void Flog::LogMojoLoggerMessage(MojoLogLevel log_level,
const char* source_file,
uint32_t source_line,
const char* message) {
if (!logger_ || log_level < GetMinimumMojoLogLevel()) {
return;
}
logger_->LogMojoLoggerMessage(GetTime(), log_level, message, source_file,
source_line);
if (log_level >= MOJO_LOG_LEVEL_FATAL) {
abort();
}
}
// static
MojoLogLevel Flog::GetMinimumMojoLogLevel() {
MOJO_DCHECK(fallback_logger_ != nullptr);
return fallback_logger_->GetMinimumLogLevel();
}
// static
void Flog::SetMinimumMojoLogLevel(MojoLogLevel level) {
MOJO_DCHECK(fallback_logger_ != nullptr);
fallback_logger_->SetMinimumLogLevel(level);
}
// static
uint64_t Flog::GetTime() {
return std::chrono::duration_cast<std::chrono::microseconds>(
std::chrono::system_clock::now().time_since_epoch())
.count();
}
// static
const MojoLogger Flog::kMojoLogger = {
&LogMojoLoggerMessage, &GetMinimumMojoLogLevel, &SetMinimumMojoLogLevel};
// static
std::atomic_ulong Flog::last_allocated_channel_id_;
// static
FlogLoggerPtr Flog::logger_;
// static
const MojoLogger* Flog::fallback_logger_;
FlogChannel::FlogChannel(const char* channel_type_name,
uint64_t subject_address)
: id_(Flog::AllocateChannelId()) {
Flog::LogChannelCreation(id_, channel_type_name, subject_address);
}
FlogChannel::~FlogChannel() {
Flog::LogChannelDeletion(id_);
}
bool FlogChannel::Accept(Message* message) {
Flog::LogChannelMessage(id_, message);
return true;
}
bool FlogChannel::AcceptWithResponder(Message* message,
MessageReceiver* responder) {
MOJO_DCHECK(false) << "Flog doesn't support messages with responses";
abort();
}
} // namespace flog
} // namespace mojo