1 | /* |
2 | * Copyright (C) 2017 The Android Open Source Project |
3 | * |
4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
5 | * you may not use this file except in compliance with the License. |
6 | * You may obtain a copy of the License at |
7 | * |
8 | * http://www.apache.org/licenses/LICENSE-2.0 |
9 | * |
10 | * Unless required by applicable law or agreed to in writing, software |
11 | * distributed under the License is distributed on an "AS IS" BASIS, |
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
13 | * See the License for the specific language governing permissions and |
14 | * limitations under the License. |
15 | */ |
16 | |
17 | #ifndef INCLUDE_PERFETTO_BASE_LOGGING_H_ |
18 | #define INCLUDE_PERFETTO_BASE_LOGGING_H_ |
19 | |
20 | #include <errno.h> |
21 | #include <string.h> // For strerror. |
22 | |
23 | #include "perfetto/base/build_config.h" |
24 | #include "perfetto/base/compiler.h" |
25 | #include "perfetto/base/export.h" |
26 | |
27 | #if defined(__GNUC__) || defined(__clang__) |
28 | // Ignore GCC warning about a missing argument for a variadic macro parameter. |
29 | #pragma GCC system_header |
30 | #endif |
31 | |
32 | #if PERFETTO_BUILDFLAG(PERFETTO_FORCE_DCHECK_ON) |
33 | #define PERFETTO_DCHECK_IS_ON() 1 |
34 | #elif PERFETTO_BUILDFLAG(PERFETTO_FORCE_DCHECK_OFF) |
35 | #define PERFETTO_DCHECK_IS_ON() 0 |
36 | #elif defined(DCHECK_ALWAYS_ON) || \ |
37 | (!defined(NDEBUG) && (PERFETTO_BUILDFLAG(PERFETTO_STANDALONE_BUILD) || \ |
38 | PERFETTO_BUILDFLAG(PERFETTO_CHROMIUM_BUILD) || \ |
39 | PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD))) |
40 | #define PERFETTO_DCHECK_IS_ON() 1 |
41 | #else |
42 | #define PERFETTO_DCHECK_IS_ON() 0 |
43 | #endif |
44 | |
45 | #if PERFETTO_BUILDFLAG(PERFETTO_FORCE_DLOG_ON) |
46 | #define PERFETTO_DLOG_IS_ON() 1 |
47 | #elif PERFETTO_BUILDFLAG(PERFETTO_FORCE_DLOG_OFF) |
48 | #define PERFETTO_DLOG_IS_ON() 0 |
49 | #else |
50 | #define PERFETTO_DLOG_IS_ON() PERFETTO_DCHECK_IS_ON() |
51 | #endif |
52 | |
53 | #if defined(PERFETTO_ANDROID_ASYNC_SAFE_LOG) |
54 | #if !PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) || \ |
55 | !PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD) |
56 | #error "Async-safe logging is limited to Android tree builds" |
57 | #endif |
58 | // For binaries which need a very lightweight logging implementation. |
59 | // Note that this header is incompatible with android/log.h. |
60 | #include <async_safe/log.h> |
61 | #elif PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) |
62 | // Normal android logging. |
63 | #include <android/log.h> |
64 | #endif |
65 | |
66 | // Enable the "Print the most recent PERFETTO_LOG(s) before crashing" feature |
67 | // on Android in-tree builds and on standalone builds (mainly for testing). |
68 | // This is deliberately no PERFETTO_OS_ANDROID because we don't want this |
69 | // feature when perfetto is embedded in other Android projects (e.g. SDK). |
70 | // TODO(b/203795298): TFLite is using the client library in blaze builds and is |
71 | // targeting API 19. For now disable the feature based on API level. |
72 | #if defined(PERFETTO_ANDROID_ASYNC_SAFE_LOG) |
73 | #define PERFETTO_ENABLE_LOG_RING_BUFFER() 0 |
74 | #elif PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD) |
75 | #define PERFETTO_ENABLE_LOG_RING_BUFFER() 1 |
76 | #elif PERFETTO_BUILDFLAG(PERFETTO_STANDALONE_BUILD) && \ |
77 | (!PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) || \ |
78 | (defined(__ANDROID_API__) && __ANDROID_API__ >= 21)) |
79 | #define PERFETTO_ENABLE_LOG_RING_BUFFER() 1 |
80 | #else |
81 | #define PERFETTO_ENABLE_LOG_RING_BUFFER() 0 |
82 | #endif |
83 | |
84 | namespace perfetto { |
85 | namespace base { |
86 | |
87 | // Constexpr functions to extract basename(__FILE__), e.g.: ../foo/f.c -> f.c . |
88 | constexpr const char* StrEnd(const char* s) { |
89 | return *s ? StrEnd(s: s + 1) : s; |
90 | } |
91 | |
92 | constexpr const char* BasenameRecursive(const char* s, |
93 | const char* begin, |
94 | const char* end) { |
95 | return (*s == '/' && s < end) |
96 | ? (s + 1) |
97 | : ((s > begin) ? BasenameRecursive(s: s - 1, begin, end) : s); |
98 | } |
99 | |
100 | constexpr const char* Basename(const char* str) { |
101 | return BasenameRecursive(s: StrEnd(s: str), begin: str, end: StrEnd(s: str)); |
102 | } |
103 | |
104 | enum LogLev { kLogDebug = 0, kLogInfo, kLogImportant, kLogError }; |
105 | |
106 | struct LogMessageCallbackArgs { |
107 | LogLev level; |
108 | int line; |
109 | const char* filename; |
110 | const char* message; |
111 | }; |
112 | |
113 | using LogMessageCallback = void (*)(LogMessageCallbackArgs); |
114 | |
115 | // This is not thread safe and must be called before using tracing from other |
116 | // threads. |
117 | PERFETTO_EXPORT_COMPONENT void SetLogMessageCallback( |
118 | LogMessageCallback callback); |
119 | |
120 | PERFETTO_EXPORT_COMPONENT void LogMessage(LogLev, |
121 | const char* fname, |
122 | int line, |
123 | const char* fmt, |
124 | ...) PERFETTO_PRINTF_FORMAT(4, 5); |
125 | |
126 | // This is defined in debug_crash_stack_trace.cc, but that is only linked in |
127 | // standalone && debug builds, see enable_perfetto_stderr_crash_dump in |
128 | // perfetto.gni. |
129 | PERFETTO_EXPORT_COMPONENT void EnableStacktraceOnCrashForDebug(); |
130 | |
131 | #if PERFETTO_ENABLE_LOG_RING_BUFFER() |
132 | // Gets a snapshot of the logs from the internal log ring buffer and: |
133 | // - On Android in-tree builds: Passes that to android_set_abort_message(). |
134 | // That will attach the logs to the crash report. |
135 | // - On standalone builds (all otther OSes) prints that on stderr. |
136 | // This function must called only once, right before inducing a crash (This is |
137 | // because android_set_abort_message() can only be called once). |
138 | PERFETTO_EXPORT_COMPONENT void MaybeSerializeLastLogsForCrashReporting(); |
139 | #else |
140 | inline void MaybeSerializeLastLogsForCrashReporting() {} |
141 | #endif |
142 | |
143 | #if defined(PERFETTO_ANDROID_ASYNC_SAFE_LOG) |
144 | #define PERFETTO_XLOG(level, fmt, ...) \ |
145 | do { \ |
146 | async_safe_format_log((ANDROID_LOG_DEBUG + level), "perfetto", \ |
147 | "%s:%d " fmt, ::perfetto::base::Basename(__FILE__), \ |
148 | __LINE__, ##__VA_ARGS__); \ |
149 | } while (0) |
150 | #elif defined(PERFETTO_DISABLE_LOG) |
151 | #define PERFETTO_XLOG(level, fmt, ...) ::perfetto::base::ignore_result(level, \ |
152 | fmt, ##__VA_ARGS__) |
153 | #else |
154 | #define PERFETTO_XLOG(level, fmt, ...) \ |
155 | ::perfetto::base::LogMessage(level, ::perfetto::base::Basename(__FILE__), \ |
156 | __LINE__, fmt, ##__VA_ARGS__) |
157 | #endif |
158 | |
159 | #if defined(_MSC_VER) |
160 | #define PERFETTO_IMMEDIATE_CRASH() \ |
161 | do { \ |
162 | ::perfetto::base::MaybeSerializeLastLogsForCrashReporting(); \ |
163 | __debugbreak(); \ |
164 | __assume(0); \ |
165 | } while (0) |
166 | #else |
167 | #define PERFETTO_IMMEDIATE_CRASH() \ |
168 | do { \ |
169 | ::perfetto::base::MaybeSerializeLastLogsForCrashReporting(); \ |
170 | __builtin_trap(); \ |
171 | __builtin_unreachable(); \ |
172 | } while (0) |
173 | #endif |
174 | |
175 | #if PERFETTO_BUILDFLAG(PERFETTO_VERBOSE_LOGS) |
176 | #define PERFETTO_LOG(fmt, ...) \ |
177 | PERFETTO_XLOG(::perfetto::base::kLogInfo, fmt, ##__VA_ARGS__) |
178 | #else // PERFETTO_BUILDFLAG(PERFETTO_VERBOSE_LOGS) |
179 | #define PERFETTO_LOG(...) ::perfetto::base::ignore_result(__VA_ARGS__) |
180 | #endif // PERFETTO_BUILDFLAG(PERFETTO_VERBOSE_LOGS) |
181 | |
182 | #define PERFETTO_ILOG(fmt, ...) \ |
183 | PERFETTO_XLOG(::perfetto::base::kLogImportant, fmt, ##__VA_ARGS__) |
184 | #define PERFETTO_ELOG(fmt, ...) \ |
185 | PERFETTO_XLOG(::perfetto::base::kLogError, fmt, ##__VA_ARGS__) |
186 | #define PERFETTO_FATAL(fmt, ...) \ |
187 | do { \ |
188 | PERFETTO_PLOG(fmt, ##__VA_ARGS__); \ |
189 | PERFETTO_IMMEDIATE_CRASH(); \ |
190 | } while (0) |
191 | |
192 | #if defined(__GNUC__) || defined(__clang__) |
193 | #define PERFETTO_PLOG(x, ...) \ |
194 | PERFETTO_ELOG(x " (errno: %d, %s)", ##__VA_ARGS__, errno, strerror(errno)) |
195 | #else |
196 | // MSVC expands __VA_ARGS__ in a different order. Give up, not worth it. |
197 | #define PERFETTO_PLOG PERFETTO_ELOG |
198 | #endif |
199 | |
200 | #define PERFETTO_CHECK(x) \ |
201 | do { \ |
202 | if (PERFETTO_UNLIKELY(!(x))) { \ |
203 | PERFETTO_PLOG("%s", "PERFETTO_CHECK(" #x ")"); \ |
204 | PERFETTO_IMMEDIATE_CRASH(); \ |
205 | } \ |
206 | } while (0) |
207 | |
208 | #if PERFETTO_DLOG_IS_ON() |
209 | |
210 | #define PERFETTO_DLOG(fmt, ...) \ |
211 | PERFETTO_XLOG(::perfetto::base::kLogDebug, fmt, ##__VA_ARGS__) |
212 | |
213 | #if defined(__GNUC__) || defined(__clang__) |
214 | #define PERFETTO_DPLOG(x, ...) \ |
215 | PERFETTO_DLOG(x " (errno: %d, %s)", ##__VA_ARGS__, errno, strerror(errno)) |
216 | #else |
217 | // MSVC expands __VA_ARGS__ in a different order. Give up, not worth it. |
218 | #define PERFETTO_DPLOG PERFETTO_DLOG |
219 | #endif |
220 | |
221 | #else // PERFETTO_DLOG_IS_ON() |
222 | |
223 | #define PERFETTO_DLOG(...) ::perfetto::base::ignore_result(__VA_ARGS__) |
224 | #define PERFETTO_DPLOG(...) ::perfetto::base::ignore_result(__VA_ARGS__) |
225 | |
226 | #endif // PERFETTO_DLOG_IS_ON() |
227 | |
228 | #if PERFETTO_DCHECK_IS_ON() |
229 | |
230 | #define PERFETTO_DCHECK(x) PERFETTO_CHECK(x) |
231 | #define PERFETTO_DFATAL(...) PERFETTO_FATAL(__VA_ARGS__) |
232 | #define PERFETTO_DFATAL_OR_ELOG(...) PERFETTO_DFATAL(__VA_ARGS__) |
233 | |
234 | #else // PERFETTO_DCHECK_IS_ON() |
235 | |
236 | #define PERFETTO_DCHECK(x) \ |
237 | do { \ |
238 | } while (false && (x)) |
239 | |
240 | #define PERFETTO_DFATAL(...) ::perfetto::base::ignore_result(__VA_ARGS__) |
241 | #define PERFETTO_DFATAL_OR_ELOG(...) PERFETTO_ELOG(__VA_ARGS__) |
242 | |
243 | #endif // PERFETTO_DCHECK_IS_ON() |
244 | |
245 | } // namespace base |
246 | } // namespace perfetto |
247 | |
248 | #endif // INCLUDE_PERFETTO_BASE_LOGGING_H_ |
249 | |