blob: 381b637e446ae4849ed0560b6643f9ab3b059c9b [file] [log] [blame]
// Copyright 2019 The Fuchsia 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 "log_listener.h"
#include <zircon/status.h>
#include "log_listener_log_sink.h"
#include "log_listener_ostream.h"
#include "src/lib/fxl/logging.h"
namespace netemul {
namespace internal {
/*
* LogListenerImpl
*
* public
*/
LogListenerImpl::LogListenerImpl(fidl::InterfaceRequest<fuchsia::logger::LogListenerSafe> request,
std::string prefix, async_dispatcher_t* dispatcher)
: binding_(this, std::move(request), dispatcher), prefix_(std::move(prefix)), dropped_logs_(0) {
binding_.set_error_handler([](zx_status_t status) {
FX_LOGS(ERROR) << "LogListenerImpl error: " << zx_status_get_string(status) << std::endl;
});
}
void LogListenerImpl::Log(fuchsia::logger::LogMessage m, LogCallback received) {
// Actually process the log
LogImpl(std::move(m));
received();
}
void LogListenerImpl::LogMany(std::vector<fuchsia::logger::LogMessage> ms,
LogManyCallback received) {
for (auto& m : ms) {
Log(std::move(m), []() {});
}
received();
}
void LogListenerImpl::Done() { return; }
} // namespace internal
/*
* LogListener
*
* public
*/
LogListener::LogListener(std::unique_ptr<fuchsia::logger::LogFilterOptions> log_filter_options,
fidl::InterfaceHandle<fuchsia::logger::LogListenerSafe> loglistener_handle,
std::shared_ptr<internal::LogListenerImpl> loglistener_impl)
: log_filter_options_(std::move(log_filter_options)),
loglistener_handle_(std::move(loglistener_handle)),
loglistener_impl_(std::move(loglistener_impl)) {}
bool LogListener::Bindable() const { return loglistener_handle_.is_valid(); }
void LogListener::BindToLogService(fuchsia::netemul::environment::ManagedEnvironment* env) {
// Connect to a remote that implements the fuchsia.logger.Log interface
// within |env|.
fuchsia::logger::LogPtr log_service;
log_service.set_error_handler([](zx_status_t status) {
FX_LOGS(ERROR) << "LogListenerImpl error: " << zx_status_get_string(status) << std::endl;
});
env->ConnectToService(fuchsia::logger::Log::Name_, log_service.NewRequest().TakeChannel());
log_service->ListenSafe(std::move(loglistener_handle_), std::move(log_filter_options_));
}
std::shared_ptr<internal::LogListenerImpl> LogListener::GetLogListenerImpl() const {
return loglistener_impl_;
}
std::unique_ptr<LogListener> LogListener::Create(
fuchsia::netemul::environment::LoggerOptions logger_options, const std::string& prefix,
async_dispatcher_t* dispatcher) {
if (!logger_options.has_enabled() || !logger_options.enabled()) {
return nullptr;
}
// Create an instance of the LogListenerSafe implementation
// and start listening for logs
fidl::InterfaceHandle<fuchsia::logger::LogListenerSafe> loglistener_h;
std::shared_ptr<internal::LogListenerImpl> impl;
if (logger_options.has_syslog_output() && logger_options.syslog_output()) {
// Create a LogListenerImpl that forwards logs to another LogSink
impl.reset(new internal::LogListenerLogSinkImpl(loglistener_h.NewRequest(), prefix,
zx::socket(), dispatcher));
} else {
// Create a LogListenerImpl that writes logs to stdout.
impl.reset(new internal::LogListenerOStreamImpl(loglistener_h.NewRequest(), prefix, &std::cout,
dispatcher));
}
if (!impl) {
FX_LOGS(ERROR) << "Failed to create a LogListenerImpl";
return nullptr;
}
std::unique_ptr<fuchsia::logger::LogFilterOptions> log_filter_options;
if (logger_options.has_filter_options()) {
log_filter_options =
std::make_unique<fuchsia::logger::LogFilterOptions>(logger_options.filter_options());
}
return std::make_unique<LogListener>(std::move(log_filter_options), std::move(loglistener_h),
std::move(impl));
}
} // namespace netemul