| // 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. |
| |
| #ifndef ZIRCON_SYSTEM_ULIB_SYSLOG_FX_LOGGER_H_ |
| #define ZIRCON_SYSTEM_ULIB_SYSLOG_FX_LOGGER_H_ |
| |
| #include <lib/syslog/logger.h> |
| #include <lib/zx/process.h> |
| #include <lib/zx/socket.h> |
| #include <lib/zx/thread.h> |
| |
| #include <atomic> |
| |
| #include <fbl/mutex.h> |
| #include <fbl/string.h> |
| #include <fbl/unique_fd.h> |
| #include <fbl/vector.h> |
| |
| namespace { |
| |
| zx_koid_t GetKoid(zx_handle_t handle) { |
| zx_info_handle_basic_t info; |
| zx_status_t status = |
| zx_object_get_info(handle, ZX_INFO_HANDLE_BASIC, &info, sizeof(info), nullptr, nullptr); |
| return status == ZX_OK ? info.koid : ZX_KOID_INVALID; |
| } |
| |
| zx_koid_t GetCurrentProcessKoid() { |
| auto koid = GetKoid(zx_process_self()); |
| ZX_DEBUG_ASSERT(koid != ZX_KOID_INVALID); |
| return koid; |
| } |
| |
| } // namespace |
| |
| struct fx_logger { |
| public: |
| // If tags or ntags are out of bound, this constructor will not fail but it |
| // will not store all the tags and global tag behaviour would be undefined. |
| // So they should be validated before calling this constructor. |
| fx_logger(const fx_logger_config_t* config) { |
| pid_ = GetCurrentProcessKoid(); |
| dropped_logs_.store(0, std::memory_order_relaxed); |
| Reconfigure(config); |
| if (GetLogConnectionStatus() == ZX_ERR_BAD_STATE) { |
| ActivateFallback(-1); |
| } |
| } |
| |
| ~fx_logger() = default; |
| |
| zx_status_t VLogWrite(fx_log_severity_t severity, const char* tag, const char* format, |
| va_list args, const char* file = nullptr, uint32_t line = 0) { |
| return VLogWrite(severity, tag, file, line, format, args, true); |
| } |
| |
| zx_status_t LogWrite(fx_log_severity_t severity, const char* tag, const char* msg, |
| const char* file = nullptr, uint32_t line = 0) { |
| va_list empty_args; |
| return VLogWrite(severity, tag, file, line, msg, empty_args, false); |
| } |
| |
| zx_status_t SetSeverity(fx_log_severity_t log_severity) { |
| if (log_severity > FX_LOG_FATAL) { |
| return ZX_ERR_INVALID_ARGS; |
| } |
| severity_.store(log_severity, std::memory_order_relaxed); |
| return ZX_OK; |
| } |
| |
| fx_log_severity_t GetSeverity() { return severity_.load(std::memory_order_relaxed); } |
| |
| void ActivateFallback(int fallback_fd); |
| |
| zx_status_t Reconfigure(const fx_logger_config_t* config); |
| |
| zx_status_t GetLogConnectionStatus(); |
| |
| // Set the log connection for this logger using a handle which |
| // is presumed to come from a socket connection with the logging |
| // service. |
| void SetLogConnection(zx_handle_t handle); |
| |
| private: |
| zx_status_t VLogWrite(fx_log_severity_t severity, const char* tag, const char* file, |
| uint32_t line, const char* format, va_list args, bool perform_format); |
| |
| zx_status_t VLogWriteToSocket(fx_log_severity_t severity, const char* tag, const char* file, |
| uint32_t line, const char* msg, va_list args, bool perform_format); |
| |
| zx_status_t VLogWriteToFd(int fd, fx_log_severity_t severity, const char* tag, const char* file, |
| uint32_t line, const char* msg, va_list args, bool perform_format); |
| |
| zx_status_t SetTags(const char* const* tags, size_t ntags); |
| |
| zx_koid_t pid_; |
| std::atomic<fx_log_severity_t> severity_; |
| std::atomic<uint32_t> dropped_logs_; |
| std::atomic<int> logger_fd_ = -1; |
| zx::socket socket_; |
| fbl::Vector<fbl::String> tags_; |
| |
| // This field is just used to close fd when |
| // logger object goes out of scope |
| fbl::unique_fd fd_to_close_; |
| |
| // string representation to print in fallback mode |
| fbl::String tagstr_; |
| |
| fbl::Mutex logger_mutex_; |
| }; |
| |
| #endif // ZIRCON_SYSTEM_ULIB_SYSLOG_FX_LOGGER_H_ |