blob: 5824dc95695644f1e5c3b0eb7e22cc40d786fde5 [file] [log] [blame]
// Copyright 2018 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.
// Code for listening to logger service and dumping the logs.
// This implements LogListener interface for logger fidl @ //zircon/system/fidl/fuchsia-logger.
#include <memory>
#include <fbl/function.h>
#include <fbl/string.h>
#include <fbl/vector.h>
#include <lib/async-loop/cpp/loop.h>
#include <lib/async/cpp/wait.h>
#include <lib/fidl/cpp/message_buffer.h>
#include <lib/zx/channel.h>
#include <stdint.h>
// TODO(FIDL-182): Remove this once fixed.
typedef zx_handle_t fuchsia_logger_LogListener;
#include <fuchsia/logger/c/fidl.h>
#include <utility>
namespace runtests {
// Error while launching LogExporter.
enum ExporterLaunchError {
// Listens to channel messages, converts them fidl log object and writes them to
// passed file object.
// This implements LogListener fidl interface.
// Example:
// FILE* f = fopen("file", "w");
// zx::channel channel;
// //init above channel to link to logger service
// ...
// LogExporter l(std::move(channel), f);
// l->StartThread();
class LogExporter {
using ErrorHandler = fbl::Function<void(zx_status_t)>;
using FileErrorHandler = fbl::Function<void(const char* error)>;
// Creates object and starts listening for msgs on channel written by Log
// interface in logger fidl.
// |channel| channel to read log messages from.
// |output_file| file to write logs to.
LogExporter(zx::channel channel, FILE* output_file);
// Starts LogListener service on a seperate thread.
// Returns result of loop_.StartThread().
zx_status_t StartThread();
// Runs LogListener service until message loop is idle.
// Returns result of loop_.RunUntilIdle().
zx_status_t RunUntilIdle();
// Sets Error handler which would be called when there is an error
// while serving |channel_|. If an error occurs, the channel will close and
// the listener thread will stop.
void set_error_handler(ErrorHandler error_handler) {
error_handler_ = std::move(error_handler);
// Sets Error handler which would be called whenever there is an error
// writing to file. If an error occurs, the channel will close and the
// listener thread will stop.
void set_file_error_handler(FileErrorHandler error_handler) {
file_error_handler_ = std::move(error_handler);
// Keeps track of the count of dropped logs for a process.
struct DroppedLogs {
uint64_t pid;
uint32_t dropped_logs;
void OnHandleReady(async_dispatcher_t* dispatcher, async::WaitBase* wait, zx_status_t status,
const zx_packet_signal_t* signal);
// Decodes channel message and dispatches to correct handler.
zx_status_t ReadAndDispatchMessage(fidl::MessageBuffer* buffer);
// Implementation of LogListener Log method.
zx_status_t Log(fidl::Message message);
// Implementation of LogListener LogMany method.
zx_status_t LogMany(fidl::Message message);
// Helper method to log |message| to file.
int LogMessage(fuchsia_logger_LogMessage* message);
// Helper method to call |error_handler_|.
void NotifyError(zx_status_t error);
// Helper method to call |error_handler_|.
void NotifyFileError(const char* error);
// Helper method to write severity string.
int WriteSeverity(int32_t severity);
async::Loop loop_;
zx::channel channel_;
async::WaitMethod<LogExporter, &LogExporter::OnHandleReady> wait_;
ErrorHandler error_handler_;
FileErrorHandler file_error_handler_;
FILE* output_file_;
// Vector to keep track of dropped logs per pid
fbl::Vector<DroppedLogs> dropped_logs_;
// Launches Log Exporter.
// Starts message loop on a seperate thread.
// |syslog_path| file path where to write logs.
// |error| error to set in case of failure.
// Returns nullptr if it is not possible to launch Log Exporter.
std::unique_ptr<LogExporter> LaunchLogExporter(fbl::StringPiece syslog_path,
ExporterLaunchError* error);
} // namespace runtests