| // 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 <lib/syslog/cpp/macros.h> |
| #include <zircon/status.h> |
| |
| #include "log_listener_log_sink.h" |
| #include "log_listener_ostream.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 |