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 | |