| // 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; } |