xref: /aosp_15_r20/external/perfetto/src/traceconv/trace_to_systrace.cc (revision 6dbdd20afdafa5e3ca9b8809fa73465d530080dc)
1*6dbdd20aSAndroid Build Coastguard Worker /*
2*6dbdd20aSAndroid Build Coastguard Worker  * Copyright (C) 2018 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 "src/traceconv/trace_to_systrace.h"
18*6dbdd20aSAndroid Build Coastguard Worker 
19*6dbdd20aSAndroid Build Coastguard Worker #include <stdio.h>
20*6dbdd20aSAndroid Build Coastguard Worker 
21*6dbdd20aSAndroid Build Coastguard Worker #include <algorithm>
22*6dbdd20aSAndroid Build Coastguard Worker #include <cinttypes>
23*6dbdd20aSAndroid Build Coastguard Worker #include <functional>
24*6dbdd20aSAndroid Build Coastguard Worker #include <map>
25*6dbdd20aSAndroid Build Coastguard Worker #include <memory>
26*6dbdd20aSAndroid Build Coastguard Worker #include <utility>
27*6dbdd20aSAndroid Build Coastguard Worker 
28*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/base/build_config.h"
29*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/base/logging.h"
30*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/ext/base/string_utils.h"
31*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/ext/base/string_writer.h"
32*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/ext/base/utils.h"
33*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/trace_processor/trace_processor.h"
34*6dbdd20aSAndroid Build Coastguard Worker #include "src/traceconv/utils.h"
35*6dbdd20aSAndroid Build Coastguard Worker 
36*6dbdd20aSAndroid Build Coastguard Worker namespace perfetto {
37*6dbdd20aSAndroid Build Coastguard Worker namespace trace_to_text {
38*6dbdd20aSAndroid Build Coastguard Worker 
39*6dbdd20aSAndroid Build Coastguard Worker namespace {
40*6dbdd20aSAndroid Build Coastguard Worker 
41*6dbdd20aSAndroid Build Coastguard Worker const char kProcessDumpHeader[] =
42*6dbdd20aSAndroid Build Coastguard Worker     "\"androidProcessDump\": "
43*6dbdd20aSAndroid Build Coastguard Worker     "\"PROCESS DUMP\\nUSER           PID  PPID     VSZ    RSS WCHAN  "
44*6dbdd20aSAndroid Build Coastguard Worker     "PC S NAME                        COMM                       \\n";
45*6dbdd20aSAndroid Build Coastguard Worker 
46*6dbdd20aSAndroid Build Coastguard Worker const char kThreadHeader[] = "USER           PID   TID CMD \\n";
47*6dbdd20aSAndroid Build Coastguard Worker 
48*6dbdd20aSAndroid Build Coastguard Worker const char kProcessDumpFooter[] = "\"";
49*6dbdd20aSAndroid Build Coastguard Worker 
50*6dbdd20aSAndroid Build Coastguard Worker const char kSystemTraceEvents[] = "  \"systemTraceEvents\": \"";
51*6dbdd20aSAndroid Build Coastguard Worker 
52*6dbdd20aSAndroid Build Coastguard Worker const char kFtraceHeader[] =
53*6dbdd20aSAndroid Build Coastguard Worker     "# tracer: nop\n"
54*6dbdd20aSAndroid Build Coastguard Worker     "#\n"
55*6dbdd20aSAndroid Build Coastguard Worker     "# entries-in-buffer/entries-written: 30624/30624   #P:4\n"
56*6dbdd20aSAndroid Build Coastguard Worker     "#\n"
57*6dbdd20aSAndroid Build Coastguard Worker     "#                                      _-----=> irqs-off\n"
58*6dbdd20aSAndroid Build Coastguard Worker     "#                                     / _----=> need-resched\n"
59*6dbdd20aSAndroid Build Coastguard Worker     "#                                    | / _---=> hardirq/softirq\n"
60*6dbdd20aSAndroid Build Coastguard Worker     "#                                    || / _--=> preempt-depth\n"
61*6dbdd20aSAndroid Build Coastguard Worker     "#                                    ||| /     delay\n"
62*6dbdd20aSAndroid Build Coastguard Worker     "#           TASK-PID    TGID   CPU#  ||||    TIMESTAMP  FUNCTION\n"
63*6dbdd20aSAndroid Build Coastguard Worker     "#              | |        |      |   ||||       |         |\n";
64*6dbdd20aSAndroid Build Coastguard Worker 
65*6dbdd20aSAndroid Build Coastguard Worker const char kFtraceJsonHeader[] =
66*6dbdd20aSAndroid Build Coastguard Worker     "# tracer: nop\\n"
67*6dbdd20aSAndroid Build Coastguard Worker     "#\\n"
68*6dbdd20aSAndroid Build Coastguard Worker     "# entries-in-buffer/entries-written: 30624/30624   #P:4\\n"
69*6dbdd20aSAndroid Build Coastguard Worker     "#\\n"
70*6dbdd20aSAndroid Build Coastguard Worker     "#                                      _-----=> irqs-off\\n"
71*6dbdd20aSAndroid Build Coastguard Worker     "#                                     / _----=> need-resched\\n"
72*6dbdd20aSAndroid Build Coastguard Worker     "#                                    | / _---=> hardirq/softirq\\n"
73*6dbdd20aSAndroid Build Coastguard Worker     "#                                    || / _--=> preempt-depth\\n"
74*6dbdd20aSAndroid Build Coastguard Worker     "#                                    ||| /     delay\\n"
75*6dbdd20aSAndroid Build Coastguard Worker     "#           TASK-PID    TGID   CPU#  ||||    TIMESTAMP  FUNCTION\\n"
76*6dbdd20aSAndroid Build Coastguard Worker     "#              | |        |      |   ||||       |         |\\n";
77*6dbdd20aSAndroid Build Coastguard Worker 
78*6dbdd20aSAndroid Build Coastguard Worker // The legacy trace viewer requires a clock sync marker to tie ftrace and
79*6dbdd20aSAndroid Build Coastguard Worker // userspace clocks together. Trace processor already aligned these clocks, so
80*6dbdd20aSAndroid Build Coastguard Worker // we just emit a clock sync for an equality mapping.
81*6dbdd20aSAndroid Build Coastguard Worker const char kSystemTraceEventsFooter[] =
82*6dbdd20aSAndroid Build Coastguard Worker     "\\n<...>-12345 (-----) [000] ...1 0.000000: tracing_mark_write: "
83*6dbdd20aSAndroid Build Coastguard Worker     "trace_event_clock_sync: parent_ts=0\\n\"";
84*6dbdd20aSAndroid Build Coastguard Worker 
FormatProcess(uint32_t pid,uint32_t ppid,const base::StringView & name,base::StringWriter * writer)85*6dbdd20aSAndroid Build Coastguard Worker inline void FormatProcess(uint32_t pid,
86*6dbdd20aSAndroid Build Coastguard Worker                           uint32_t ppid,
87*6dbdd20aSAndroid Build Coastguard Worker                           const base::StringView& name,
88*6dbdd20aSAndroid Build Coastguard Worker                           base::StringWriter* writer) {
89*6dbdd20aSAndroid Build Coastguard Worker   writer->AppendLiteral("root             ");
90*6dbdd20aSAndroid Build Coastguard Worker   writer->AppendInt(pid);
91*6dbdd20aSAndroid Build Coastguard Worker   writer->AppendLiteral("     ");
92*6dbdd20aSAndroid Build Coastguard Worker   writer->AppendInt(ppid);
93*6dbdd20aSAndroid Build Coastguard Worker   writer->AppendLiteral("   00000   000 null 0000000000 S ");
94*6dbdd20aSAndroid Build Coastguard Worker   writer->AppendString(name);
95*6dbdd20aSAndroid Build Coastguard Worker   writer->AppendLiteral("         null");
96*6dbdd20aSAndroid Build Coastguard Worker }
97*6dbdd20aSAndroid Build Coastguard Worker 
FormatThread(uint32_t tid,uint32_t tgid,const base::StringView & name,base::StringWriter * writer)98*6dbdd20aSAndroid Build Coastguard Worker inline void FormatThread(uint32_t tid,
99*6dbdd20aSAndroid Build Coastguard Worker                          uint32_t tgid,
100*6dbdd20aSAndroid Build Coastguard Worker                          const base::StringView& name,
101*6dbdd20aSAndroid Build Coastguard Worker                          base::StringWriter* writer) {
102*6dbdd20aSAndroid Build Coastguard Worker   writer->AppendLiteral("root         ");
103*6dbdd20aSAndroid Build Coastguard Worker   writer->AppendInt(tgid);
104*6dbdd20aSAndroid Build Coastguard Worker   writer->AppendChar(' ');
105*6dbdd20aSAndroid Build Coastguard Worker   writer->AppendInt(tid);
106*6dbdd20aSAndroid Build Coastguard Worker   writer->AppendChar(' ');
107*6dbdd20aSAndroid Build Coastguard Worker   if (name.empty()) {
108*6dbdd20aSAndroid Build Coastguard Worker     writer->AppendLiteral("<...>");
109*6dbdd20aSAndroid Build Coastguard Worker   } else {
110*6dbdd20aSAndroid Build Coastguard Worker     writer->AppendString(name);
111*6dbdd20aSAndroid Build Coastguard Worker   }
112*6dbdd20aSAndroid Build Coastguard Worker }
113*6dbdd20aSAndroid Build Coastguard Worker 
114*6dbdd20aSAndroid Build Coastguard Worker class QueryWriter {
115*6dbdd20aSAndroid Build Coastguard Worker  public:
QueryWriter(trace_processor::TraceProcessor * tp,TraceWriter * trace_writer)116*6dbdd20aSAndroid Build Coastguard Worker   QueryWriter(trace_processor::TraceProcessor* tp, TraceWriter* trace_writer)
117*6dbdd20aSAndroid Build Coastguard Worker       : tp_(tp),
118*6dbdd20aSAndroid Build Coastguard Worker         buffer_(base::PagedMemory::Allocate(kBufferSize)),
119*6dbdd20aSAndroid Build Coastguard Worker         global_writer_(static_cast<char*>(buffer_.Get()), kBufferSize),
120*6dbdd20aSAndroid Build Coastguard Worker         trace_writer_(trace_writer) {}
121*6dbdd20aSAndroid Build Coastguard Worker 
122*6dbdd20aSAndroid Build Coastguard Worker   template <typename Callback>
RunQuery(const std::string & sql,Callback callback)123*6dbdd20aSAndroid Build Coastguard Worker   bool RunQuery(const std::string& sql, Callback callback) {
124*6dbdd20aSAndroid Build Coastguard Worker     char buffer[2048];
125*6dbdd20aSAndroid Build Coastguard Worker     auto iterator = tp_->ExecuteQuery(sql);
126*6dbdd20aSAndroid Build Coastguard Worker     for (uint32_t rows = 0; iterator.Next(); rows++) {
127*6dbdd20aSAndroid Build Coastguard Worker       base::StringWriter line_writer(buffer, base::ArraySize(buffer));
128*6dbdd20aSAndroid Build Coastguard Worker       callback(&iterator, &line_writer);
129*6dbdd20aSAndroid Build Coastguard Worker 
130*6dbdd20aSAndroid Build Coastguard Worker       if (global_writer_.pos() + line_writer.pos() >= global_writer_.size()) {
131*6dbdd20aSAndroid Build Coastguard Worker         fprintf(stderr, "Writing row %" PRIu32 "%c", rows, kProgressChar);
132*6dbdd20aSAndroid Build Coastguard Worker         auto str = global_writer_.GetStringView();
133*6dbdd20aSAndroid Build Coastguard Worker         trace_writer_->Write(str.data(), str.size());
134*6dbdd20aSAndroid Build Coastguard Worker         global_writer_.reset();
135*6dbdd20aSAndroid Build Coastguard Worker       }
136*6dbdd20aSAndroid Build Coastguard Worker       global_writer_.AppendStringView(line_writer.GetStringView());
137*6dbdd20aSAndroid Build Coastguard Worker     }
138*6dbdd20aSAndroid Build Coastguard Worker 
139*6dbdd20aSAndroid Build Coastguard Worker     // Check if we have an error in the iterator and print if so.
140*6dbdd20aSAndroid Build Coastguard Worker     auto status = iterator.Status();
141*6dbdd20aSAndroid Build Coastguard Worker     if (!status.ok()) {
142*6dbdd20aSAndroid Build Coastguard Worker       PERFETTO_ELOG("Error while writing systrace %s", status.c_message());
143*6dbdd20aSAndroid Build Coastguard Worker       return false;
144*6dbdd20aSAndroid Build Coastguard Worker     }
145*6dbdd20aSAndroid Build Coastguard Worker 
146*6dbdd20aSAndroid Build Coastguard Worker     // Flush any dangling pieces in the global writer.
147*6dbdd20aSAndroid Build Coastguard Worker     auto str = global_writer_.GetStringView();
148*6dbdd20aSAndroid Build Coastguard Worker     trace_writer_->Write(str.data(), str.size());
149*6dbdd20aSAndroid Build Coastguard Worker     global_writer_.reset();
150*6dbdd20aSAndroid Build Coastguard Worker     return true;
151*6dbdd20aSAndroid Build Coastguard Worker   }
152*6dbdd20aSAndroid Build Coastguard Worker 
153*6dbdd20aSAndroid Build Coastguard Worker  private:
154*6dbdd20aSAndroid Build Coastguard Worker   static constexpr uint32_t kBufferSize = 1024u * 1024u * 16u;
155*6dbdd20aSAndroid Build Coastguard Worker 
156*6dbdd20aSAndroid Build Coastguard Worker   trace_processor::TraceProcessor* tp_ = nullptr;
157*6dbdd20aSAndroid Build Coastguard Worker   base::PagedMemory buffer_;
158*6dbdd20aSAndroid Build Coastguard Worker   base::StringWriter global_writer_;
159*6dbdd20aSAndroid Build Coastguard Worker   TraceWriter* trace_writer_;
160*6dbdd20aSAndroid Build Coastguard Worker };
161*6dbdd20aSAndroid Build Coastguard Worker 
ExtractRawEvents(TraceWriter * trace_writer,QueryWriter & q_writer,bool wrapped_in_json,Keep truncate_keep)162*6dbdd20aSAndroid Build Coastguard Worker int ExtractRawEvents(TraceWriter* trace_writer,
163*6dbdd20aSAndroid Build Coastguard Worker                      QueryWriter& q_writer,
164*6dbdd20aSAndroid Build Coastguard Worker                      bool wrapped_in_json,
165*6dbdd20aSAndroid Build Coastguard Worker                      Keep truncate_keep) {
166*6dbdd20aSAndroid Build Coastguard Worker   using trace_processor::Iterator;
167*6dbdd20aSAndroid Build Coastguard Worker 
168*6dbdd20aSAndroid Build Coastguard Worker   static const char kRawEventsCountSql[] = "select count(1) from ftrace_event";
169*6dbdd20aSAndroid Build Coastguard Worker   uint32_t raw_events = 0;
170*6dbdd20aSAndroid Build Coastguard Worker   auto e_callback = [&raw_events](Iterator* it, base::StringWriter*) {
171*6dbdd20aSAndroid Build Coastguard Worker     raw_events = static_cast<uint32_t>(it->Get(0).long_value);
172*6dbdd20aSAndroid Build Coastguard Worker   };
173*6dbdd20aSAndroid Build Coastguard Worker   if (!q_writer.RunQuery(kRawEventsCountSql, e_callback))
174*6dbdd20aSAndroid Build Coastguard Worker     return 1;
175*6dbdd20aSAndroid Build Coastguard Worker 
176*6dbdd20aSAndroid Build Coastguard Worker   if (raw_events == 0) {
177*6dbdd20aSAndroid Build Coastguard Worker     if (!wrapped_in_json) {
178*6dbdd20aSAndroid Build Coastguard Worker       // Write out the normal header even if we won't actually have
179*6dbdd20aSAndroid Build Coastguard Worker       // any events under it.
180*6dbdd20aSAndroid Build Coastguard Worker       trace_writer->Write(kFtraceHeader);
181*6dbdd20aSAndroid Build Coastguard Worker     }
182*6dbdd20aSAndroid Build Coastguard Worker     return 0;
183*6dbdd20aSAndroid Build Coastguard Worker   }
184*6dbdd20aSAndroid Build Coastguard Worker 
185*6dbdd20aSAndroid Build Coastguard Worker   fprintf(stderr, "Converting ftrace events%c", kProgressChar);
186*6dbdd20aSAndroid Build Coastguard Worker   fflush(stderr);
187*6dbdd20aSAndroid Build Coastguard Worker 
188*6dbdd20aSAndroid Build Coastguard Worker   auto raw_callback = [wrapped_in_json](Iterator* it,
189*6dbdd20aSAndroid Build Coastguard Worker                                         base::StringWriter* writer) {
190*6dbdd20aSAndroid Build Coastguard Worker     const char* line = it->Get(0 /* col */).string_value;
191*6dbdd20aSAndroid Build Coastguard Worker     if (wrapped_in_json) {
192*6dbdd20aSAndroid Build Coastguard Worker       for (uint32_t i = 0; line[i] != '\0'; i++) {
193*6dbdd20aSAndroid Build Coastguard Worker         char c = line[i];
194*6dbdd20aSAndroid Build Coastguard Worker         switch (c) {
195*6dbdd20aSAndroid Build Coastguard Worker           case '\n':
196*6dbdd20aSAndroid Build Coastguard Worker             writer->AppendLiteral("\\n");
197*6dbdd20aSAndroid Build Coastguard Worker             break;
198*6dbdd20aSAndroid Build Coastguard Worker           case '\f':
199*6dbdd20aSAndroid Build Coastguard Worker             writer->AppendLiteral("\\f");
200*6dbdd20aSAndroid Build Coastguard Worker             break;
201*6dbdd20aSAndroid Build Coastguard Worker           case '\b':
202*6dbdd20aSAndroid Build Coastguard Worker             writer->AppendLiteral("\\b");
203*6dbdd20aSAndroid Build Coastguard Worker             break;
204*6dbdd20aSAndroid Build Coastguard Worker           case '\r':
205*6dbdd20aSAndroid Build Coastguard Worker             writer->AppendLiteral("\\r");
206*6dbdd20aSAndroid Build Coastguard Worker             break;
207*6dbdd20aSAndroid Build Coastguard Worker           case '\t':
208*6dbdd20aSAndroid Build Coastguard Worker             writer->AppendLiteral("\\t");
209*6dbdd20aSAndroid Build Coastguard Worker             break;
210*6dbdd20aSAndroid Build Coastguard Worker           case '\\':
211*6dbdd20aSAndroid Build Coastguard Worker             writer->AppendLiteral("\\\\");
212*6dbdd20aSAndroid Build Coastguard Worker             break;
213*6dbdd20aSAndroid Build Coastguard Worker           case '"':
214*6dbdd20aSAndroid Build Coastguard Worker             writer->AppendLiteral("\\\"");
215*6dbdd20aSAndroid Build Coastguard Worker             break;
216*6dbdd20aSAndroid Build Coastguard Worker           default:
217*6dbdd20aSAndroid Build Coastguard Worker             writer->AppendChar(c);
218*6dbdd20aSAndroid Build Coastguard Worker             break;
219*6dbdd20aSAndroid Build Coastguard Worker         }
220*6dbdd20aSAndroid Build Coastguard Worker       }
221*6dbdd20aSAndroid Build Coastguard Worker       writer->AppendChar('\\');
222*6dbdd20aSAndroid Build Coastguard Worker       writer->AppendChar('n');
223*6dbdd20aSAndroid Build Coastguard Worker     } else {
224*6dbdd20aSAndroid Build Coastguard Worker       writer->AppendString(line);
225*6dbdd20aSAndroid Build Coastguard Worker       writer->AppendChar('\n');
226*6dbdd20aSAndroid Build Coastguard Worker     }
227*6dbdd20aSAndroid Build Coastguard Worker   };
228*6dbdd20aSAndroid Build Coastguard Worker 
229*6dbdd20aSAndroid Build Coastguard Worker   // An estimate of 130b per ftrace event, allowing some space for the processes
230*6dbdd20aSAndroid Build Coastguard Worker   // and threads.
231*6dbdd20aSAndroid Build Coastguard Worker   const uint32_t max_ftrace_events = (140 * 1024 * 1024) / 130;
232*6dbdd20aSAndroid Build Coastguard Worker 
233*6dbdd20aSAndroid Build Coastguard Worker   static const char kRawEventsQuery[] =
234*6dbdd20aSAndroid Build Coastguard Worker       "select to_ftrace(id) from ftrace_event";
235*6dbdd20aSAndroid Build Coastguard Worker 
236*6dbdd20aSAndroid Build Coastguard Worker   // 1. Write the appropriate header for the file type.
237*6dbdd20aSAndroid Build Coastguard Worker   if (wrapped_in_json) {
238*6dbdd20aSAndroid Build Coastguard Worker     trace_writer->Write(",\n");
239*6dbdd20aSAndroid Build Coastguard Worker     trace_writer->Write(kSystemTraceEvents);
240*6dbdd20aSAndroid Build Coastguard Worker     trace_writer->Write(kFtraceJsonHeader);
241*6dbdd20aSAndroid Build Coastguard Worker   } else {
242*6dbdd20aSAndroid Build Coastguard Worker     trace_writer->Write(kFtraceHeader);
243*6dbdd20aSAndroid Build Coastguard Worker   }
244*6dbdd20aSAndroid Build Coastguard Worker 
245*6dbdd20aSAndroid Build Coastguard Worker   // 2. Write the actual events.
246*6dbdd20aSAndroid Build Coastguard Worker   if (truncate_keep == Keep::kEnd && raw_events > max_ftrace_events) {
247*6dbdd20aSAndroid Build Coastguard Worker     base::StackString<150> end_truncate("%s limit %d offset %d",
248*6dbdd20aSAndroid Build Coastguard Worker                                         kRawEventsQuery, max_ftrace_events,
249*6dbdd20aSAndroid Build Coastguard Worker                                         raw_events - max_ftrace_events);
250*6dbdd20aSAndroid Build Coastguard Worker     if (!q_writer.RunQuery(end_truncate.ToStdString(), raw_callback))
251*6dbdd20aSAndroid Build Coastguard Worker       return 1;
252*6dbdd20aSAndroid Build Coastguard Worker   } else if (truncate_keep == Keep::kStart) {
253*6dbdd20aSAndroid Build Coastguard Worker     base::StackString<150> start_truncate("%s limit %d", kRawEventsQuery,
254*6dbdd20aSAndroid Build Coastguard Worker                                           max_ftrace_events);
255*6dbdd20aSAndroid Build Coastguard Worker     if (!q_writer.RunQuery(start_truncate.ToStdString(), raw_callback))
256*6dbdd20aSAndroid Build Coastguard Worker       return 1;
257*6dbdd20aSAndroid Build Coastguard Worker   } else {
258*6dbdd20aSAndroid Build Coastguard Worker     if (!q_writer.RunQuery(kRawEventsQuery, raw_callback))
259*6dbdd20aSAndroid Build Coastguard Worker       return 1;
260*6dbdd20aSAndroid Build Coastguard Worker   }
261*6dbdd20aSAndroid Build Coastguard Worker 
262*6dbdd20aSAndroid Build Coastguard Worker   // 3. Write the footer for JSON.
263*6dbdd20aSAndroid Build Coastguard Worker   if (wrapped_in_json)
264*6dbdd20aSAndroid Build Coastguard Worker     trace_writer->Write(kSystemTraceEventsFooter);
265*6dbdd20aSAndroid Build Coastguard Worker 
266*6dbdd20aSAndroid Build Coastguard Worker   return 0;
267*6dbdd20aSAndroid Build Coastguard Worker }
268*6dbdd20aSAndroid Build Coastguard Worker 
269*6dbdd20aSAndroid Build Coastguard Worker }  // namespace
270*6dbdd20aSAndroid Build Coastguard Worker 
TraceToSystrace(std::istream * input,std::ostream * output,bool ctrace,Keep truncate_keep,bool full_sort)271*6dbdd20aSAndroid Build Coastguard Worker int TraceToSystrace(std::istream* input,
272*6dbdd20aSAndroid Build Coastguard Worker                     std::ostream* output,
273*6dbdd20aSAndroid Build Coastguard Worker                     bool ctrace,
274*6dbdd20aSAndroid Build Coastguard Worker                     Keep truncate_keep,
275*6dbdd20aSAndroid Build Coastguard Worker                     bool full_sort) {
276*6dbdd20aSAndroid Build Coastguard Worker   std::unique_ptr<TraceWriter> trace_writer(
277*6dbdd20aSAndroid Build Coastguard Worker       ctrace ? new DeflateTraceWriter(output) : new TraceWriter(output));
278*6dbdd20aSAndroid Build Coastguard Worker 
279*6dbdd20aSAndroid Build Coastguard Worker   trace_processor::Config config;
280*6dbdd20aSAndroid Build Coastguard Worker   config.sorting_mode = full_sort
281*6dbdd20aSAndroid Build Coastguard Worker                             ? trace_processor::SortingMode::kForceFullSort
282*6dbdd20aSAndroid Build Coastguard Worker                             : trace_processor::SortingMode::kDefaultHeuristics;
283*6dbdd20aSAndroid Build Coastguard Worker   std::unique_ptr<trace_processor::TraceProcessor> tp =
284*6dbdd20aSAndroid Build Coastguard Worker       trace_processor::TraceProcessor::CreateInstance(config);
285*6dbdd20aSAndroid Build Coastguard Worker 
286*6dbdd20aSAndroid Build Coastguard Worker   if (!ReadTraceUnfinalized(tp.get(), input))
287*6dbdd20aSAndroid Build Coastguard Worker     return 1;
288*6dbdd20aSAndroid Build Coastguard Worker   if (auto status = tp->NotifyEndOfFile(); !status.ok()) {
289*6dbdd20aSAndroid Build Coastguard Worker     return 1;
290*6dbdd20aSAndroid Build Coastguard Worker   }
291*6dbdd20aSAndroid Build Coastguard Worker 
292*6dbdd20aSAndroid Build Coastguard Worker   if (ctrace)
293*6dbdd20aSAndroid Build Coastguard Worker     *output << "TRACE:\n";
294*6dbdd20aSAndroid Build Coastguard Worker 
295*6dbdd20aSAndroid Build Coastguard Worker   return ExtractSystrace(tp.get(), trace_writer.get(),
296*6dbdd20aSAndroid Build Coastguard Worker                          /*wrapped_in_json=*/false, truncate_keep);
297*6dbdd20aSAndroid Build Coastguard Worker }
298*6dbdd20aSAndroid Build Coastguard Worker 
ExtractSystrace(trace_processor::TraceProcessor * tp,TraceWriter * trace_writer,bool wrapped_in_json,Keep truncate_keep)299*6dbdd20aSAndroid Build Coastguard Worker int ExtractSystrace(trace_processor::TraceProcessor* tp,
300*6dbdd20aSAndroid Build Coastguard Worker                     TraceWriter* trace_writer,
301*6dbdd20aSAndroid Build Coastguard Worker                     bool wrapped_in_json,
302*6dbdd20aSAndroid Build Coastguard Worker                     Keep truncate_keep) {
303*6dbdd20aSAndroid Build Coastguard Worker   using trace_processor::Iterator;
304*6dbdd20aSAndroid Build Coastguard Worker 
305*6dbdd20aSAndroid Build Coastguard Worker   QueryWriter q_writer(tp, trace_writer);
306*6dbdd20aSAndroid Build Coastguard Worker   if (wrapped_in_json) {
307*6dbdd20aSAndroid Build Coastguard Worker     trace_writer->Write(kProcessDumpHeader);
308*6dbdd20aSAndroid Build Coastguard Worker 
309*6dbdd20aSAndroid Build Coastguard Worker     // Write out all the processes in the trace.
310*6dbdd20aSAndroid Build Coastguard Worker     // TODO(lalitm): change this query to actually use ppid when it is exposed
311*6dbdd20aSAndroid Build Coastguard Worker     // by the process table.
312*6dbdd20aSAndroid Build Coastguard Worker     static const char kPSql[] = "select pid, 0 as ppid, name from process";
313*6dbdd20aSAndroid Build Coastguard Worker     auto p_callback = [](Iterator* it, base::StringWriter* writer) {
314*6dbdd20aSAndroid Build Coastguard Worker       uint32_t pid = static_cast<uint32_t>(it->Get(0 /* col */).long_value);
315*6dbdd20aSAndroid Build Coastguard Worker       uint32_t ppid = static_cast<uint32_t>(it->Get(1 /* col */).long_value);
316*6dbdd20aSAndroid Build Coastguard Worker       const auto& name_col = it->Get(2 /* col */);
317*6dbdd20aSAndroid Build Coastguard Worker       auto name_view = name_col.type == trace_processor::SqlValue::kString
318*6dbdd20aSAndroid Build Coastguard Worker                            ? base::StringView(name_col.string_value)
319*6dbdd20aSAndroid Build Coastguard Worker                            : base::StringView();
320*6dbdd20aSAndroid Build Coastguard Worker       FormatProcess(pid, ppid, name_view, writer);
321*6dbdd20aSAndroid Build Coastguard Worker     };
322*6dbdd20aSAndroid Build Coastguard Worker     if (!q_writer.RunQuery(kPSql, p_callback))
323*6dbdd20aSAndroid Build Coastguard Worker       return 1;
324*6dbdd20aSAndroid Build Coastguard Worker 
325*6dbdd20aSAndroid Build Coastguard Worker     trace_writer->Write(kThreadHeader);
326*6dbdd20aSAndroid Build Coastguard Worker 
327*6dbdd20aSAndroid Build Coastguard Worker     // Write out all the threads in the trace.
328*6dbdd20aSAndroid Build Coastguard Worker     static const char kTSql[] =
329*6dbdd20aSAndroid Build Coastguard Worker         "select tid, COALESCE(upid, 0), thread.name "
330*6dbdd20aSAndroid Build Coastguard Worker         "from thread left join process using (upid)";
331*6dbdd20aSAndroid Build Coastguard Worker     auto t_callback = [](Iterator* it, base::StringWriter* writer) {
332*6dbdd20aSAndroid Build Coastguard Worker       uint32_t tid = static_cast<uint32_t>(it->Get(0 /* col */).long_value);
333*6dbdd20aSAndroid Build Coastguard Worker       uint32_t tgid = static_cast<uint32_t>(it->Get(1 /* col */).long_value);
334*6dbdd20aSAndroid Build Coastguard Worker       const auto& name_col = it->Get(2 /* col */);
335*6dbdd20aSAndroid Build Coastguard Worker       auto name_view = name_col.type == trace_processor::SqlValue::kString
336*6dbdd20aSAndroid Build Coastguard Worker                            ? base::StringView(name_col.string_value)
337*6dbdd20aSAndroid Build Coastguard Worker                            : base::StringView();
338*6dbdd20aSAndroid Build Coastguard Worker       FormatThread(tid, tgid, name_view, writer);
339*6dbdd20aSAndroid Build Coastguard Worker     };
340*6dbdd20aSAndroid Build Coastguard Worker     if (!q_writer.RunQuery(kTSql, t_callback))
341*6dbdd20aSAndroid Build Coastguard Worker       return 1;
342*6dbdd20aSAndroid Build Coastguard Worker 
343*6dbdd20aSAndroid Build Coastguard Worker     trace_writer->Write(kProcessDumpFooter);
344*6dbdd20aSAndroid Build Coastguard Worker   }
345*6dbdd20aSAndroid Build Coastguard Worker   return ExtractRawEvents(trace_writer, q_writer, wrapped_in_json,
346*6dbdd20aSAndroid Build Coastguard Worker                           truncate_keep);
347*6dbdd20aSAndroid Build Coastguard Worker }
348*6dbdd20aSAndroid Build Coastguard Worker 
349*6dbdd20aSAndroid Build Coastguard Worker }  // namespace trace_to_text
350*6dbdd20aSAndroid Build Coastguard Worker }  // namespace perfetto
351