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
84namespace perfetto {
85namespace base {
86
87// Constexpr functions to extract basename(__FILE__), e.g.: ../foo/f.c -> f.c .
88constexpr const char* StrEnd(const char* s) {
89 return *s ? StrEnd(s: s + 1) : s;
90}
91
92constexpr 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
100constexpr const char* Basename(const char* str) {
101 return BasenameRecursive(s: StrEnd(s: str), begin: str, end: StrEnd(s: str));
102}
103
104enum LogLev { kLogDebug = 0, kLogInfo, kLogImportant, kLogError };
105
106struct LogMessageCallbackArgs {
107 LogLev level;
108 int line;
109 const char* filename;
110 const char* message;
111};
112
113using LogMessageCallback = void (*)(LogMessageCallbackArgs);
114
115// This is not thread safe and must be called before using tracing from other
116// threads.
117PERFETTO_EXPORT_COMPONENT void SetLogMessageCallback(
118 LogMessageCallback callback);
119
120PERFETTO_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.
129PERFETTO_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).
138PERFETTO_EXPORT_COMPONENT void MaybeSerializeLastLogsForCrashReporting();
139#else
140inline 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

source code of dart_sdk/third_party/perfetto/include/perfetto/base/logging.h