| // 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 LIB_SYSLOG_CPP_LOGGER_H_ |
| #define LIB_SYSLOG_CPP_LOGGER_H_ |
| |
| #include <lib/syslog/global.h> |
| #include <stdint.h> |
| #include <zircon/types.h> |
| |
| #include <initializer_list> |
| #include <ostream> |
| #include <sstream> |
| #include <string> |
| |
| namespace syslog { |
| namespace internal { |
| |
| class LogMessageVoidify { |
| public: |
| void operator&(std::ostream&) {} |
| }; |
| |
| class LogMessage { |
| public: |
| LogMessage(fx_log_severity_t severity, const char* file, int line, |
| const char* tag, zx_status_t status, const char* condition); |
| ~LogMessage(); |
| |
| std::ostream& stream() { return stream_; } |
| |
| private: |
| std::ostringstream stream_; |
| const fx_log_severity_t severity_; |
| const char* file_; |
| const int line_; |
| const char* tag_; |
| const zx_status_t status_; |
| |
| LogMessage(const LogMessage&) = delete; |
| LogMessage& operator=(const LogMessage&) = delete; |
| }; |
| |
| // LogFirstNState is used by the macro FX_LOGS_FIRST_N below. |
| class LogFirstNState { |
| public: |
| bool ShouldLog(int n); |
| |
| private: |
| std::atomic<int32_t> counter_{0}; |
| }; |
| |
| } // namespace internal |
| |
| struct LogSettings { |
| fx_log_severity_t severity; |
| int fd; |
| }; |
| |
| // Creates default logger from provided tags and settings. |
| // Returns zx_status_t if it is not able to create logger. |
| zx_status_t InitLogger(const syslog::LogSettings& settings, |
| const std::initializer_list<std::string>& tags); |
| |
| // Creates default logger from provided tags. |
| // Returns zx_status_t if it is not able to create logger. |
| zx_status_t InitLogger(const std::initializer_list<std::string>& tags); |
| |
| // Creates default logger. |
| // Returns zx_status_t if it is not able to create logger. |
| zx_status_t InitLogger(); |
| |
| } // namespace syslog |
| |
| #define _FX_LOG_STREAM(severity, tag, status) \ |
| ::syslog::internal::LogMessage((severity), __FILE__, __LINE__, (tag), \ |
| (status), nullptr) \ |
| .stream() |
| |
| #define FX_LOG_STREAM(severity, tag, status) \ |
| _FX_LOG_STREAM(FX_LOG_##severity, (tag), (status)) |
| |
| #define FX_LOG_LAZY_STREAM(stream, condition) \ |
| !(condition) ? (void)0 : ::syslog::internal::LogMessageVoidify() & (stream) |
| |
| #define _FX_EAT_STREAM_PARAMETERS(ignored, tag) \ |
| true || (ignored) || (tag) != nullptr \ |
| ? (void)0 \ |
| : FX_LOG_LAZY_STREAM( \ |
| ::syslog::internal::LogMessage(FX_LOG_FATAL, __FILE__, __LINE__, \ |
| tag, INT32_MAX, #ignored) \ |
| .stream(), \ |
| !(ignored)) |
| |
| // Writes a message to the global logger. |
| // |severity| is one of DEBUG, INFO, WARNING, ERROR, FATAL |
| // |tag| is a tag to associated with the message, or NULL if none. |
| #define FX_LOGST(severity, tag) \ |
| FX_LOG_LAZY_STREAM(FX_LOG_STREAM(severity, (tag), INT32_MAX), \ |
| FX_LOG_IS_ENABLED(severity)) |
| |
| // Writes a message to the global logger. |
| // |severity| is one of DEBUG, INFO, WARNING, ERROR, FATAL |
| // |tag| is a tag to associated with the message, or NULL if none. |
| // |status| is a zx_status_t which will be appended in decimal and string forms |
| // after the message. |
| #define FX_PLOGST(severity, tag, status) \ |
| FX_LOG_LAZY_STREAM(FX_LOG_STREAM(severity, (tag), (status)), \ |
| FX_LOG_IS_ENABLED(severity)) |
| |
| // Writes a message to the global logger. |
| // |severity| is one of FX_LOG_DEBUG, FX_LOG_INFO, FX_LOG_WARNING, |
| // FX_LOG_ERROR, FX_LOG_FATAL |
| // |tag| is a tag to associated with the message, or NULL if none. |
| #define FX_LOGST_WITH_SEVERITY(severity, tag) \ |
| FX_LOG_LAZY_STREAM(_FX_LOG_STREAM((severity), (tag), INT32_MAX), \ |
| fx_log_is_enabled((severity))) |
| |
| // Writes a message to the global logger. |
| // |severity| is one of DEBUG, INFO, WARNING, ERROR, FATAL |
| #define FX_LOGS(severity) FX_LOGST(severity, nullptr) |
| |
| // Writes a message to the global logger. |
| // |severity| is one of DEBUG, INFO, WARNING, ERROR, FATAL |
| // |status| is a zx_status_t which will be appended in decimal and string forms |
| // after the message. |
| #define FX_PLOGS(severity, status) FX_PLOGST(severity, nullptr, status) |
| |
| // Writes a message to the global logger, the first |n| times that any callsite |
| // of this macro is invoked. |n| should be a positive integer literal. If a |
| // single callsite is invoked by multiple threads it is possible that the |
| // number of times the message is written could be greater than |n| but will |
| // never be greater than n-1 + #(calling threads). |
| // |severity| is one of DEBUG, INFO, WARNING, ERROR, FATAL |
| // |
| // Implementation notes: |
| // The outer for loop is a trick to allow us to introduce a new scope and |
| // introduce the variable |syslog_internal_do_log| into that scope. It |
| // executes exactly once. |
| // |
| // The inner for loop is a trick to allow us to introduce a new scope |
| // and introduce the static variable |syslog_internal_state| into that |
| // new scope. It executes either zero or one times. |
| // |
| // C++ does not allow us to introduce two new variables into |
| // a single for loop scope and we need |syslog_internal_do_log| so that |
| // the inner for loop doesn't execute twice. |
| #define FX_LOGS_FIRST_N(severity, n) \ |
| for (bool syslog_internal_do_log = true; syslog_internal_do_log; \ |
| syslog_internal_do_log = false) \ |
| for (static syslog::internal::LogFirstNState syslog_internal_state; \ |
| syslog_internal_do_log && syslog_internal_state.ShouldLog(n); \ |
| syslog_internal_do_log = false) \ |
| FX_LOGS(severity) |
| |
| // Writes a message to the global logger. |
| // |severity| is one of FX_LOG_DEBUG, FX_LOG_INFO, FX_LOG_WARNING, |
| // FX_LOG_ERROR, FX_LOG_FATAL |
| #define FX_LOGS_WITH_SEVERITY(severity) \ |
| FX_LOGST_WITH_SEVERITY((severity), nullptr) |
| |
| // Writes error message to the global logger if |condition| fails. |
| // |tag| is a tag to associated with the message, or NULL if none. |
| #define FX_CHECKT(condition, tag) \ |
| FX_LOG_LAZY_STREAM( \ |
| ::syslog::internal::LogMessage(FX_LOG_FATAL, __FILE__, __LINE__, tag, \ |
| INT32_MAX, #condition) \ |
| .stream(), \ |
| !(condition)) |
| |
| // Writes error message to the global logger if |condition| fails. |
| #define FX_CHECK(condition) FX_CHECKT(condition, nullptr) |
| |
| // Writes error message to the global logger if |condition| fails in debug |
| // build. |
| #ifndef NDEBUG |
| #define FX_DCHECK(condition) FX_CHECK(condition) |
| #define FX_DCHECKT(condition, tag) FX_CHECKT(condition, tag) |
| #else |
| #define FX_DCHECK(condition) _FX_EAT_STREAM_PARAMETERS(condition, nullptr) |
| #define FX_DCHECKT(condition, tag) _FX_EAT_STREAM_PARAMETERS(condition, tag) |
| #endif |
| |
| // VLOG macros log with negative verbosities. |
| #define FX_VLOG_STREAM(verbose_level, tag, status) \ |
| ::syslog::internal::LogMessage(-(verbose_level), __FILE__, __LINE__, (tag), \ |
| (status), nullptr) \ |
| .stream() |
| |
| #define FX_VLOGST(verbose_level, tag) \ |
| FX_LOG_LAZY_STREAM(FX_VLOG_STREAM((verbose_level), (tag), INT32_MAX), \ |
| FX_VLOG_IS_ENABLED((verbose_level))) |
| |
| #define FX_VPLOGST(verbose_level, tag, status) \ |
| FX_LOG_LAZY_STREAM(FX_VLOG_STREAM((verbose_level), (tag), (status)), \ |
| FX_VLOG_IS_ENABLED((verbose_level))) |
| |
| #define FX_VLOGS(verbose_level) FX_VLOGST((verbose_level), nullptr) |
| |
| #define FX_VPLOGS(verbose_level, status) \ |
| FX_VPLOGST((verbose_level), nullptr, status) |
| |
| #endif // LIB_SYSLOG_CPP_LOGGER_H_ |