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