blob: fab2df383e3f3853f650280569e372f127633832 [file] [log] [blame]
Fabien Sanglard2d34e762019-02-21 15:13:29 -08001/*
2 * Copyright (C) 2019 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "TraceBuffer.h"
18
19#include <chrono>
20#include <sstream>
21#include <unistd.h>
22#include <vector>
23
24#include <inttypes.h>
25
26#include "android-base/utf8.h"
27
28#include "util/Files.h"
29
30namespace aapt {
31namespace tracebuffer {
32
33namespace {
34
35constexpr char kBegin = 'B';
36constexpr char kEnd = 'E';
37
38struct TracePoint {
Yurii Zubrytskyi76d51b12023-08-16 13:45:09 -070039 char type;
Fabien Sanglard2d34e762019-02-21 15:13:29 -080040 pid_t tid;
41 int64_t time;
42 std::string tag;
Fabien Sanglard2d34e762019-02-21 15:13:29 -080043};
44
45std::vector<TracePoint> traces;
Yurii Zubrytskyi76d51b12023-08-16 13:45:09 -070046bool enabled = true;
Fabien Sanglard2d34e762019-02-21 15:13:29 -080047
48int64_t GetTime() noexcept {
49 auto now = std::chrono::steady_clock::now();
50 return std::chrono::duration_cast<std::chrono::microseconds>(now.time_since_epoch()).count();
51}
52
53} // namespace anonymous
54
Yurii Zubrytskyi76d51b12023-08-16 13:45:09 -070055void AddWithTime(std::string tag, char type, int64_t time) noexcept {
56 TracePoint t = {type, getpid(), time, std::move(tag)};
57 traces.emplace_back(std::move(t));
Fabien Sanglard2d34e762019-02-21 15:13:29 -080058}
59
Yurii Zubrytskyi76d51b12023-08-16 13:45:09 -070060void Add(std::string tag, char type) noexcept {
61 AddWithTime(std::move(tag), type, GetTime());
Fabien Sanglard2d34e762019-02-21 15:13:29 -080062}
63
Fabien Sanglard2d34e762019-02-21 15:13:29 -080064void Flush(const std::string& basePath) {
Fabien Sanglard2d34e762019-02-21 15:13:29 -080065 if (basePath.empty()) {
66 return;
67 }
Yurii Zubrytskyi76d51b12023-08-16 13:45:09 -070068 BeginTrace(__func__); // We can't do much here, only record that it happened.
Fabien Sanglard2d34e762019-02-21 15:13:29 -080069
Yurii Zubrytskyi76d51b12023-08-16 13:45:09 -070070 std::ostringstream s;
Fabien Sanglard2d34e762019-02-21 15:13:29 -080071 s << basePath << aapt::file::sDirSep << "report_aapt2_" << getpid() << ".json";
72 FILE* f = android::base::utf8::fopen(s.str().c_str(), "a");
73 if (f == nullptr) {
74 return;
75 }
76
Yurii Zubrytskyi76d51b12023-08-16 13:45:09 -070077 // Wrap the trace in a JSON array [] to make Chrome/Perfetto UI handle it.
78 char delimiter = '[';
Fabien Sanglard2d34e762019-02-21 15:13:29 -080079 for(const TracePoint& trace : traces) {
Yurii Zubrytskyi76d51b12023-08-16 13:45:09 -070080 fprintf(f,
81 "%c{\"ts\" : \"%" PRIu64
82 "\", \"ph\" : \"%c\", \"tid\" : \"%d\" , \"pid\" : \"%d\", \"name\" : \"%s\" }\n",
83 delimiter, trace.time, trace.type, 0, trace.tid, trace.tag.c_str());
84 delimiter = ',';
85 }
86 if (!traces.empty()) {
87 fprintf(f, "]");
Fabien Sanglard2d34e762019-02-21 15:13:29 -080088 }
89 fclose(f);
90 traces.clear();
91}
92
93} // namespace tracebuffer
94
Yurii Zubrytskyi76d51b12023-08-16 13:45:09 -070095void BeginTrace(std::string tag) {
96 if (!tracebuffer::enabled) return;
97 tracebuffer::Add(std::move(tag), tracebuffer::kBegin);
Fabien Sanglard2d34e762019-02-21 15:13:29 -080098}
99
Yurii Zubrytskyi76d51b12023-08-16 13:45:09 -0700100void EndTrace(std::string tag) {
101 if (!tracebuffer::enabled) return;
102 tracebuffer::Add(std::move(tag), tracebuffer::kEnd);
Fabien Sanglard2d34e762019-02-21 15:13:29 -0800103}
104
Yurii Zubrytskyi76d51b12023-08-16 13:45:09 -0700105bool Trace::enable(bool value) {
106 return tracebuffer::enabled = value;
Fabien Sanglard2d34e762019-02-21 15:13:29 -0800107}
108
Yurii Zubrytskyi76d51b12023-08-16 13:45:09 -0700109Trace::Trace(const char* tag) {
110 if (!tracebuffer::enabled) return;
111 tag_.assign(tag);
112 tracebuffer::Add(tag_, tracebuffer::kBegin);
113}
114
115Trace::Trace(std::string tag) : tag_(std::move(tag)) {
116 if (!tracebuffer::enabled) return;
117 tracebuffer::Add(tag_, tracebuffer::kBegin);
118}
119
120template <class SpanOfStrings>
121std::string makeTag(std::string_view tag, const SpanOfStrings& args) {
122 std::ostringstream s;
Fabien Sanglard2d34e762019-02-21 15:13:29 -0800123 s << tag;
Yurii Zubrytskyi76d51b12023-08-16 13:45:09 -0700124 if (!args.empty()) {
125 for (const auto& arg : args) {
126 s << ' ';
127 s << arg;
128 }
Fabien Sanglard2d34e762019-02-21 15:13:29 -0800129 }
Yurii Zubrytskyi76d51b12023-08-16 13:45:09 -0700130 return std::move(s).str();
131}
132
133Trace::Trace(std::string_view tag, const std::vector<android::StringPiece>& args) {
134 if (!tracebuffer::enabled) return;
135 tag_ = makeTag(tag, args);
136 tracebuffer::Add(tag_, tracebuffer::kBegin);
Fabien Sanglard2d34e762019-02-21 15:13:29 -0800137}
138
139Trace::~Trace() {
Yurii Zubrytskyi76d51b12023-08-16 13:45:09 -0700140 if (!tracebuffer::enabled) return;
141 tracebuffer::Add(std::move(tag_), tracebuffer::kEnd);
Fabien Sanglard2d34e762019-02-21 15:13:29 -0800142}
143
Yurii Zubrytskyi76d51b12023-08-16 13:45:09 -0700144FlushTrace::FlushTrace(std::string_view basepath, std::string_view tag) {
145 if (!Trace::enable(!basepath.empty())) return;
146 basepath_.assign(basepath);
147 tag_.assign(tag);
148 tracebuffer::Add(tag_, tracebuffer::kBegin);
Fabien Sanglard2d34e762019-02-21 15:13:29 -0800149}
150
Yurii Zubrytskyi76d51b12023-08-16 13:45:09 -0700151FlushTrace::FlushTrace(std::string_view basepath, std::string_view tag,
152 const std::vector<android::StringPiece>& args) {
153 if (!Trace::enable(!basepath.empty())) return;
154 basepath_.assign(basepath);
155 tag_ = makeTag(tag, args);
156 tracebuffer::Add(tag_, tracebuffer::kBegin);
Fabien Sanglard2d34e762019-02-21 15:13:29 -0800157}
158
Yurii Zubrytskyi76d51b12023-08-16 13:45:09 -0700159FlushTrace::FlushTrace(std::string_view basepath, std::string_view tag,
160 const std::vector<std::string>& args) {
161 if (!Trace::enable(!basepath.empty())) return;
162 basepath_.assign(basepath);
163 tag_ = makeTag(tag, args);
164 tracebuffer::Add(tag_, tracebuffer::kBegin);
Fabien Sanglard2d34e762019-02-21 15:13:29 -0800165}
166
167FlushTrace::~FlushTrace() {
Yurii Zubrytskyi76d51b12023-08-16 13:45:09 -0700168 if (!tracebuffer::enabled) return;
169 tracebuffer::Add(tag_, tracebuffer::kEnd);
Fabien Sanglard2d34e762019-02-21 15:13:29 -0800170 tracebuffer::Flush(basepath_);
171}
172
Yurii Zubrytskyi76d51b12023-08-16 13:45:09 -0700173} // namespace aapt