| // Copyright 2019 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 GARNET_LIB_SYSTEM_MONITOR_GT_LOG_H_ |
| #define GARNET_LIB_SYSTEM_MONITOR_GT_LOG_H_ |
| |
| #include <cassert> |
| #include <fstream> |
| #include <iostream> |
| #include <sstream> |
| |
| // TODO(sm_bug.com/48): This is a minimum logging system intended to quickly |
| // replace a prior logging API. This should be expanded over time. |
| |
| // Each level will be tagged in the output. Output from levels can be enabled or |
| // disabled by ordinal value. |
| // This is defined outside of the namespace for user ergonomics. |
| enum class GuiToolsLogLevel : int { |
| DEBUG3 = -3, |
| DEBUG2 = -2, |
| DEBUG = -1, |
| INFO = 0, |
| WARNING = 1, |
| ERROR = 2, |
| FATAL = 3, |
| }; |
| |
| namespace gt { |
| |
| extern GuiToolsLogLevel g_log_level; |
| extern std::ofstream g_no_output_ofstream; |
| |
| class Logger { |
| public: |
| // Write the line prefix. |
| // Note: |out| and |file_path| must not be null. |
| Logger(std::ostream* out, GuiToolsLogLevel level, GuiToolsLogLevel limit, |
| const char* file_path, int line, const char* function) |
| : out_(out) { |
| assert(out != nullptr); |
| assert(file_path != nullptr); |
| if (level < limit) { |
| out_ = &g_no_output_ofstream; |
| return; |
| } |
| switch (level) { |
| case GuiToolsLogLevel::FATAL: |
| *out_ << "[FATAL]"; |
| break; |
| case GuiToolsLogLevel::ERROR: |
| *out_ << "[ERROR]"; |
| break; |
| case GuiToolsLogLevel::WARNING: |
| *out_ << "[WARNING]"; |
| break; |
| case GuiToolsLogLevel::INFO: |
| *out_ << "[INFO]"; |
| break; |
| case GuiToolsLogLevel::DEBUG: |
| *out_ << "[DEBUG]"; |
| break; |
| case GuiToolsLogLevel::DEBUG2: |
| *out_ << "[DEBUG2]"; |
| break; |
| case GuiToolsLogLevel::DEBUG3: |
| *out_ << "[DEBUG3]"; |
| break; |
| default: |
| *out_ << "[UNKNOWN]"; |
| break; |
| } |
| *out_ << NameOnly(file_path) << ":" << line << ": " << function << ": "; |
| } |
| // Put an end-line on the output. |
| ~Logger() { *out_ << std::endl; } |
| |
| // A stream for the log output for the caller to use. |
| std::ostream& out() { return *out_; } |
| |
| private: |
| std::ostream* out_; |
| |
| // Clip the name off the path. (It's too noisy to print a long file path on |
| // each log line.) |
| const char* NameOnly(const char* file_path) { |
| const char* name = strrchr(file_path, '/'); |
| return name ? name + 1 : file_path; |
| } |
| }; |
| |
| // Initialize the logging systems. The parameters are similar to those passed to |
| // main(). |
| // Returns true on success. |
| bool SetUpLogging(int argc, const char* const* argv); |
| |
| // Provides an ostream to send output to. Avoid calling this function directly. |
| // Use the GT_LOG macro provided below. |
| inline std::ostream& GuiToolsLog(GuiToolsLogLevel level) { return std::cout; } |
| |
| } // namespace gt. |
| |
| // Use like you would `std::cout`. E.g. |
| // GT_LOG(INFO) << "The special value is " << special_value; |
| // |
| // A new-line will end each call implicitly. (If std::endl is passed, there will |
| // be two '\n' printed.) |
| #define GT_LOG(x) \ |
| ::gt::Logger(&std::cout, GuiToolsLogLevel::x, ::gt::g_log_level, __FILE__, \ |
| __LINE__, __FUNCTION__) \ |
| .out() |
| |
| #endif // GARNET_LIB_SYSTEM_MONITOR_GT_LOG_H_ |