• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 // TODO(primiano): move this to base/build_config.h, turn into
33 // PERFETTO_BUILDFLAG(DCHECK_IS_ON) and update call sites to use that instead.
34 #if defined(NDEBUG) && !defined(DCHECK_ALWAYS_ON)
35 #define PERFETTO_DCHECK_IS_ON() 0
36 #else
37 #define PERFETTO_DCHECK_IS_ON() 1
38 #endif
39 
40 #if PERFETTO_BUILDFLAG(PERFETTO_FORCE_DLOG_ON)
41 #define PERFETTO_DLOG_IS_ON() 1
42 #elif PERFETTO_BUILDFLAG(PERFETTO_FORCE_DLOG_OFF)
43 #define PERFETTO_DLOG_IS_ON() 0
44 #else
45 #define PERFETTO_DLOG_IS_ON() PERFETTO_DCHECK_IS_ON()
46 #endif
47 
48 #if defined(PERFETTO_ANDROID_ASYNC_SAFE_LOG)
49 #if !PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) || \
50     !PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD)
51 #error "Async-safe logging is limited to Android tree builds"
52 #endif
53 // For binaries which need a very lightweight logging implementation.
54 // Note that this header is incompatible with android/log.h.
55 #include <async_safe/log.h>
56 #elif PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
57 // Normal android logging.
58 #include <android/log.h>
59 #endif
60 
61 namespace perfetto {
62 namespace base {
63 
64 // Constexpr functions to extract basename(__FILE__), e.g.: ../foo/f.c -> f.c .
StrEnd(const char * s)65 constexpr const char* StrEnd(const char* s) {
66   return *s ? StrEnd(s + 1) : s;
67 }
68 
BasenameRecursive(const char * s,const char * begin,const char * end)69 constexpr const char* BasenameRecursive(const char* s,
70                                         const char* begin,
71                                         const char* end) {
72   return (*s == '/' && s < end)
73              ? (s + 1)
74              : ((s > begin) ? BasenameRecursive(s - 1, begin, end) : s);
75 }
76 
Basename(const char * str)77 constexpr const char* Basename(const char* str) {
78   return BasenameRecursive(StrEnd(str), str, StrEnd(str));
79 }
80 
81 enum LogLev { kLogDebug = 0, kLogInfo, kLogImportant, kLogError };
82 
83 struct LogMessageCallbackArgs {
84   LogLev level;
85   int line;
86   const char* filename;
87   const char* message;
88 };
89 
90 using LogMessageCallback = void (*)(LogMessageCallbackArgs);
91 
92 // This is not thread safe and must be called before using tracing from other
93 // threads.
94 PERFETTO_EXPORT void SetLogMessageCallback(LogMessageCallback callback);
95 
96 PERFETTO_EXPORT void LogMessage(LogLev,
97                                 const char* fname,
98                                 int line,
99                                 const char* fmt,
100                                 ...) PERFETTO_PRINTF_FORMAT(4, 5);
101 
102 #if defined(PERFETTO_ANDROID_ASYNC_SAFE_LOG)
103 #define PERFETTO_XLOG(level, fmt, ...)                                        \
104   do {                                                                        \
105     async_safe_format_log((ANDROID_LOG_DEBUG + level), "perfetto",            \
106                           "%s:%d " fmt, ::perfetto::base::Basename(__FILE__), \
107                           __LINE__, ##__VA_ARGS__);                           \
108   } while (0)
109 #elif defined(PERFETTO_DISABLE_LOG)
110 #define PERFETTO_XLOG(...) ::perfetto::base::ignore_result(__VA_ARGS__)
111 #else
112 #define PERFETTO_XLOG(level, fmt, ...)                                      \
113   ::perfetto::base::LogMessage(level, ::perfetto::base::Basename(__FILE__), \
114                                __LINE__, fmt, ##__VA_ARGS__)
115 #endif
116 
117 #if defined(_MSC_VER)
118 #define PERFETTO_IMMEDIATE_CRASH() \
119   do {                             \
120     __debugbreak();                \
121     __assume(0);                   \
122   } while (0)
123 #else
124 #define PERFETTO_IMMEDIATE_CRASH() \
125   do {                             \
126     __builtin_trap();              \
127     __builtin_unreachable();       \
128   } while (0)
129 #endif
130 
131 #if PERFETTO_BUILDFLAG(PERFETTO_VERBOSE_LOGS)
132 #define PERFETTO_LOG(fmt, ...) \
133   PERFETTO_XLOG(::perfetto::base::kLogInfo, fmt, ##__VA_ARGS__)
134 #else  // PERFETTO_BUILDFLAG(PERFETTO_VERBOSE_LOGS)
135 #define PERFETTO_LOG(...) ::perfetto::base::ignore_result(__VA_ARGS__)
136 #endif  // PERFETTO_BUILDFLAG(PERFETTO_VERBOSE_LOGS)
137 
138 #define PERFETTO_ILOG(fmt, ...) \
139   PERFETTO_XLOG(::perfetto::base::kLogImportant, fmt, ##__VA_ARGS__)
140 #define PERFETTO_ELOG(fmt, ...) \
141   PERFETTO_XLOG(::perfetto::base::kLogError, fmt, ##__VA_ARGS__)
142 #define PERFETTO_FATAL(fmt, ...)       \
143   do {                                 \
144     PERFETTO_PLOG(fmt, ##__VA_ARGS__); \
145     PERFETTO_IMMEDIATE_CRASH();        \
146   } while (0)
147 
148 #if defined(__GNUC__) || defined(__clang__)
149 #define PERFETTO_PLOG(x, ...) \
150   PERFETTO_ELOG(x " (errno: %d, %s)", ##__VA_ARGS__, errno, strerror(errno))
151 #else
152 // MSVC expands __VA_ARGS__ in a different order. Give up, not worth it.
153 #define PERFETTO_PLOG PERFETTO_ELOG
154 #endif
155 
156 #define PERFETTO_CHECK(x)                            \
157   do {                                               \
158     if (PERFETTO_UNLIKELY(!(x))) {                   \
159       PERFETTO_PLOG("%s", "PERFETTO_CHECK(" #x ")"); \
160       PERFETTO_IMMEDIATE_CRASH();                    \
161     }                                                \
162   } while (0)
163 
164 #if PERFETTO_DLOG_IS_ON()
165 
166 #define PERFETTO_DLOG(fmt, ...) \
167   PERFETTO_XLOG(::perfetto::base::kLogDebug, fmt, ##__VA_ARGS__)
168 
169 #if defined(__GNUC__) || defined(__clang__)
170 #define PERFETTO_DPLOG(x, ...) \
171   PERFETTO_DLOG(x " (errno: %d, %s)", ##__VA_ARGS__, errno, strerror(errno))
172 #else
173 // MSVC expands __VA_ARGS__ in a different order. Give up, not worth it.
174 #define PERFETTO_DPLOG PERFETTO_DLOG
175 #endif
176 
177 #else  // PERFETTO_DLOG_IS_ON()
178 
179 #define PERFETTO_DLOG(...) ::perfetto::base::ignore_result(__VA_ARGS__)
180 #define PERFETTO_DPLOG(...) ::perfetto::base::ignore_result(__VA_ARGS__)
181 
182 #endif  // PERFETTO_DLOG_IS_ON()
183 
184 #if PERFETTO_DCHECK_IS_ON()
185 
186 #define PERFETTO_DCHECK(x) PERFETTO_CHECK(x)
187 #define PERFETTO_DFATAL(...) PERFETTO_FATAL(__VA_ARGS__)
188 #define PERFETTO_DFATAL_OR_ELOG(...) PERFETTO_DFATAL(__VA_ARGS__)
189 
190 #else  // PERFETTO_DCHECK_IS_ON()
191 
192 #define PERFETTO_DCHECK(x) \
193   do {                     \
194   } while (false && (x))
195 
196 #define PERFETTO_DFATAL(...) ::perfetto::base::ignore_result(__VA_ARGS__)
197 #define PERFETTO_DFATAL_OR_ELOG(...) PERFETTO_ELOG(__VA_ARGS__)
198 
199 #endif  // PERFETTO_DCHECK_IS_ON()
200 
201 }  // namespace base
202 }  // namespace perfetto
203 
204 #endif  // INCLUDE_PERFETTO_BASE_LOGGING_H_
205