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 "src/traceconv/trace_to_json.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 "perfetto/base/logging.h"
22*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/ext/base/scoped_file.h"
23*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/ext/base/string_utils.h"
24*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/ext/base/temp_file.h"
25*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/trace_processor/trace_processor.h"
26*6dbdd20aSAndroid Build Coastguard Worker #include "src/traceconv/utils.h"
27*6dbdd20aSAndroid Build Coastguard Worker
28*6dbdd20aSAndroid Build Coastguard Worker namespace perfetto {
29*6dbdd20aSAndroid Build Coastguard Worker namespace trace_to_text {
30*6dbdd20aSAndroid Build Coastguard Worker
31*6dbdd20aSAndroid Build Coastguard Worker namespace {
32*6dbdd20aSAndroid Build Coastguard Worker
33*6dbdd20aSAndroid Build Coastguard Worker const char kTraceHeader[] = R"({
34*6dbdd20aSAndroid Build Coastguard Worker "traceEvents": [],
35*6dbdd20aSAndroid Build Coastguard Worker )";
36*6dbdd20aSAndroid Build Coastguard Worker
37*6dbdd20aSAndroid Build Coastguard Worker const char kTraceFooter[] = R"(,
38*6dbdd20aSAndroid Build Coastguard Worker "controllerTraceDataKey": "systraceController"
39*6dbdd20aSAndroid Build Coastguard Worker })";
40*6dbdd20aSAndroid Build Coastguard Worker
ExportUserspaceEvents(trace_processor::TraceProcessor * tp,TraceWriter * writer)41*6dbdd20aSAndroid Build Coastguard Worker bool ExportUserspaceEvents(trace_processor::TraceProcessor* tp,
42*6dbdd20aSAndroid Build Coastguard Worker TraceWriter* writer) {
43*6dbdd20aSAndroid Build Coastguard Worker fprintf(stderr, "Converting userspace events%c", kProgressChar);
44*6dbdd20aSAndroid Build Coastguard Worker fflush(stderr);
45*6dbdd20aSAndroid Build Coastguard Worker
46*6dbdd20aSAndroid Build Coastguard Worker // Write userspace trace to a temporary file.
47*6dbdd20aSAndroid Build Coastguard Worker // TODO(eseckler): Support streaming the result out of TP directly instead.
48*6dbdd20aSAndroid Build Coastguard Worker auto file = base::TempFile::Create();
49*6dbdd20aSAndroid Build Coastguard Worker base::StackString<100> query("select export_json(\"%s\")",
50*6dbdd20aSAndroid Build Coastguard Worker file.path().c_str());
51*6dbdd20aSAndroid Build Coastguard Worker auto it = tp->ExecuteQuery(query.ToStdString());
52*6dbdd20aSAndroid Build Coastguard Worker
53*6dbdd20aSAndroid Build Coastguard Worker if (!it.Next()) {
54*6dbdd20aSAndroid Build Coastguard Worker auto status = it.Status();
55*6dbdd20aSAndroid Build Coastguard Worker PERFETTO_CHECK(!status.ok());
56*6dbdd20aSAndroid Build Coastguard Worker PERFETTO_ELOG("Could not convert userspace events: %s", status.c_message());
57*6dbdd20aSAndroid Build Coastguard Worker return false;
58*6dbdd20aSAndroid Build Coastguard Worker }
59*6dbdd20aSAndroid Build Coastguard Worker
60*6dbdd20aSAndroid Build Coastguard Worker base::ScopedFstream source(fopen(file.path().c_str(), "r"));
61*6dbdd20aSAndroid Build Coastguard Worker if (!source) {
62*6dbdd20aSAndroid Build Coastguard Worker PERFETTO_ELOG("Could not convert userspace events: Couldn't read file %s",
63*6dbdd20aSAndroid Build Coastguard Worker file.path().c_str());
64*6dbdd20aSAndroid Build Coastguard Worker return false;
65*6dbdd20aSAndroid Build Coastguard Worker }
66*6dbdd20aSAndroid Build Coastguard Worker
67*6dbdd20aSAndroid Build Coastguard Worker char buf[BUFSIZ];
68*6dbdd20aSAndroid Build Coastguard Worker size_t size;
69*6dbdd20aSAndroid Build Coastguard Worker while ((size = fread(buf, sizeof(char), BUFSIZ, *source)) > 0) {
70*6dbdd20aSAndroid Build Coastguard Worker // Skip writing the closing brace since we'll append system trace data.
71*6dbdd20aSAndroid Build Coastguard Worker if (feof(*source))
72*6dbdd20aSAndroid Build Coastguard Worker size--;
73*6dbdd20aSAndroid Build Coastguard Worker writer->Write(buf, size);
74*6dbdd20aSAndroid Build Coastguard Worker }
75*6dbdd20aSAndroid Build Coastguard Worker return true;
76*6dbdd20aSAndroid Build Coastguard Worker }
77*6dbdd20aSAndroid Build Coastguard Worker
78*6dbdd20aSAndroid Build Coastguard Worker } // namespace
79*6dbdd20aSAndroid Build Coastguard Worker
TraceToJson(std::istream * input,std::ostream * output,bool compress,Keep truncate_keep,bool full_sort)80*6dbdd20aSAndroid Build Coastguard Worker int TraceToJson(std::istream* input,
81*6dbdd20aSAndroid Build Coastguard Worker std::ostream* output,
82*6dbdd20aSAndroid Build Coastguard Worker bool compress,
83*6dbdd20aSAndroid Build Coastguard Worker Keep truncate_keep,
84*6dbdd20aSAndroid Build Coastguard Worker bool full_sort) {
85*6dbdd20aSAndroid Build Coastguard Worker std::unique_ptr<TraceWriter> trace_writer(
86*6dbdd20aSAndroid Build Coastguard Worker compress ? new DeflateTraceWriter(output) : new TraceWriter(output));
87*6dbdd20aSAndroid Build Coastguard Worker
88*6dbdd20aSAndroid Build Coastguard Worker trace_processor::Config config;
89*6dbdd20aSAndroid Build Coastguard Worker config.sorting_mode = full_sort
90*6dbdd20aSAndroid Build Coastguard Worker ? trace_processor::SortingMode::kForceFullSort
91*6dbdd20aSAndroid Build Coastguard Worker : trace_processor::SortingMode::kDefaultHeuristics;
92*6dbdd20aSAndroid Build Coastguard Worker std::unique_ptr<trace_processor::TraceProcessor> tp =
93*6dbdd20aSAndroid Build Coastguard Worker trace_processor::TraceProcessor::CreateInstance(config);
94*6dbdd20aSAndroid Build Coastguard Worker
95*6dbdd20aSAndroid Build Coastguard Worker if (!ReadTraceUnfinalized(tp.get(), input))
96*6dbdd20aSAndroid Build Coastguard Worker return 1;
97*6dbdd20aSAndroid Build Coastguard Worker if (auto status = tp->NotifyEndOfFile(); !status.ok()) {
98*6dbdd20aSAndroid Build Coastguard Worker return 1;
99*6dbdd20aSAndroid Build Coastguard Worker }
100*6dbdd20aSAndroid Build Coastguard Worker
101*6dbdd20aSAndroid Build Coastguard Worker // TODO(eseckler): Support truncation of userspace event data.
102*6dbdd20aSAndroid Build Coastguard Worker if (ExportUserspaceEvents(tp.get(), trace_writer.get())) {
103*6dbdd20aSAndroid Build Coastguard Worker trace_writer->Write(",\n");
104*6dbdd20aSAndroid Build Coastguard Worker } else {
105*6dbdd20aSAndroid Build Coastguard Worker trace_writer->Write(kTraceHeader);
106*6dbdd20aSAndroid Build Coastguard Worker }
107*6dbdd20aSAndroid Build Coastguard Worker
108*6dbdd20aSAndroid Build Coastguard Worker int ret = ExtractSystrace(tp.get(), trace_writer.get(),
109*6dbdd20aSAndroid Build Coastguard Worker /*wrapped_in_json=*/true, truncate_keep);
110*6dbdd20aSAndroid Build Coastguard Worker if (ret)
111*6dbdd20aSAndroid Build Coastguard Worker return ret;
112*6dbdd20aSAndroid Build Coastguard Worker
113*6dbdd20aSAndroid Build Coastguard Worker trace_writer->Write(kTraceFooter);
114*6dbdd20aSAndroid Build Coastguard Worker return 0;
115*6dbdd20aSAndroid Build Coastguard Worker }
116*6dbdd20aSAndroid Build Coastguard Worker
117*6dbdd20aSAndroid Build Coastguard Worker } // namespace trace_to_text
118*6dbdd20aSAndroid Build Coastguard Worker } // namespace perfetto
119