blob: 783de1a1824629e6a21eaa7603a8ae8cc37e658b [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.
#include <lib/syslog/logger.h>
#include <lib/zx/socket.h>
#include "export.h"
#include "fx_logger.h"
#ifndef SYSLOG_STATIC
#include <fidl/fuchsia.logger/cpp/wire.h>
#include <lib/component/incoming/cpp/protocol.h>
#endif
SYSLOG_EXPORT
zx_status_t fx_logger_logf(fx_logger_t* logger, fx_log_severity_t severity, const char* tag,
const char* format, ...) {
if (logger == nullptr) {
return ZX_ERR_BAD_STATE;
}
va_list args;
va_start(args, format);
zx_status_t s = logger->VLogWrite(severity, tag, format, args);
va_end(args);
return s;
}
SYSLOG_EXPORT
zx_status_t fx_logger_logf_with_source(fx_logger_t* logger, fx_log_severity_t severity,
const char* tag, const char* file, int line,
const char* format, ...) {
if (!logger || !file || line <= 0) {
return ZX_ERR_INVALID_ARGS;
}
va_list args;
va_start(args, format);
zx_status_t s = logger->VLogWrite(severity, tag, format, args, file, line);
va_end(args);
return s;
}
SYSLOG_EXPORT
zx_status_t fx_logger_log(fx_logger_t* logger, fx_log_severity_t severity, const char* tag,
const char* msg) {
if (logger == nullptr) {
return ZX_ERR_BAD_STATE;
}
return logger->LogWrite(severity, tag, msg);
}
SYSLOG_EXPORT
zx_status_t fx_logger_log_with_source(fx_logger_t* logger, fx_log_severity_t severity,
const char* tag, const char* file, int line,
const char* msg) {
if (!logger || !file || line <= 0) {
return ZX_ERR_INVALID_ARGS;
}
return logger->LogWrite(severity, tag, msg, file, line);
}
SYSLOG_EXPORT
zx_status_t fx_logger_logvf(fx_logger_t* logger, fx_log_severity_t severity, const char* tag,
const char* format, va_list args) {
if (logger == nullptr) {
return ZX_ERR_BAD_STATE;
}
return logger->VLogWrite(severity, tag, format, args);
}
SYSLOG_EXPORT
zx_status_t fx_logger_logvf_with_source(fx_logger_t* logger, fx_log_severity_t severity,
const char* tag, const char* file, int line,
const char* format, va_list args) {
if (!logger || !file || line <= 0) {
return ZX_ERR_INVALID_ARGS;
}
return logger->VLogWrite(severity, tag, format, args, file, line);
}
SYSLOG_EXPORT
fx_log_severity_t fx_logger_get_min_severity(fx_logger_t* logger) {
if (logger == nullptr) {
return FX_LOG_FATAL;
}
return logger->GetSeverity();
}
SYSLOG_EXPORT
zx_status_t fx_logger_set_min_severity(fx_logger_t* logger, fx_log_severity_t severity) {
return logger->SetSeverity(severity);
}
SYSLOG_EXPORT
zx_status_t fx_logger_get_connection_status(fx_logger_t* logger) {
return logger->GetLogConnectionStatus();
}
SYSLOG_EXPORT
void fx_logger_set_connection(fx_logger_t* logger, zx_handle_t handle) {
return logger->SetLogConnection(handle);
}
SYSLOG_EXPORT
void fx_logger_activate_fallback(fx_logger_t* logger, int fallback_fd) {
logger->ActivateFallback(fallback_fd);
}
SYSLOG_EXPORT
zx_status_t fx_logger_reconfigure(fx_logger_t* logger, const fx_logger_config_t* config) {
if (!config) {
return ZX_ERR_INVALID_ARGS;
}
return logger->Reconfigure(config, false);
}
SYSLOG_EXPORT
zx_status_t fx_logger_reconfigure_structured(fx_logger_t* logger,
const fx_logger_config_t* config) {
return logger->Reconfigure(config, true);
}
SYSLOG_EXPORT
zx_status_t fx_logger_create_internal(const fx_logger_config_t* config, fx_logger_t** out_logger) {
// TODO(https://fxbug.dev/42144753): Share the input checks and handle closing logic with
// fx_logger::Reconfigure().
if (!config || !out_logger) {
return ZX_ERR_INVALID_ARGS;
}
if ((config->num_tags > FX_LOG_MAX_TAGS) ||
#ifndef SYSLOG_STATIC
(config->log_sink_channel != ZX_HANDLE_INVALID &&
config->log_sink_socket != ZX_HANDLE_INVALID)
#else
// |log_sink_channel| is not supported by SYSLOG_STATIC.
config->log_sink_channel != ZX_HANDLE_INVALID
#endif
) {
if (config->log_sink_channel != ZX_HANDLE_INVALID) {
zx_handle_close(config->log_sink_channel);
}
if (config->log_sink_socket != ZX_HANDLE_INVALID) {
zx_handle_close(config->log_sink_socket);
}
return ZX_ERR_INVALID_ARGS;
}
bool is_structured = false;
auto c = *config;
// In the SYSLOG_STATIC mode, we cannot connect to the logging service. We
// should continue to instantiate the logger (which defaults to using stderr)
// and the client can provide the appropriate channel / fd later.
#ifndef SYSLOG_STATIC
if (config->log_sink_channel == ZX_HANDLE_INVALID &&
config->log_sink_socket == ZX_HANDLE_INVALID) {
zx::result socket = []() -> zx::result<zx::socket> {
zx::result logger = component::Connect<fuchsia_logger::LogSink>();
if (logger.is_error()) {
return logger.take_error();
}
zx::socket local, remote;
if (zx_status_t status = zx::socket::create(ZX_SOCKET_DATAGRAM, &local, &remote);
status != ZX_OK) {
return zx::error(status);
}
const fidl::Status result =
fidl::WireCall(logger.value())->ConnectStructured(std::move(remote));
if (!result.ok()) {
return zx::error(result.status());
}
return zx::ok(std::move(local));
}();
if (socket.is_ok()) {
c.log_sink_socket = socket.value().release();
is_structured = true;
}
}
#endif
*out_logger = new fx_logger(&c, is_structured);
return ZX_OK;
}
// Retrieves the tag at the specified index or nullptr if no
// such tag exists.
SYSLOG_EXPORT
void fx_logger_get_tags(fx_logger_t* logger, void (*callback)(void* context, const char* tag),
void* context) {
logger->GetTags([=](const fbl::String& tag) { callback(context, tag.c_str()); });
}
SYSLOG_EXPORT
zx_status_t fx_logger_create(const fx_logger_config_t* config, fx_logger_t** out_logger) {
return fx_logger_create_internal(config, out_logger);
}
SYSLOG_EXPORT
void fx_logger_destroy(fx_logger_t* logger) { delete logger; }