| // Copyright 2016 The Bazel Authors. All rights reserved. |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| #ifndef BAZEL_SRC_MAIN_CPP_LOGGING_H_ |
| #define BAZEL_SRC_MAIN_CPP_LOGGING_H_ |
| |
| #include <iostream> |
| #include <memory> |
| #include <sstream> |
| #include <string> |
| |
| // This file is based off the logging work by the protobuf team in |
| // stubs/logging.h, |
| // |
| // Users of this logging library should use BAZEL_LOG(level) << ""; format, |
| // and specify how they wish to handle the output of the log messages by |
| // creating a LogHandler to pass to SetLogHandler(). |
| namespace blaze_util { |
| |
| enum LogLevel { |
| LOGLEVEL_INFO, |
| LOGLEVEL_USER, |
| LOGLEVEL_WARNING, |
| LOGLEVEL_ERROR, |
| LOGLEVEL_FATAL, |
| |
| #ifdef NDEBUG |
| LOGLEVEL_DFATAL = LOGLEVEL_ERROR |
| #else |
| LOGLEVEL_DFATAL = LOGLEVEL_FATAL |
| #endif |
| }; |
| |
| // Returns a string representation of the log level. |
| const char* LogLevelName(LogLevel level); |
| |
| namespace internal { |
| |
| class LogFinisher; |
| class LogMessage { |
| public: |
| LogMessage(LogLevel level, const std::string& filename, int line); |
| LogMessage(LogLevel level, const std::string& filename, int line, |
| int exit_code); |
| |
| LogMessage& operator<<(const std::string& value); |
| LogMessage& operator<<(const char* value); |
| LogMessage& operator<<(char value); |
| LogMessage& operator<<(bool value); |
| LogMessage& operator<<(short value); |
| LogMessage& operator<<(int value); |
| LogMessage& operator<<(unsigned int value); |
| LogMessage& operator<<(long value); |
| LogMessage& operator<<(unsigned long value); |
| LogMessage& operator<<(long long value); |
| LogMessage& operator<<(unsigned long long value); |
| LogMessage& operator<<(float value); |
| LogMessage& operator<<(double value); |
| LogMessage& operator<<(long double value); |
| LogMessage& operator<<(void* value); |
| |
| private: |
| friend class LogFinisher; |
| void Finish(); |
| |
| const LogLevel level_; |
| const std::string& filename_; |
| const int line_; |
| // Only used for FATAL log messages. |
| const int exit_code_; |
| std::stringstream message_; |
| }; |
| |
| // Used to make the entire "LOG(BLAH) << etc." expression have a void return |
| // type and print a newline after each message. |
| class LogFinisher { |
| public: |
| void operator=(LogMessage& other); |
| }; |
| |
| template <typename T> |
| bool IsOk(T status) { |
| return status.ok(); |
| } |
| template <> |
| inline bool IsOk(bool status) { |
| return status; |
| } |
| |
| } // namespace internal |
| |
| #define BAZEL_LOG(LEVEL) \ |
| ::blaze_util::internal::LogFinisher() = ::blaze_util::internal::LogMessage( \ |
| ::blaze_util::LOGLEVEL_##LEVEL, __FILE__, __LINE__) |
| #define BAZEL_LOG_IF(LEVEL, CONDITION) !(CONDITION) ? (void)0 : BAZEL_LOG(LEVEL) |
| #define BAZEL_DIE(EXIT_CODE) \ |
| ::blaze_util::internal::LogFinisher() = ::blaze_util::internal::LogMessage( \ |
| ::blaze_util::LOGLEVEL_FATAL, __FILE__, __LINE__, EXIT_CODE) |
| |
| #define BAZEL_CHECK(EXPRESSION) \ |
| BAZEL_LOG_IF(FATAL, !(EXPRESSION)) << "CHECK failed: " #EXPRESSION ": " |
| #define BAZEL_CHECK_OK(A) BAZEL_CHECK(::blaze_util::internal::IsOk(A)) |
| #define BAZEL_CHECK_EQ(A, B) BAZEL_CHECK((A) == (B)) |
| #define BAZEL_CHECK_NE(A, B) BAZEL_CHECK((A) != (B)) |
| #define BAZEL_CHECK_LT(A, B) BAZEL_CHECK((A) < (B)) |
| #define BAZEL_CHECK_LE(A, B) BAZEL_CHECK((A) <= (B)) |
| #define BAZEL_CHECK_GT(A, B) BAZEL_CHECK((A) > (B)) |
| #define BAZEL_CHECK_GE(A, B) BAZEL_CHECK((A) >= (B)) |
| |
| #ifdef NDEBUG |
| |
| #define BAZEL_DLOG(LEVEL) BAZEL_LOG_IF(LEVEL, false) |
| |
| #define BAZEL_DCHECK(EXPRESSION) \ |
| while (false) BAZEL_CHECK(EXPRESSION) |
| #define BAZEL_DCHECK_OK(E) BAZEL_DCHECK(::blaze::internal::IsOk(E)) |
| #define BAZEL_DCHECK_EQ(A, B) BAZEL_DCHECK((A) == (B)) |
| #define BAZEL_DCHECK_NE(A, B) BAZEL_DCHECK((A) != (B)) |
| #define BAZEL_DCHECK_LT(A, B) BAZEL_DCHECK((A) < (B)) |
| #define BAZEL_DCHECK_LE(A, B) BAZEL_DCHECK((A) <= (B)) |
| #define BAZEL_DCHECK_GT(A, B) BAZEL_DCHECK((A) > (B)) |
| #define BAZEL_DCHECK_GE(A, B) BAZEL_DCHECK((A) >= (B)) |
| |
| #else // NDEBUG |
| |
| #define BAZEL_DLOG BAZEL_LOG |
| |
| #define BAZEL_DCHECK BAZEL_CHECK |
| #define BAZEL_DCHECK_OK BAZEL_CHECK_OK |
| #define BAZEL_DCHECK_EQ BAZEL_CHECK_EQ |
| #define BAZEL_DCHECK_NE BAZEL_CHECK_NE |
| #define BAZEL_DCHECK_LT BAZEL_CHECK_LT |
| #define BAZEL_DCHECK_LE BAZEL_CHECK_LE |
| #define BAZEL_DCHECK_GT BAZEL_CHECK_GT |
| #define BAZEL_DCHECK_GE BAZEL_CHECK_GE |
| |
| #endif // !NDEBUG |
| |
| // How much to print on the terminal. |
| enum LoggingDetail { |
| LOGGINGDETAIL_QUIET, // Only errors |
| LOGGINGDETAIL_USER, // Messages intended for the user (level USER and above) |
| LOGGINGDETAIL_DEBUG // Debug logging |
| }; |
| |
| class LogHandler { |
| public: |
| virtual ~LogHandler() {} |
| virtual void HandleMessage(LogLevel level, const std::string& filename, |
| int line, const std::string& message, |
| int exit_code) = 0; |
| |
| // See ::SetLoggingDetail() |
| virtual void SetLoggingDetail(LoggingDetail detail, |
| std::ostream* debug_stream) = 0; |
| |
| // See ::CloseLogging() |
| virtual void Close() = 0; |
| }; |
| |
| // Sets the log handler that routes all log messages. |
| // SetLogHandler is not thread-safe. You should only call it |
| // at initialization time, and probably not from library code. |
| void SetLogHandler(std::unique_ptr<LogHandler> new_handler); |
| |
| // Sets the logging detail for the currently set log handler. Prints the log |
| // messages to `debug_stream` if not null. It doesn't affect non-debug messages |
| // and is only used for testing. |
| void SetLoggingDetail(LoggingDetail detail, std::ostream* debug_stream); |
| |
| // Closes the logging. Buffers are flushed and no more log messages will be |
| // printed. |
| void CloseLogging(); |
| |
| } // namespace blaze_util |
| |
| #endif // BAZEL_SRC_MAIN_CPP_LOGGING_H_ |