blob: b8a3b5d1dabf30746d7aa96bda744c5752d1b858 [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 <zircon/status.h>
#include <atomic>
#include <fbl/auto_lock.h>
#include <fbl/mutex.h>
#include <fbl/string.h>
#include <fbl/unique_fd.h>
#include <fbl/vector.h>
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.
explicit fx_logger(const fx_logger_config_t* config, bool structured) {
pid_ = []() {
zx_info_handle_basic_t info;
zx_status_t status = zx_object_get_info(zx_process_self(), ZX_INFO_HANDLE_BASIC, &info,
sizeof(info), nullptr, nullptr);
ZX_DEBUG_ASSERT_MSG(status == ZX_OK, "zx_object_get_info(zx_process_self(), ...): %s",
zx_status_get_string(status));
return info.koid;
}();
dropped_logs_.store(0, std::memory_order_relaxed);
Reconfigure(config, structured);
if (GetLogConnectionStatus() == ZX_ERR_BAD_STATE) {
ActivateFallback(-1);
}
}
~fx_logger() = default;
template <typename Callback>
void GetTags(const Callback& callback) {
fbl::AutoLock tag_lock(&tags_mutex_);
for (auto tag : tags_) {
callback(tag);
}
}
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) {
return VLogWrite(severity, tag, file, line, msg, va_list{}, 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, bool is_structured);
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* msg, 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_ __TA_GUARDED(tags_mutex_);
// 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_;
// Mutex protecting tags
fbl::Mutex tags_mutex_;
fbl::Mutex logger_mutex_;
// True if structured logging was requested by the user,
// false otherwise. Note that this may be false,
// and we could still be using structured logs
// like in the case of drivers.
bool is_structured_ = false;
};
#endif // ZIRCON_SYSTEM_ULIB_SYSLOG_FX_LOGGER_H_