| 1 | // Copyright 2013 The Flutter Authors. All rights reserved. |
| 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
| 5 | #ifndef FLUTTER_FML_LOGGING_H_ |
| 6 | #define FLUTTER_FML_LOGGING_H_ |
| 7 | |
| 8 | #include <sstream> |
| 9 | |
| 10 | #include "flutter/fml/log_level.h" |
| 11 | #include "flutter/fml/macros.h" |
| 12 | |
| 13 | namespace fml { |
| 14 | |
| 15 | namespace testing { |
| 16 | struct LogCapture { |
| 17 | LogCapture(); |
| 18 | ~LogCapture(); |
| 19 | |
| 20 | std::string str() const; |
| 21 | |
| 22 | private: |
| 23 | std::ostringstream stream_; |
| 24 | }; |
| 25 | } // namespace testing |
| 26 | |
| 27 | class LogMessageVoidify { |
| 28 | public: |
| 29 | void operator&(std::ostream&) {} |
| 30 | }; |
| 31 | |
| 32 | class LogMessage { |
| 33 | public: |
| 34 | LogMessage(LogSeverity severity, |
| 35 | const char* file, |
| 36 | int line, |
| 37 | const char* condition); |
| 38 | ~LogMessage(); |
| 39 | |
| 40 | std::ostream& stream() { return stream_; } |
| 41 | |
| 42 | static void CaptureNextLog(std::ostringstream* stream); |
| 43 | |
| 44 | private: |
| 45 | // This is a raw pointer so that we avoid having a non-trivially-destructible |
| 46 | // static. It is only ever for use in unit tests. |
| 47 | static thread_local std::ostringstream* capture_next_log_stream_; |
| 48 | std::ostringstream stream_; |
| 49 | const LogSeverity severity_; |
| 50 | const char* file_; |
| 51 | const int line_; |
| 52 | |
| 53 | FML_DISALLOW_COPY_AND_ASSIGN(LogMessage); |
| 54 | }; |
| 55 | |
| 56 | // Gets the FML_VLOG default verbosity level. |
| 57 | int GetVlogVerbosity(); |
| 58 | |
| 59 | // Returns true if |severity| is at or above the current minimum log level. |
| 60 | // LOG_FATAL and above is always true. |
| 61 | bool ShouldCreateLogMessage(LogSeverity severity); |
| 62 | |
| 63 | [[noreturn]] void KillProcess(); |
| 64 | |
| 65 | } // namespace fml |
| 66 | |
| 67 | #define FML_LOG_STREAM(severity) \ |
| 68 | ::fml::LogMessage(::fml::LOG_##severity, __FILE__, __LINE__, nullptr).stream() |
| 69 | |
| 70 | #define FML_LAZY_STREAM(stream, condition) \ |
| 71 | !(condition) ? (void)0 : ::fml::LogMessageVoidify() & (stream) |
| 72 | |
| 73 | #define FML_EAT_STREAM_PARAMETERS(ignored) \ |
| 74 | true || (ignored) \ |
| 75 | ? (void)0 \ |
| 76 | : ::fml::LogMessageVoidify() & \ |
| 77 | ::fml::LogMessage(::fml::LOG_FATAL, 0, 0, nullptr).stream() |
| 78 | |
| 79 | #define FML_LOG_IS_ON(severity) \ |
| 80 | (::fml::ShouldCreateLogMessage(::fml::LOG_##severity)) |
| 81 | |
| 82 | #define FML_LOG(severity) \ |
| 83 | FML_LAZY_STREAM(FML_LOG_STREAM(severity), FML_LOG_IS_ON(severity)) |
| 84 | |
| 85 | #define FML_CHECK(condition) \ |
| 86 | FML_LAZY_STREAM( \ |
| 87 | ::fml::LogMessage(::fml::LOG_FATAL, __FILE__, __LINE__, #condition) \ |
| 88 | .stream(), \ |
| 89 | !(condition)) |
| 90 | |
| 91 | #define FML_VLOG_IS_ON(verbose_level) \ |
| 92 | ((verbose_level) <= ::fml::GetVlogVerbosity()) |
| 93 | |
| 94 | // The VLOG macros log with negative verbosities. |
| 95 | #define FML_VLOG_STREAM(verbose_level) \ |
| 96 | ::fml::LogMessage(-verbose_level, __FILE__, __LINE__, nullptr).stream() |
| 97 | |
| 98 | #define FML_VLOG(verbose_level) \ |
| 99 | FML_LAZY_STREAM(FML_VLOG_STREAM(verbose_level), FML_VLOG_IS_ON(verbose_level)) |
| 100 | |
| 101 | #ifndef NDEBUG |
| 102 | #define FML_DLOG(severity) FML_LOG(severity) |
| 103 | #define FML_DCHECK(condition) FML_CHECK(condition) |
| 104 | #else |
| 105 | #define FML_DLOG(severity) FML_EAT_STREAM_PARAMETERS(true) |
| 106 | #define FML_DCHECK(condition) FML_EAT_STREAM_PARAMETERS(condition) |
| 107 | #endif |
| 108 | |
| 109 | #define FML_UNREACHABLE() \ |
| 110 | { \ |
| 111 | FML_LOG(ERROR) << "Reached unreachable code."; \ |
| 112 | ::fml::KillProcess(); \ |
| 113 | } |
| 114 | |
| 115 | #endif // FLUTTER_FML_LOGGING_H_ |
| 116 | |