blob: 9996befa0645d0b3d97cdc9d290733bccb898d48 [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.
#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_