xref: /aosp_15_r20/external/perfetto/src/base/logging.cc (revision 6dbdd20afdafa5e3ca9b8809fa73465d530080dc)
1*6dbdd20aSAndroid Build Coastguard Worker /*
2*6dbdd20aSAndroid Build Coastguard Worker  * Copyright (C) 2019 The Android Open Source Project
3*6dbdd20aSAndroid Build Coastguard Worker  *
4*6dbdd20aSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*6dbdd20aSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*6dbdd20aSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*6dbdd20aSAndroid Build Coastguard Worker  *
8*6dbdd20aSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*6dbdd20aSAndroid Build Coastguard Worker  *
10*6dbdd20aSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*6dbdd20aSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*6dbdd20aSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*6dbdd20aSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*6dbdd20aSAndroid Build Coastguard Worker  * limitations under the License.
15*6dbdd20aSAndroid Build Coastguard Worker  */
16*6dbdd20aSAndroid Build Coastguard Worker 
17*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/base/logging.h"
18*6dbdd20aSAndroid Build Coastguard Worker 
19*6dbdd20aSAndroid Build Coastguard Worker #include <stdarg.h>
20*6dbdd20aSAndroid Build Coastguard Worker #include <stdio.h>
21*6dbdd20aSAndroid Build Coastguard Worker 
22*6dbdd20aSAndroid Build Coastguard Worker #if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
23*6dbdd20aSAndroid Build Coastguard Worker #include <unistd.h>  // For isatty()
24*6dbdd20aSAndroid Build Coastguard Worker #endif
25*6dbdd20aSAndroid Build Coastguard Worker 
26*6dbdd20aSAndroid Build Coastguard Worker #include <atomic>
27*6dbdd20aSAndroid Build Coastguard Worker #include <memory>
28*6dbdd20aSAndroid Build Coastguard Worker 
29*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/base/build_config.h"
30*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/base/time.h"
31*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/ext/base/crash_keys.h"
32*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/ext/base/string_utils.h"
33*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/ext/base/string_view.h"
34*6dbdd20aSAndroid Build Coastguard Worker #include "src/base/log_ring_buffer.h"
35*6dbdd20aSAndroid Build Coastguard Worker 
36*6dbdd20aSAndroid Build Coastguard Worker #if PERFETTO_ENABLE_LOG_RING_BUFFER() && PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
37*6dbdd20aSAndroid Build Coastguard Worker #include <android/set_abort_message.h>
38*6dbdd20aSAndroid Build Coastguard Worker #endif
39*6dbdd20aSAndroid Build Coastguard Worker 
40*6dbdd20aSAndroid Build Coastguard Worker namespace perfetto {
41*6dbdd20aSAndroid Build Coastguard Worker namespace base {
42*6dbdd20aSAndroid Build Coastguard Worker 
43*6dbdd20aSAndroid Build Coastguard Worker namespace {
44*6dbdd20aSAndroid Build Coastguard Worker const char kReset[] = "\x1b[0m";
45*6dbdd20aSAndroid Build Coastguard Worker const char kDefault[] = "\x1b[39m";
46*6dbdd20aSAndroid Build Coastguard Worker const char kDim[] = "\x1b[2m";
47*6dbdd20aSAndroid Build Coastguard Worker const char kRed[] = "\x1b[31m";
48*6dbdd20aSAndroid Build Coastguard Worker const char kBoldGreen[] = "\x1b[1m\x1b[32m";
49*6dbdd20aSAndroid Build Coastguard Worker const char kLightGray[] = "\x1b[90m";
50*6dbdd20aSAndroid Build Coastguard Worker 
51*6dbdd20aSAndroid Build Coastguard Worker std::atomic<LogMessageCallback> g_log_callback{};
52*6dbdd20aSAndroid Build Coastguard Worker 
53*6dbdd20aSAndroid Build Coastguard Worker #if PERFETTO_BUILDFLAG(PERFETTO_STDERR_CRASH_DUMP)
54*6dbdd20aSAndroid Build Coastguard Worker // __attribute__((constructor)) causes a static initializer that automagically
55*6dbdd20aSAndroid Build Coastguard Worker // early runs this function before the main().
56*6dbdd20aSAndroid Build Coastguard Worker void PERFETTO_EXPORT_COMPONENT __attribute__((constructor))
InitDebugCrashReporter()57*6dbdd20aSAndroid Build Coastguard Worker InitDebugCrashReporter() {
58*6dbdd20aSAndroid Build Coastguard Worker   // This function is defined in debug_crash_stack_trace.cc.
59*6dbdd20aSAndroid Build Coastguard Worker   // The dynamic initializer is in logging.cc because logging.cc is included
60*6dbdd20aSAndroid Build Coastguard Worker   // in virtually any target that depends on base. Having it in
61*6dbdd20aSAndroid Build Coastguard Worker   // debug_crash_stack_trace.cc would require figuring out -Wl,whole-archive
62*6dbdd20aSAndroid Build Coastguard Worker   // which is not worth it.
63*6dbdd20aSAndroid Build Coastguard Worker   EnableStacktraceOnCrashForDebug();
64*6dbdd20aSAndroid Build Coastguard Worker }
65*6dbdd20aSAndroid Build Coastguard Worker #endif
66*6dbdd20aSAndroid Build Coastguard Worker 
67*6dbdd20aSAndroid Build Coastguard Worker #if PERFETTO_ENABLE_LOG_RING_BUFFER()
68*6dbdd20aSAndroid Build Coastguard Worker LogRingBuffer g_log_ring_buffer{};
69*6dbdd20aSAndroid Build Coastguard Worker 
70*6dbdd20aSAndroid Build Coastguard Worker // This is global to avoid allocating memory or growing too much the stack
71*6dbdd20aSAndroid Build Coastguard Worker // in MaybeSerializeLastLogsForCrashReporting(), which is called from
72*6dbdd20aSAndroid Build Coastguard Worker // arbitrary code paths hitting PERFETTO_CHECK()/FATAL().
73*6dbdd20aSAndroid Build Coastguard Worker char g_crash_buf[kLogRingBufEntries * kLogRingBufMsgLen];
74*6dbdd20aSAndroid Build Coastguard Worker #endif
75*6dbdd20aSAndroid Build Coastguard Worker 
76*6dbdd20aSAndroid Build Coastguard Worker }  // namespace
77*6dbdd20aSAndroid Build Coastguard Worker 
SetLogMessageCallback(LogMessageCallback callback)78*6dbdd20aSAndroid Build Coastguard Worker void SetLogMessageCallback(LogMessageCallback callback) {
79*6dbdd20aSAndroid Build Coastguard Worker   g_log_callback.store(callback, std::memory_order_relaxed);
80*6dbdd20aSAndroid Build Coastguard Worker }
81*6dbdd20aSAndroid Build Coastguard Worker 
LogMessage(LogLev level,const char * fname,int line,const char * fmt,...)82*6dbdd20aSAndroid Build Coastguard Worker void LogMessage(LogLev level,
83*6dbdd20aSAndroid Build Coastguard Worker                 const char* fname,
84*6dbdd20aSAndroid Build Coastguard Worker                 int line,
85*6dbdd20aSAndroid Build Coastguard Worker                 const char* fmt,
86*6dbdd20aSAndroid Build Coastguard Worker                 ...) {
87*6dbdd20aSAndroid Build Coastguard Worker   char stack_buf[512];
88*6dbdd20aSAndroid Build Coastguard Worker   std::unique_ptr<char[]> large_buf;
89*6dbdd20aSAndroid Build Coastguard Worker   char* log_msg = &stack_buf[0];
90*6dbdd20aSAndroid Build Coastguard Worker   size_t log_msg_len = 0;
91*6dbdd20aSAndroid Build Coastguard Worker 
92*6dbdd20aSAndroid Build Coastguard Worker   // By default use a stack allocated buffer because most log messages are quite
93*6dbdd20aSAndroid Build Coastguard Worker   // short. In rare cases they can be larger (e.g. --help). In those cases we
94*6dbdd20aSAndroid Build Coastguard Worker   // pay the cost of allocating the buffer on the heap.
95*6dbdd20aSAndroid Build Coastguard Worker   for (size_t max_len = sizeof(stack_buf);;) {
96*6dbdd20aSAndroid Build Coastguard Worker     va_list args;
97*6dbdd20aSAndroid Build Coastguard Worker     va_start(args, fmt);
98*6dbdd20aSAndroid Build Coastguard Worker     int res = vsnprintf(log_msg, max_len, fmt, args);
99*6dbdd20aSAndroid Build Coastguard Worker     va_end(args);
100*6dbdd20aSAndroid Build Coastguard Worker 
101*6dbdd20aSAndroid Build Coastguard Worker     // If for any reason the print fails, overwrite the message but still print
102*6dbdd20aSAndroid Build Coastguard Worker     // it. The code below will attach the filename and line, which is still
103*6dbdd20aSAndroid Build Coastguard Worker     // useful.
104*6dbdd20aSAndroid Build Coastguard Worker     if (res < 0) {
105*6dbdd20aSAndroid Build Coastguard Worker       snprintf(log_msg, max_len, "%s", "[printf format error]");
106*6dbdd20aSAndroid Build Coastguard Worker       break;
107*6dbdd20aSAndroid Build Coastguard Worker     }
108*6dbdd20aSAndroid Build Coastguard Worker 
109*6dbdd20aSAndroid Build Coastguard Worker     // if res == max_len, vsnprintf saturated the input buffer. Retry with a
110*6dbdd20aSAndroid Build Coastguard Worker     // larger buffer in that case (within reasonable limits).
111*6dbdd20aSAndroid Build Coastguard Worker     if (res < static_cast<int>(max_len) || max_len >= 128 * 1024) {
112*6dbdd20aSAndroid Build Coastguard Worker       // In case of truncation vsnprintf returns the len that "would have been
113*6dbdd20aSAndroid Build Coastguard Worker       // written if the string was longer", not the actual chars written.
114*6dbdd20aSAndroid Build Coastguard Worker       log_msg_len = std::min(static_cast<size_t>(res), max_len - 1);
115*6dbdd20aSAndroid Build Coastguard Worker       break;
116*6dbdd20aSAndroid Build Coastguard Worker     }
117*6dbdd20aSAndroid Build Coastguard Worker     max_len *= 4;
118*6dbdd20aSAndroid Build Coastguard Worker     large_buf.reset(new char[max_len]);
119*6dbdd20aSAndroid Build Coastguard Worker     log_msg = &large_buf[0];
120*6dbdd20aSAndroid Build Coastguard Worker   }
121*6dbdd20aSAndroid Build Coastguard Worker 
122*6dbdd20aSAndroid Build Coastguard Worker   LogMessageCallback cb = g_log_callback.load(std::memory_order_relaxed);
123*6dbdd20aSAndroid Build Coastguard Worker   if (cb) {
124*6dbdd20aSAndroid Build Coastguard Worker     cb({level, line, fname, log_msg});
125*6dbdd20aSAndroid Build Coastguard Worker     return;
126*6dbdd20aSAndroid Build Coastguard Worker   }
127*6dbdd20aSAndroid Build Coastguard Worker 
128*6dbdd20aSAndroid Build Coastguard Worker   const char* color = kDefault;
129*6dbdd20aSAndroid Build Coastguard Worker   switch (level) {
130*6dbdd20aSAndroid Build Coastguard Worker     case kLogDebug:
131*6dbdd20aSAndroid Build Coastguard Worker       color = kDim;
132*6dbdd20aSAndroid Build Coastguard Worker       break;
133*6dbdd20aSAndroid Build Coastguard Worker     case kLogInfo:
134*6dbdd20aSAndroid Build Coastguard Worker       color = kDefault;
135*6dbdd20aSAndroid Build Coastguard Worker       break;
136*6dbdd20aSAndroid Build Coastguard Worker     case kLogImportant:
137*6dbdd20aSAndroid Build Coastguard Worker       color = kBoldGreen;
138*6dbdd20aSAndroid Build Coastguard Worker       break;
139*6dbdd20aSAndroid Build Coastguard Worker     case kLogError:
140*6dbdd20aSAndroid Build Coastguard Worker       color = kRed;
141*6dbdd20aSAndroid Build Coastguard Worker       break;
142*6dbdd20aSAndroid Build Coastguard Worker   }
143*6dbdd20aSAndroid Build Coastguard Worker 
144*6dbdd20aSAndroid Build Coastguard Worker #if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) &&  \
145*6dbdd20aSAndroid Build Coastguard Worker     !PERFETTO_BUILDFLAG(PERFETTO_OS_WASM) && \
146*6dbdd20aSAndroid Build Coastguard Worker     !PERFETTO_BUILDFLAG(PERFETTO_CHROMIUM_BUILD)
147*6dbdd20aSAndroid Build Coastguard Worker   static const bool use_colors = isatty(STDERR_FILENO);
148*6dbdd20aSAndroid Build Coastguard Worker #else
149*6dbdd20aSAndroid Build Coastguard Worker   static const bool use_colors = false;
150*6dbdd20aSAndroid Build Coastguard Worker #endif
151*6dbdd20aSAndroid Build Coastguard Worker 
152*6dbdd20aSAndroid Build Coastguard Worker   // Formats file.cc:line as a space-padded fixed width string. If the file name
153*6dbdd20aSAndroid Build Coastguard Worker   // |fname| is too long, truncate it on the left-hand side.
154*6dbdd20aSAndroid Build Coastguard Worker   StackString<10> line_str("%d", line);
155*6dbdd20aSAndroid Build Coastguard Worker 
156*6dbdd20aSAndroid Build Coastguard Worker   // 24 will be the width of the file.cc:line column in the log event.
157*6dbdd20aSAndroid Build Coastguard Worker   static constexpr size_t kMaxNameAndLine = 24;
158*6dbdd20aSAndroid Build Coastguard Worker   size_t fname_len = strlen(fname);
159*6dbdd20aSAndroid Build Coastguard Worker   size_t fname_max = kMaxNameAndLine - line_str.len() - 2;  // 2 = ':' + '\0'.
160*6dbdd20aSAndroid Build Coastguard Worker   size_t fname_offset = fname_len <= fname_max ? 0 : fname_len - fname_max;
161*6dbdd20aSAndroid Build Coastguard Worker   StackString<kMaxNameAndLine> file_and_line(
162*6dbdd20aSAndroid Build Coastguard Worker       "%*s:%s", static_cast<int>(fname_max), &fname[fname_offset],
163*6dbdd20aSAndroid Build Coastguard Worker       line_str.c_str());
164*6dbdd20aSAndroid Build Coastguard Worker 
165*6dbdd20aSAndroid Build Coastguard Worker #if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
166*6dbdd20aSAndroid Build Coastguard Worker   // Logcat has already timestamping, don't re-emit it.
167*6dbdd20aSAndroid Build Coastguard Worker   __android_log_print(int{ANDROID_LOG_DEBUG} + level, "perfetto", "%s %s",
168*6dbdd20aSAndroid Build Coastguard Worker                       file_and_line.c_str(), log_msg);
169*6dbdd20aSAndroid Build Coastguard Worker #endif
170*6dbdd20aSAndroid Build Coastguard Worker 
171*6dbdd20aSAndroid Build Coastguard Worker   // When printing on stderr, print also the timestamp. We don't really care
172*6dbdd20aSAndroid Build Coastguard Worker   // about the actual time. We just need some reference clock that can be used
173*6dbdd20aSAndroid Build Coastguard Worker   // to correlated events across differrent processses (e.g. traced and
174*6dbdd20aSAndroid Build Coastguard Worker   // traced_probes). The wall time % 1000 is good enough.
175*6dbdd20aSAndroid Build Coastguard Worker   uint32_t t_ms = static_cast<uint32_t>(GetWallTimeMs().count());
176*6dbdd20aSAndroid Build Coastguard Worker   uint32_t t_sec = t_ms / 1000;
177*6dbdd20aSAndroid Build Coastguard Worker   t_ms -= t_sec * 1000;
178*6dbdd20aSAndroid Build Coastguard Worker   t_sec = t_sec % 1000;
179*6dbdd20aSAndroid Build Coastguard Worker   StackString<32> timestamp("[%03u.%03u] ", t_sec, t_ms);
180*6dbdd20aSAndroid Build Coastguard Worker 
181*6dbdd20aSAndroid Build Coastguard Worker   if (use_colors) {
182*6dbdd20aSAndroid Build Coastguard Worker     fprintf(stderr, "%s%s%s%s %s%s%s\n", kLightGray, timestamp.c_str(),
183*6dbdd20aSAndroid Build Coastguard Worker             file_and_line.c_str(), kReset, color, log_msg, kReset);
184*6dbdd20aSAndroid Build Coastguard Worker   } else {
185*6dbdd20aSAndroid Build Coastguard Worker     fprintf(stderr, "%s%s %s\n", timestamp.c_str(), file_and_line.c_str(),
186*6dbdd20aSAndroid Build Coastguard Worker             log_msg);
187*6dbdd20aSAndroid Build Coastguard Worker   }
188*6dbdd20aSAndroid Build Coastguard Worker 
189*6dbdd20aSAndroid Build Coastguard Worker #if PERFETTO_ENABLE_LOG_RING_BUFFER()
190*6dbdd20aSAndroid Build Coastguard Worker   // Append the message to the ring buffer for crash reporting postmortems.
191*6dbdd20aSAndroid Build Coastguard Worker   StringView timestamp_sv = timestamp.string_view();
192*6dbdd20aSAndroid Build Coastguard Worker   StringView file_and_line_sv = file_and_line.string_view();
193*6dbdd20aSAndroid Build Coastguard Worker   StringView log_msg_sv(log_msg, static_cast<size_t>(log_msg_len));
194*6dbdd20aSAndroid Build Coastguard Worker   g_log_ring_buffer.Append(timestamp_sv, file_and_line_sv, log_msg_sv);
195*6dbdd20aSAndroid Build Coastguard Worker #else
196*6dbdd20aSAndroid Build Coastguard Worker   ignore_result(log_msg_len);
197*6dbdd20aSAndroid Build Coastguard Worker #endif
198*6dbdd20aSAndroid Build Coastguard Worker }
199*6dbdd20aSAndroid Build Coastguard Worker 
200*6dbdd20aSAndroid Build Coastguard Worker #if PERFETTO_ENABLE_LOG_RING_BUFFER()
MaybeSerializeLastLogsForCrashReporting()201*6dbdd20aSAndroid Build Coastguard Worker void MaybeSerializeLastLogsForCrashReporting() {
202*6dbdd20aSAndroid Build Coastguard Worker   // Keep this function minimal. This is called from the watchdog thread, often
203*6dbdd20aSAndroid Build Coastguard Worker   // when the system is thrashing.
204*6dbdd20aSAndroid Build Coastguard Worker 
205*6dbdd20aSAndroid Build Coastguard Worker   // This is racy because two threads could hit a CHECK/FATAL at the same time.
206*6dbdd20aSAndroid Build Coastguard Worker   // But if that happens we have bigger problems, not worth designing around it.
207*6dbdd20aSAndroid Build Coastguard Worker   // The behaviour is still defined in the race case (the string attached to
208*6dbdd20aSAndroid Build Coastguard Worker   // the crash report will contain a mixture of log strings).
209*6dbdd20aSAndroid Build Coastguard Worker   size_t wr = 0;
210*6dbdd20aSAndroid Build Coastguard Worker   wr += SerializeCrashKeys(&g_crash_buf[wr], sizeof(g_crash_buf) - wr);
211*6dbdd20aSAndroid Build Coastguard Worker   wr += g_log_ring_buffer.Read(&g_crash_buf[wr], sizeof(g_crash_buf) - wr);
212*6dbdd20aSAndroid Build Coastguard Worker 
213*6dbdd20aSAndroid Build Coastguard Worker   // Read() null-terminates the string properly. This is just to avoid UB when
214*6dbdd20aSAndroid Build Coastguard Worker   // two threads race on each other (T1 writes a shorter string, T2
215*6dbdd20aSAndroid Build Coastguard Worker   // overwrites the \0 writing a longer string. T1 continues here before T2
216*6dbdd20aSAndroid Build Coastguard Worker   // finishes writing the longer string with the \0 -> boom.
217*6dbdd20aSAndroid Build Coastguard Worker   g_crash_buf[sizeof(g_crash_buf) - 1] = '\0';
218*6dbdd20aSAndroid Build Coastguard Worker 
219*6dbdd20aSAndroid Build Coastguard Worker #if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
220*6dbdd20aSAndroid Build Coastguard Worker   // android_set_abort_message() will cause debuggerd to report the message
221*6dbdd20aSAndroid Build Coastguard Worker   // in the tombstone and in the crash log in logcat.
222*6dbdd20aSAndroid Build Coastguard Worker   // NOTE: android_set_abort_message() can be called only once. This should
223*6dbdd20aSAndroid Build Coastguard Worker   // be called only when we are sure we are about to crash.
224*6dbdd20aSAndroid Build Coastguard Worker   android_set_abort_message(g_crash_buf);
225*6dbdd20aSAndroid Build Coastguard Worker #else
226*6dbdd20aSAndroid Build Coastguard Worker   // Print out the message on stderr on Linux/Mac/Win.
227*6dbdd20aSAndroid Build Coastguard Worker   fputs("\n-----BEGIN PERFETTO PRE-CRASH LOG-----\n", stderr);
228*6dbdd20aSAndroid Build Coastguard Worker   fputs(g_crash_buf, stderr);
229*6dbdd20aSAndroid Build Coastguard Worker   fputs("\n-----END PERFETTO PRE-CRASH LOG-----\n", stderr);
230*6dbdd20aSAndroid Build Coastguard Worker #endif
231*6dbdd20aSAndroid Build Coastguard Worker }
232*6dbdd20aSAndroid Build Coastguard Worker #endif  // PERFETTO_ENABLE_LOG_RING_BUFFER
233*6dbdd20aSAndroid Build Coastguard Worker 
234*6dbdd20aSAndroid Build Coastguard Worker }  // namespace base
235*6dbdd20aSAndroid Build Coastguard Worker }  // namespace perfetto
236