xref: /aosp_15_r20/system/logging/logd/ReplayMessages.cpp (revision 598139dc91b21518d67c408eaea2644226490971)
1*598139dcSAndroid Build Coastguard Worker /*
2*598139dcSAndroid Build Coastguard Worker  * Copyright (C) 2020 The Android Open Source Project
3*598139dcSAndroid Build Coastguard Worker  *
4*598139dcSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*598139dcSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*598139dcSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*598139dcSAndroid Build Coastguard Worker  *
8*598139dcSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*598139dcSAndroid Build Coastguard Worker  *
10*598139dcSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*598139dcSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*598139dcSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*598139dcSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*598139dcSAndroid Build Coastguard Worker  * limitations under the License.
15*598139dcSAndroid Build Coastguard Worker  */
16*598139dcSAndroid Build Coastguard Worker 
17*598139dcSAndroid Build Coastguard Worker #include <inttypes.h>
18*598139dcSAndroid Build Coastguard Worker 
19*598139dcSAndroid Build Coastguard Worker #include <chrono>
20*598139dcSAndroid Build Coastguard Worker #include <map>
21*598139dcSAndroid Build Coastguard Worker 
22*598139dcSAndroid Build Coastguard Worker #include <android-base/file.h>
23*598139dcSAndroid Build Coastguard Worker #include <android-base/mapped_file.h>
24*598139dcSAndroid Build Coastguard Worker #include <android-base/parseint.h>
25*598139dcSAndroid Build Coastguard Worker #include <android-base/strings.h>
26*598139dcSAndroid Build Coastguard Worker #include <android-base/unique_fd.h>
27*598139dcSAndroid Build Coastguard Worker #include <android/log.h>
28*598139dcSAndroid Build Coastguard Worker #include <log/log_time.h>
29*598139dcSAndroid Build Coastguard Worker #include <log/logprint.h>
30*598139dcSAndroid Build Coastguard Worker 
31*598139dcSAndroid Build Coastguard Worker #include "LogBuffer.h"
32*598139dcSAndroid Build Coastguard Worker #include "LogStatistics.h"
33*598139dcSAndroid Build Coastguard Worker #include "PruneList.h"
34*598139dcSAndroid Build Coastguard Worker #include "RecordedLogMessage.h"
35*598139dcSAndroid Build Coastguard Worker #include "SerializedLogBuffer.h"
36*598139dcSAndroid Build Coastguard Worker #include "SimpleLogBuffer.h"
37*598139dcSAndroid Build Coastguard Worker 
38*598139dcSAndroid Build Coastguard Worker using android::base::MappedFile;
39*598139dcSAndroid Build Coastguard Worker using android::base::ParseInt;
40*598139dcSAndroid Build Coastguard Worker using android::base::ParseUint;
41*598139dcSAndroid Build Coastguard Worker using android::base::Split;
42*598139dcSAndroid Build Coastguard Worker 
uidToName(uid_t)43*598139dcSAndroid Build Coastguard Worker char* android::uidToName(uid_t) {
44*598139dcSAndroid Build Coastguard Worker     return nullptr;
45*598139dcSAndroid Build Coastguard Worker }
46*598139dcSAndroid Build Coastguard Worker 
GetPrivateDirty()47*598139dcSAndroid Build Coastguard Worker static size_t GetPrivateDirty() {
48*598139dcSAndroid Build Coastguard Worker     // Allocate once and hope that we don't need to reallocate >40000, to prevent heap fragmentation
49*598139dcSAndroid Build Coastguard Worker     static std::string smaps(40000, '\0');
50*598139dcSAndroid Build Coastguard Worker     android::base::ReadFileToString("/proc/self/smaps", &smaps);
51*598139dcSAndroid Build Coastguard Worker 
52*598139dcSAndroid Build Coastguard Worker     size_t result = 0;
53*598139dcSAndroid Build Coastguard Worker     size_t base = 0;
54*598139dcSAndroid Build Coastguard Worker     size_t found;
55*598139dcSAndroid Build Coastguard Worker     while (true) {
56*598139dcSAndroid Build Coastguard Worker         found = smaps.find("Private_Dirty:", base);
57*598139dcSAndroid Build Coastguard Worker         if (found == smaps.npos) break;
58*598139dcSAndroid Build Coastguard Worker 
59*598139dcSAndroid Build Coastguard Worker         found += sizeof("Private_Dirty:");
60*598139dcSAndroid Build Coastguard Worker 
61*598139dcSAndroid Build Coastguard Worker         result += atoi(&smaps[found]);
62*598139dcSAndroid Build Coastguard Worker 
63*598139dcSAndroid Build Coastguard Worker         base = found + 1;
64*598139dcSAndroid Build Coastguard Worker     }
65*598139dcSAndroid Build Coastguard Worker 
66*598139dcSAndroid Build Coastguard Worker     return result;
67*598139dcSAndroid Build Coastguard Worker }
68*598139dcSAndroid Build Coastguard Worker 
GetLogFormat()69*598139dcSAndroid Build Coastguard Worker static AndroidLogFormat* GetLogFormat() {
70*598139dcSAndroid Build Coastguard Worker     static AndroidLogFormat* format = [] {
71*598139dcSAndroid Build Coastguard Worker         auto* format = android_log_format_new();
72*598139dcSAndroid Build Coastguard Worker         android_log_setPrintFormat(format, android_log_formatFromString("threadtime"));
73*598139dcSAndroid Build Coastguard Worker         android_log_setPrintFormat(format, android_log_formatFromString("uid"));
74*598139dcSAndroid Build Coastguard Worker         return format;
75*598139dcSAndroid Build Coastguard Worker     }();
76*598139dcSAndroid Build Coastguard Worker     return format;
77*598139dcSAndroid Build Coastguard Worker }
78*598139dcSAndroid Build Coastguard Worker 
PrintMessage(struct log_msg * buf)79*598139dcSAndroid Build Coastguard Worker static void PrintMessage(struct log_msg* buf) {
80*598139dcSAndroid Build Coastguard Worker     bool is_binary =
81*598139dcSAndroid Build Coastguard Worker             buf->id() == LOG_ID_EVENTS || buf->id() == LOG_ID_STATS || buf->id() == LOG_ID_SECURITY;
82*598139dcSAndroid Build Coastguard Worker 
83*598139dcSAndroid Build Coastguard Worker     AndroidLogEntry entry;
84*598139dcSAndroid Build Coastguard Worker     int err;
85*598139dcSAndroid Build Coastguard Worker     if (is_binary) {
86*598139dcSAndroid Build Coastguard Worker         char binaryMsgBuf[1024];
87*598139dcSAndroid Build Coastguard Worker         err = android_log_processBinaryLogBuffer(&buf->entry, &entry, nullptr, binaryMsgBuf,
88*598139dcSAndroid Build Coastguard Worker                                                  sizeof(binaryMsgBuf));
89*598139dcSAndroid Build Coastguard Worker     } else {
90*598139dcSAndroid Build Coastguard Worker         err = android_log_processLogBuffer(&buf->entry, &entry);
91*598139dcSAndroid Build Coastguard Worker     }
92*598139dcSAndroid Build Coastguard Worker     if (err < 0) {
93*598139dcSAndroid Build Coastguard Worker         fprintf(stderr, "Error parsing log message\n");
94*598139dcSAndroid Build Coastguard Worker     }
95*598139dcSAndroid Build Coastguard Worker 
96*598139dcSAndroid Build Coastguard Worker     android_log_printLogLine(GetLogFormat(), stdout, &entry);
97*598139dcSAndroid Build Coastguard Worker }
98*598139dcSAndroid Build Coastguard Worker 
GetFirstTimeStamp(const MappedFile & recorded_messages)99*598139dcSAndroid Build Coastguard Worker static log_time GetFirstTimeStamp(const MappedFile& recorded_messages) {
100*598139dcSAndroid Build Coastguard Worker     if (sizeof(RecordedLogMessage) >= recorded_messages.size()) {
101*598139dcSAndroid Build Coastguard Worker         fprintf(stderr, "At least one log message must be present in the input\n");
102*598139dcSAndroid Build Coastguard Worker         exit(1);
103*598139dcSAndroid Build Coastguard Worker     }
104*598139dcSAndroid Build Coastguard Worker 
105*598139dcSAndroid Build Coastguard Worker     auto* meta = reinterpret_cast<RecordedLogMessage*>(recorded_messages.data());
106*598139dcSAndroid Build Coastguard Worker     return meta->realtime;
107*598139dcSAndroid Build Coastguard Worker }
108*598139dcSAndroid Build Coastguard Worker 
BuffersToLogMask(const char * buffers)109*598139dcSAndroid Build Coastguard Worker static LogMask BuffersToLogMask(const char* buffers) {
110*598139dcSAndroid Build Coastguard Worker     if (buffers == nullptr || !strcmp(buffers, "all")) {
111*598139dcSAndroid Build Coastguard Worker         return kLogMaskAll;
112*598139dcSAndroid Build Coastguard Worker     }
113*598139dcSAndroid Build Coastguard Worker     auto string_ids = Split(buffers, ",");
114*598139dcSAndroid Build Coastguard Worker     LogMask log_mask = 0;
115*598139dcSAndroid Build Coastguard Worker     for (const auto& string_id : string_ids) {
116*598139dcSAndroid Build Coastguard Worker         int buffer_id;
117*598139dcSAndroid Build Coastguard Worker         if (!ParseInt(string_id, &buffer_id, 0, 7)) {
118*598139dcSAndroid Build Coastguard Worker             fprintf(stderr, "Could not parse buffer_id '%s'\n", string_id.c_str());
119*598139dcSAndroid Build Coastguard Worker             exit(1);
120*598139dcSAndroid Build Coastguard Worker         }
121*598139dcSAndroid Build Coastguard Worker         log_mask |= 1 << buffer_id;
122*598139dcSAndroid Build Coastguard Worker     }
123*598139dcSAndroid Build Coastguard Worker     return log_mask;
124*598139dcSAndroid Build Coastguard Worker }
125*598139dcSAndroid Build Coastguard Worker 
126*598139dcSAndroid Build Coastguard Worker class StdoutWriter : public LogWriter {
127*598139dcSAndroid Build Coastguard Worker   public:
StdoutWriter()128*598139dcSAndroid Build Coastguard Worker     StdoutWriter() : LogWriter(0, true) {}
Write(const logger_entry & entry,const char * message)129*598139dcSAndroid Build Coastguard Worker     bool Write(const logger_entry& entry, const char* message) override {
130*598139dcSAndroid Build Coastguard Worker         struct log_msg log_msg;
131*598139dcSAndroid Build Coastguard Worker         log_msg.entry = entry;
132*598139dcSAndroid Build Coastguard Worker         if (log_msg.entry.len > LOGGER_ENTRY_MAX_PAYLOAD) {
133*598139dcSAndroid Build Coastguard Worker             fprintf(stderr, "payload too large %" PRIu16, log_msg.entry.len);
134*598139dcSAndroid Build Coastguard Worker             exit(1);
135*598139dcSAndroid Build Coastguard Worker         }
136*598139dcSAndroid Build Coastguard Worker         memcpy(log_msg.msg(), message, log_msg.entry.len);
137*598139dcSAndroid Build Coastguard Worker 
138*598139dcSAndroid Build Coastguard Worker         PrintMessage(&log_msg);
139*598139dcSAndroid Build Coastguard Worker 
140*598139dcSAndroid Build Coastguard Worker         return true;
141*598139dcSAndroid Build Coastguard Worker     }
142*598139dcSAndroid Build Coastguard Worker 
Shutdown()143*598139dcSAndroid Build Coastguard Worker     void Shutdown() override {
144*598139dcSAndroid Build Coastguard Worker         fprintf(stderr, "LogWriter::Shutdown() called\n");
145*598139dcSAndroid Build Coastguard Worker         exit(1);
146*598139dcSAndroid Build Coastguard Worker     }
147*598139dcSAndroid Build Coastguard Worker 
name() const148*598139dcSAndroid Build Coastguard Worker     std::string name() const override { return "stdout writer"; }
149*598139dcSAndroid Build Coastguard Worker };
150*598139dcSAndroid Build Coastguard Worker 
151*598139dcSAndroid Build Coastguard Worker class Operation {
152*598139dcSAndroid Build Coastguard Worker   public:
~Operation()153*598139dcSAndroid Build Coastguard Worker     virtual ~Operation() {}
154*598139dcSAndroid Build Coastguard Worker 
Begin()155*598139dcSAndroid Build Coastguard Worker     virtual void Begin() {}
156*598139dcSAndroid Build Coastguard Worker     virtual void Log(const RecordedLogMessage& meta, const char* msg) = 0;
End()157*598139dcSAndroid Build Coastguard Worker     virtual void End() {}
158*598139dcSAndroid Build Coastguard Worker };
159*598139dcSAndroid Build Coastguard Worker 
160*598139dcSAndroid Build Coastguard Worker class PrintInteresting : public Operation {
161*598139dcSAndroid Build Coastguard Worker   public:
PrintInteresting(log_time first_log_timestamp)162*598139dcSAndroid Build Coastguard Worker     PrintInteresting(log_time first_log_timestamp)
163*598139dcSAndroid Build Coastguard Worker         : stats_simple_{false, false, first_log_timestamp},
164*598139dcSAndroid Build Coastguard Worker           stats_serialized_{false, true, first_log_timestamp} {}
165*598139dcSAndroid Build Coastguard Worker 
Begin()166*598139dcSAndroid Build Coastguard Worker     void Begin() override {
167*598139dcSAndroid Build Coastguard Worker         printf("message_count,simple_main_lines,simple_radio_lines,simple_events_lines,simple_"
168*598139dcSAndroid Build Coastguard Worker                "system_lines,simple_crash_lines,simple_stats_lines,simple_security_lines,simple_"
169*598139dcSAndroid Build Coastguard Worker                "kernel_lines,simple_main_size,simple_radio_size,simple_events_size,simple_system_"
170*598139dcSAndroid Build Coastguard Worker                "size,simple_crash_size,simple_stats_size,simple_security_size,simple_kernel_size,"
171*598139dcSAndroid Build Coastguard Worker                "simple_main_overhead,simple_radio_overhead,simple_events_overhead,simple_system_"
172*598139dcSAndroid Build Coastguard Worker                "overhead,simple_crash_overhead,simple_stats_overhead,simple_security_overhead,"
173*598139dcSAndroid Build Coastguard Worker                "simple_kernel_overhead,simple_main_range,simple_radio_range,simple_events_range,"
174*598139dcSAndroid Build Coastguard Worker                "simple_system_range,simple_crash_range,simple_stats_range,simple_security_range,"
175*598139dcSAndroid Build Coastguard Worker                "simple_kernel_range,"
176*598139dcSAndroid Build Coastguard Worker                "serialized_main_lines,serialized_radio_lines,serialized_events_lines,serialized_"
177*598139dcSAndroid Build Coastguard Worker                "system_lines,serialized_crash_lines,serialized_stats_lines,serialized_security_"
178*598139dcSAndroid Build Coastguard Worker                "lines,serialized_"
179*598139dcSAndroid Build Coastguard Worker                "kernel_lines,serialized_main_size,serialized_radio_size,serialized_events_size,"
180*598139dcSAndroid Build Coastguard Worker                "serialized_system_"
181*598139dcSAndroid Build Coastguard Worker                "size,serialized_crash_size,serialized_stats_size,serialized_security_size,"
182*598139dcSAndroid Build Coastguard Worker                "serialized_kernel_size,"
183*598139dcSAndroid Build Coastguard Worker                "serialized_main_overhead,serialized_radio_overhead,serialized_events_overhead,"
184*598139dcSAndroid Build Coastguard Worker                "serialized_system_"
185*598139dcSAndroid Build Coastguard Worker                "overhead,serialized_crash_overhead,serialized_stats_overhead,serialized_security_"
186*598139dcSAndroid Build Coastguard Worker                "overhead,"
187*598139dcSAndroid Build Coastguard Worker                "serialized_kernel_overhead,serialized_main_range,serialized_radio_range,serialized_"
188*598139dcSAndroid Build Coastguard Worker                "events_range,"
189*598139dcSAndroid Build Coastguard Worker                "serialized_system_range,serialized_crash_range,serialized_stats_range,serialized_"
190*598139dcSAndroid Build Coastguard Worker                "security_range,"
191*598139dcSAndroid Build Coastguard Worker                "serialized_kernel_range\n");
192*598139dcSAndroid Build Coastguard Worker     }
193*598139dcSAndroid Build Coastguard Worker 
Log(const RecordedLogMessage & meta,const char * msg)194*598139dcSAndroid Build Coastguard Worker     void Log(const RecordedLogMessage& meta, const char* msg) override {
195*598139dcSAndroid Build Coastguard Worker         simple_log_buffer_.Log(static_cast<log_id_t>(meta.log_id), meta.realtime, meta.uid,
196*598139dcSAndroid Build Coastguard Worker                                meta.pid, meta.tid, msg, meta.msg_len);
197*598139dcSAndroid Build Coastguard Worker 
198*598139dcSAndroid Build Coastguard Worker         serialized_log_buffer_.Log(static_cast<log_id_t>(meta.log_id), meta.realtime, meta.uid,
199*598139dcSAndroid Build Coastguard Worker                                    meta.pid, meta.tid, msg, meta.msg_len);
200*598139dcSAndroid Build Coastguard Worker 
201*598139dcSAndroid Build Coastguard Worker         if (num_message_ % 10000 == 0) {
202*598139dcSAndroid Build Coastguard Worker             printf("%" PRIu64 ",%s,%s\n", num_message_, stats_simple_.ReportInteresting().c_str(),
203*598139dcSAndroid Build Coastguard Worker                    stats_serialized_.ReportInteresting().c_str());
204*598139dcSAndroid Build Coastguard Worker         }
205*598139dcSAndroid Build Coastguard Worker 
206*598139dcSAndroid Build Coastguard Worker         num_message_++;
207*598139dcSAndroid Build Coastguard Worker     }
208*598139dcSAndroid Build Coastguard Worker 
209*598139dcSAndroid Build Coastguard Worker   private:
210*598139dcSAndroid Build Coastguard Worker     uint64_t num_message_ = 1;
211*598139dcSAndroid Build Coastguard Worker 
212*598139dcSAndroid Build Coastguard Worker     LogReaderList reader_list_;
213*598139dcSAndroid Build Coastguard Worker     LogTags tags_;
214*598139dcSAndroid Build Coastguard Worker     PruneList prune_list_;
215*598139dcSAndroid Build Coastguard Worker 
216*598139dcSAndroid Build Coastguard Worker     LogStatistics stats_simple_;
217*598139dcSAndroid Build Coastguard Worker     SimpleLogBuffer simple_log_buffer_{&reader_list_, &tags_, &stats_simple_};
218*598139dcSAndroid Build Coastguard Worker 
219*598139dcSAndroid Build Coastguard Worker     LogStatistics stats_serialized_;
220*598139dcSAndroid Build Coastguard Worker     SerializedLogBuffer serialized_log_buffer_{&reader_list_, &tags_, &stats_serialized_};
221*598139dcSAndroid Build Coastguard Worker };
222*598139dcSAndroid Build Coastguard Worker 
223*598139dcSAndroid Build Coastguard Worker class SingleBufferOperation : public Operation {
224*598139dcSAndroid Build Coastguard Worker   public:
SingleBufferOperation(log_time first_log_timestamp,const char * buffer)225*598139dcSAndroid Build Coastguard Worker     SingleBufferOperation(log_time first_log_timestamp, const char* buffer) {
226*598139dcSAndroid Build Coastguard Worker         if (!strcmp(buffer, "simple")) {
227*598139dcSAndroid Build Coastguard Worker             stats_.reset(new LogStatistics{false, false, first_log_timestamp});
228*598139dcSAndroid Build Coastguard Worker             log_buffer_.reset(new SimpleLogBuffer(&reader_list_, &tags_, stats_.get()));
229*598139dcSAndroid Build Coastguard Worker         } else if (!strcmp(buffer, "serialized")) {
230*598139dcSAndroid Build Coastguard Worker             stats_.reset(new LogStatistics{false, true, first_log_timestamp});
231*598139dcSAndroid Build Coastguard Worker             log_buffer_.reset(new SerializedLogBuffer(&reader_list_, &tags_, stats_.get()));
232*598139dcSAndroid Build Coastguard Worker         } else {
233*598139dcSAndroid Build Coastguard Worker             fprintf(stderr, "invalid log buffer type '%s'\n", buffer);
234*598139dcSAndroid Build Coastguard Worker             abort();
235*598139dcSAndroid Build Coastguard Worker         }
236*598139dcSAndroid Build Coastguard Worker     }
237*598139dcSAndroid Build Coastguard Worker 
Log(const RecordedLogMessage & meta,const char * msg)238*598139dcSAndroid Build Coastguard Worker     void Log(const RecordedLogMessage& meta, const char* msg) override {
239*598139dcSAndroid Build Coastguard Worker         PreOperation();
240*598139dcSAndroid Build Coastguard Worker         log_buffer_->Log(static_cast<log_id_t>(meta.log_id), meta.realtime, meta.uid, meta.pid,
241*598139dcSAndroid Build Coastguard Worker                          meta.tid, msg, meta.msg_len);
242*598139dcSAndroid Build Coastguard Worker 
243*598139dcSAndroid Build Coastguard Worker         Operation();
244*598139dcSAndroid Build Coastguard Worker 
245*598139dcSAndroid Build Coastguard Worker         num_message_++;
246*598139dcSAndroid Build Coastguard Worker     }
247*598139dcSAndroid Build Coastguard Worker 
PreOperation()248*598139dcSAndroid Build Coastguard Worker     virtual void PreOperation() {}
Operation()249*598139dcSAndroid Build Coastguard Worker     virtual void Operation() {}
250*598139dcSAndroid Build Coastguard Worker 
251*598139dcSAndroid Build Coastguard Worker   protected:
252*598139dcSAndroid Build Coastguard Worker     uint64_t num_message_ = 1;
253*598139dcSAndroid Build Coastguard Worker 
254*598139dcSAndroid Build Coastguard Worker     LogReaderList reader_list_;
255*598139dcSAndroid Build Coastguard Worker     LogTags tags_;
256*598139dcSAndroid Build Coastguard Worker     PruneList prune_list_;
257*598139dcSAndroid Build Coastguard Worker 
258*598139dcSAndroid Build Coastguard Worker     std::unique_ptr<LogStatistics> stats_;
259*598139dcSAndroid Build Coastguard Worker     std::unique_ptr<LogBuffer> log_buffer_;
260*598139dcSAndroid Build Coastguard Worker };
261*598139dcSAndroid Build Coastguard Worker 
262*598139dcSAndroid Build Coastguard Worker class PrintMemory : public SingleBufferOperation {
263*598139dcSAndroid Build Coastguard Worker   public:
PrintMemory(log_time first_log_timestamp,const char * buffer)264*598139dcSAndroid Build Coastguard Worker     PrintMemory(log_time first_log_timestamp, const char* buffer)
265*598139dcSAndroid Build Coastguard Worker         : SingleBufferOperation(first_log_timestamp, buffer) {}
266*598139dcSAndroid Build Coastguard Worker 
Operation()267*598139dcSAndroid Build Coastguard Worker     void Operation() override {
268*598139dcSAndroid Build Coastguard Worker         if (num_message_ % 100000 == 0) {
269*598139dcSAndroid Build Coastguard Worker             printf("%" PRIu64 ",%s\n", num_message_,
270*598139dcSAndroid Build Coastguard Worker                    std::to_string(GetPrivateDirty() - baseline_memory_).c_str());
271*598139dcSAndroid Build Coastguard Worker         }
272*598139dcSAndroid Build Coastguard Worker     }
273*598139dcSAndroid Build Coastguard Worker 
274*598139dcSAndroid Build Coastguard Worker   private:
275*598139dcSAndroid Build Coastguard Worker     size_t baseline_memory_ = GetPrivateDirty();
276*598139dcSAndroid Build Coastguard Worker };
277*598139dcSAndroid Build Coastguard Worker 
278*598139dcSAndroid Build Coastguard Worker class PrintLogs : public SingleBufferOperation {
279*598139dcSAndroid Build Coastguard Worker   public:
PrintLogs(log_time first_log_timestamp,const char * buffer,const char * buffers,const char * print_point)280*598139dcSAndroid Build Coastguard Worker     PrintLogs(log_time first_log_timestamp, const char* buffer, const char* buffers,
281*598139dcSAndroid Build Coastguard Worker               const char* print_point)
282*598139dcSAndroid Build Coastguard Worker         : SingleBufferOperation(first_log_timestamp, buffer) {
283*598139dcSAndroid Build Coastguard Worker         mask_ = BuffersToLogMask(buffers);
284*598139dcSAndroid Build Coastguard Worker         if (print_point != nullptr) {
285*598139dcSAndroid Build Coastguard Worker             uint64_t result = 0;
286*598139dcSAndroid Build Coastguard Worker             if (!ParseUint(print_point, &result)) {
287*598139dcSAndroid Build Coastguard Worker                 fprintf(stderr, "Could not parse print point '%s'\n", print_point);
288*598139dcSAndroid Build Coastguard Worker                 exit(1);
289*598139dcSAndroid Build Coastguard Worker             }
290*598139dcSAndroid Build Coastguard Worker             print_point_ = result;
291*598139dcSAndroid Build Coastguard Worker         }
292*598139dcSAndroid Build Coastguard Worker     }
293*598139dcSAndroid Build Coastguard Worker 
Operation()294*598139dcSAndroid Build Coastguard Worker     void Operation() override {
295*598139dcSAndroid Build Coastguard Worker         if (print_point_ && num_message_ >= *print_point_) {
296*598139dcSAndroid Build Coastguard Worker             End();
297*598139dcSAndroid Build Coastguard Worker             exit(0);
298*598139dcSAndroid Build Coastguard Worker         }
299*598139dcSAndroid Build Coastguard Worker     }
300*598139dcSAndroid Build Coastguard Worker 
End()301*598139dcSAndroid Build Coastguard Worker     void End() override {
302*598139dcSAndroid Build Coastguard Worker         auto lock = std::lock_guard{logd_lock};
303*598139dcSAndroid Build Coastguard Worker         std::unique_ptr<LogWriter> test_writer(new StdoutWriter());
304*598139dcSAndroid Build Coastguard Worker         std::unique_ptr<FlushToState> flush_to_state = log_buffer_->CreateFlushToState(1, mask_);
305*598139dcSAndroid Build Coastguard Worker         log_buffer_->FlushTo(test_writer.get(), *flush_to_state, nullptr);
306*598139dcSAndroid Build Coastguard Worker 
307*598139dcSAndroid Build Coastguard Worker         auto stats_string = stats_->Format(0, 0, mask_);
308*598139dcSAndroid Build Coastguard Worker         printf("%s\n", stats_string.c_str());
309*598139dcSAndroid Build Coastguard Worker     }
310*598139dcSAndroid Build Coastguard Worker 
311*598139dcSAndroid Build Coastguard Worker   private:
312*598139dcSAndroid Build Coastguard Worker     LogMask mask_ = kLogMaskAll;
313*598139dcSAndroid Build Coastguard Worker     std::optional<uint64_t> print_point_;
314*598139dcSAndroid Build Coastguard Worker };
315*598139dcSAndroid Build Coastguard Worker 
316*598139dcSAndroid Build Coastguard Worker class PrintLatency : public SingleBufferOperation {
317*598139dcSAndroid Build Coastguard Worker   public:
PrintLatency(log_time first_log_timestamp,const char * buffer)318*598139dcSAndroid Build Coastguard Worker     PrintLatency(log_time first_log_timestamp, const char* buffer)
319*598139dcSAndroid Build Coastguard Worker         : SingleBufferOperation(first_log_timestamp, buffer) {}
320*598139dcSAndroid Build Coastguard Worker 
PreOperation()321*598139dcSAndroid Build Coastguard Worker     void PreOperation() override { operation_start_ = std::chrono::steady_clock::now(); }
322*598139dcSAndroid Build Coastguard Worker 
Operation()323*598139dcSAndroid Build Coastguard Worker     void Operation() override {
324*598139dcSAndroid Build Coastguard Worker         auto end = std::chrono::steady_clock::now();
325*598139dcSAndroid Build Coastguard Worker         auto duration = (end - operation_start_).count();
326*598139dcSAndroid Build Coastguard Worker         durations_.emplace_back(duration);
327*598139dcSAndroid Build Coastguard Worker     }
328*598139dcSAndroid Build Coastguard Worker 
End()329*598139dcSAndroid Build Coastguard Worker     void End() override {
330*598139dcSAndroid Build Coastguard Worker         std::sort(durations_.begin(), durations_.end());
331*598139dcSAndroid Build Coastguard Worker         auto q1 = durations_.size() / 4;
332*598139dcSAndroid Build Coastguard Worker         auto q2 = durations_.size() / 2;
333*598139dcSAndroid Build Coastguard Worker         auto q3 = 3 * durations_.size() / 4;
334*598139dcSAndroid Build Coastguard Worker 
335*598139dcSAndroid Build Coastguard Worker         auto p95 = 95 * durations_.size() / 100;
336*598139dcSAndroid Build Coastguard Worker         auto p99 = 99 * durations_.size() / 100;
337*598139dcSAndroid Build Coastguard Worker         auto p9999 = 9999 * durations_.size() / 10000;
338*598139dcSAndroid Build Coastguard Worker 
339*598139dcSAndroid Build Coastguard Worker         printf("q1: %lld q2: %lld q3: %lld  p95: %lld p99: %lld p99.99: %lld  max: %lld\n",
340*598139dcSAndroid Build Coastguard Worker                durations_[q1], durations_[q2], durations_[q3], durations_[p95], durations_[p99],
341*598139dcSAndroid Build Coastguard Worker                durations_[p9999], durations_.back());
342*598139dcSAndroid Build Coastguard Worker     }
343*598139dcSAndroid Build Coastguard Worker 
344*598139dcSAndroid Build Coastguard Worker   private:
345*598139dcSAndroid Build Coastguard Worker     std::chrono::steady_clock::time_point operation_start_;
346*598139dcSAndroid Build Coastguard Worker     std::vector<long long> durations_;
347*598139dcSAndroid Build Coastguard Worker };
348*598139dcSAndroid Build Coastguard Worker 
349*598139dcSAndroid Build Coastguard Worker class PrintAllLogs : public SingleBufferOperation {
350*598139dcSAndroid Build Coastguard Worker   public:
PrintAllLogs(log_time first_log_timestamp,const char * buffer,const char * buffers)351*598139dcSAndroid Build Coastguard Worker     PrintAllLogs(log_time first_log_timestamp, const char* buffer, const char* buffers)
352*598139dcSAndroid Build Coastguard Worker         : SingleBufferOperation(first_log_timestamp, buffer) {
353*598139dcSAndroid Build Coastguard Worker         LogMask mask = BuffersToLogMask(buffers);
354*598139dcSAndroid Build Coastguard Worker         auto lock = std::unique_lock{logd_lock};
355*598139dcSAndroid Build Coastguard Worker         std::unique_ptr<LogWriter> stdout_writer(new StdoutWriter());
356*598139dcSAndroid Build Coastguard Worker         std::unique_ptr<LogReaderThread> log_reader(
357*598139dcSAndroid Build Coastguard Worker                 new LogReaderThread(log_buffer_.get(), &reader_list_, std::move(stdout_writer),
358*598139dcSAndroid Build Coastguard Worker                                     false, 0, mask, 0, {}, 1, {}));
359*598139dcSAndroid Build Coastguard Worker         reader_list_.AddAndRunThread(std::move(log_reader));
360*598139dcSAndroid Build Coastguard Worker     }
361*598139dcSAndroid Build Coastguard Worker 
Operation()362*598139dcSAndroid Build Coastguard Worker     void Operation() override {
363*598139dcSAndroid Build Coastguard Worker         // If the rate of reading logs is slower than the rate of incoming logs, then the reader
364*598139dcSAndroid Build Coastguard Worker         // thread is disconnected to not overflow log buffers, therefore we artificially slow down
365*598139dcSAndroid Build Coastguard Worker         // the incoming log rate.
366*598139dcSAndroid Build Coastguard Worker         usleep(100);
367*598139dcSAndroid Build Coastguard Worker     }
368*598139dcSAndroid Build Coastguard Worker 
End()369*598139dcSAndroid Build Coastguard Worker     void End() override {
370*598139dcSAndroid Build Coastguard Worker         // Release the reader thread.
371*598139dcSAndroid Build Coastguard Worker         {
372*598139dcSAndroid Build Coastguard Worker             auto lock = std::lock_guard{logd_lock};
373*598139dcSAndroid Build Coastguard Worker             reader_list_.running_reader_threads().back()->Release();
374*598139dcSAndroid Build Coastguard Worker         }
375*598139dcSAndroid Build Coastguard Worker 
376*598139dcSAndroid Build Coastguard Worker         // Wait until it has deleted itself.
377*598139dcSAndroid Build Coastguard Worker         while (true) {
378*598139dcSAndroid Build Coastguard Worker             usleep(500);
379*598139dcSAndroid Build Coastguard Worker             auto lock = std::lock_guard{logd_lock};
380*598139dcSAndroid Build Coastguard Worker             if (reader_list_.running_reader_threads().size() == 0) {
381*598139dcSAndroid Build Coastguard Worker                 break;
382*598139dcSAndroid Build Coastguard Worker             }
383*598139dcSAndroid Build Coastguard Worker         }
384*598139dcSAndroid Build Coastguard Worker     }
385*598139dcSAndroid Build Coastguard Worker };
386*598139dcSAndroid Build Coastguard Worker 
main(int argc,char ** argv)387*598139dcSAndroid Build Coastguard Worker int main(int argc, char** argv) {
388*598139dcSAndroid Build Coastguard Worker     if (argc < 3) {
389*598139dcSAndroid Build Coastguard Worker         fprintf(stderr, "Usage: %s FILE OPERATION [BUFFER] [OPTIONS]\n", argv[0]);
390*598139dcSAndroid Build Coastguard Worker         return 1;
391*598139dcSAndroid Build Coastguard Worker     }
392*598139dcSAndroid Build Coastguard Worker 
393*598139dcSAndroid Build Coastguard Worker     if (strcmp(argv[2], "interesting") != 0 && argc < 4) {
394*598139dcSAndroid Build Coastguard Worker         fprintf(stderr, "Operations other than 'interesting' require a BUFFER argument\n");
395*598139dcSAndroid Build Coastguard Worker         return 1;
396*598139dcSAndroid Build Coastguard Worker     }
397*598139dcSAndroid Build Coastguard Worker 
398*598139dcSAndroid Build Coastguard Worker     int recorded_messages_fd = open(argv[1], O_RDONLY);
399*598139dcSAndroid Build Coastguard Worker     if (recorded_messages_fd == -1) {
400*598139dcSAndroid Build Coastguard Worker         fprintf(stderr, "Couldn't open input file\n");
401*598139dcSAndroid Build Coastguard Worker         return 1;
402*598139dcSAndroid Build Coastguard Worker     }
403*598139dcSAndroid Build Coastguard Worker     struct stat fd_stat;
404*598139dcSAndroid Build Coastguard Worker     if (fstat(recorded_messages_fd, &fd_stat) != 0) {
405*598139dcSAndroid Build Coastguard Worker         fprintf(stderr, "Couldn't fstat input file\n");
406*598139dcSAndroid Build Coastguard Worker         return 1;
407*598139dcSAndroid Build Coastguard Worker     }
408*598139dcSAndroid Build Coastguard Worker     auto recorded_messages = MappedFile::FromFd(recorded_messages_fd, 0,
409*598139dcSAndroid Build Coastguard Worker                                                 static_cast<size_t>(fd_stat.st_size), PROT_READ);
410*598139dcSAndroid Build Coastguard Worker     if (recorded_messages == nullptr) {
411*598139dcSAndroid Build Coastguard Worker         fprintf(stderr, "Couldn't mmap input file\n");
412*598139dcSAndroid Build Coastguard Worker         return 1;
413*598139dcSAndroid Build Coastguard Worker     }
414*598139dcSAndroid Build Coastguard Worker 
415*598139dcSAndroid Build Coastguard Worker     // LogStatistics typically uses 'now()' to initialize its log range state, but this doesn't work
416*598139dcSAndroid Build Coastguard Worker     // when replaying older logs, so we instead give it the timestamp from the first log.
417*598139dcSAndroid Build Coastguard Worker     log_time first_log_timestamp = GetFirstTimeStamp(*recorded_messages);
418*598139dcSAndroid Build Coastguard Worker 
419*598139dcSAndroid Build Coastguard Worker     std::unique_ptr<Operation> operation;
420*598139dcSAndroid Build Coastguard Worker     if (!strcmp(argv[2], "interesting")) {
421*598139dcSAndroid Build Coastguard Worker         operation.reset(new PrintInteresting(first_log_timestamp));
422*598139dcSAndroid Build Coastguard Worker     } else if (!strcmp(argv[2], "memory_usage")) {
423*598139dcSAndroid Build Coastguard Worker         operation.reset(new PrintMemory(first_log_timestamp, argv[3]));
424*598139dcSAndroid Build Coastguard Worker     } else if (!strcmp(argv[2], "latency")) {
425*598139dcSAndroid Build Coastguard Worker         operation.reset(new PrintLatency(first_log_timestamp, argv[3]));
426*598139dcSAndroid Build Coastguard Worker     } else if (!strcmp(argv[2], "print_logs")) {
427*598139dcSAndroid Build Coastguard Worker         operation.reset(new PrintLogs(first_log_timestamp, argv[3], argc > 4 ? argv[4] : nullptr,
428*598139dcSAndroid Build Coastguard Worker                                       argc > 5 ? argv[5] : nullptr));
429*598139dcSAndroid Build Coastguard Worker     } else if (!strcmp(argv[2], "print_all_logs")) {
430*598139dcSAndroid Build Coastguard Worker         operation.reset(
431*598139dcSAndroid Build Coastguard Worker                 new PrintAllLogs(first_log_timestamp, argv[3], argc > 4 ? argv[4] : nullptr));
432*598139dcSAndroid Build Coastguard Worker     } else if (!strcmp(argv[2], "nothing")) {
433*598139dcSAndroid Build Coastguard Worker         operation.reset(new SingleBufferOperation(first_log_timestamp, argv[3]));
434*598139dcSAndroid Build Coastguard Worker     } else {
435*598139dcSAndroid Build Coastguard Worker         fprintf(stderr, "unknown operation '%s'\n", argv[2]);
436*598139dcSAndroid Build Coastguard Worker         return 1;
437*598139dcSAndroid Build Coastguard Worker     }
438*598139dcSAndroid Build Coastguard Worker 
439*598139dcSAndroid Build Coastguard Worker     // LogBuffer::Log() won't log without this on host.
440*598139dcSAndroid Build Coastguard Worker     __android_log_set_minimum_priority(ANDROID_LOG_VERBOSE);
441*598139dcSAndroid Build Coastguard Worker     // But we still want to suppress messages <= error to not interrupt the rest of the output.
442*598139dcSAndroid Build Coastguard Worker     __android_log_set_logger([](const struct __android_log_message* log_message) {
443*598139dcSAndroid Build Coastguard Worker         if (log_message->priority < ANDROID_LOG_ERROR) {
444*598139dcSAndroid Build Coastguard Worker             return;
445*598139dcSAndroid Build Coastguard Worker         }
446*598139dcSAndroid Build Coastguard Worker         __android_log_stderr_logger(log_message);
447*598139dcSAndroid Build Coastguard Worker     });
448*598139dcSAndroid Build Coastguard Worker 
449*598139dcSAndroid Build Coastguard Worker     operation->Begin();
450*598139dcSAndroid Build Coastguard Worker 
451*598139dcSAndroid Build Coastguard Worker     uint64_t read_position = 0;
452*598139dcSAndroid Build Coastguard Worker     while (read_position + sizeof(RecordedLogMessage) < recorded_messages->size()) {
453*598139dcSAndroid Build Coastguard Worker         auto* meta =
454*598139dcSAndroid Build Coastguard Worker                 reinterpret_cast<RecordedLogMessage*>(recorded_messages->data() + read_position);
455*598139dcSAndroid Build Coastguard Worker         if (read_position + sizeof(RecordedLogMessage) + meta->msg_len >=
456*598139dcSAndroid Build Coastguard Worker             recorded_messages->size()) {
457*598139dcSAndroid Build Coastguard Worker             break;
458*598139dcSAndroid Build Coastguard Worker         }
459*598139dcSAndroid Build Coastguard Worker         char* msg = recorded_messages->data() + read_position + sizeof(RecordedLogMessage);
460*598139dcSAndroid Build Coastguard Worker         read_position += sizeof(RecordedLogMessage) + meta->msg_len;
461*598139dcSAndroid Build Coastguard Worker 
462*598139dcSAndroid Build Coastguard Worker         operation->Log(*meta, msg);
463*598139dcSAndroid Build Coastguard Worker     }
464*598139dcSAndroid Build Coastguard Worker 
465*598139dcSAndroid Build Coastguard Worker     operation->End();
466*598139dcSAndroid Build Coastguard Worker 
467*598139dcSAndroid Build Coastguard Worker     return 0;
468*598139dcSAndroid Build Coastguard Worker }
469