Home | History | Annotate | Download | only in trace
      1 /*
      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 
     30 namespace aapt {
     31 namespace tracebuffer {
     32 
     33 namespace {
     34 
     35 constexpr char kBegin = 'B';
     36 constexpr char kEnd = 'E';
     37 
     38 struct TracePoint {
     39   pid_t tid;
     40   int64_t time;
     41   std::string tag;
     42   char type;
     43 };
     44 
     45 std::vector<TracePoint> traces;
     46 
     47 int64_t GetTime() noexcept {
     48   auto now = std::chrono::steady_clock::now();
     49   return std::chrono::duration_cast<std::chrono::microseconds>(now.time_since_epoch()).count();
     50 }
     51 
     52 } // namespace anonymous
     53 
     54 void AddWithTime(const std::string& tag, char type, int64_t time) noexcept {
     55   TracePoint t = {getpid(), time, tag, type};
     56   traces.emplace_back(t);
     57 }
     58 
     59 void Add(const std::string& tag, char type) noexcept {
     60   AddWithTime(tag, type, GetTime());
     61 }
     62 
     63 
     64 
     65 
     66 void Flush(const std::string& basePath) {
     67   TRACE_CALL();
     68   if (basePath.empty()) {
     69     return;
     70   }
     71 
     72   std::stringstream s;
     73   s << basePath << aapt::file::sDirSep << "report_aapt2_" << getpid() << ".json";
     74   FILE* f = android::base::utf8::fopen(s.str().c_str(), "a");
     75   if (f == nullptr) {
     76     return;
     77   }
     78 
     79   for(const TracePoint& trace : traces) {
     80     fprintf(f, "{\"ts\" : \"%" PRIu64 "\", \"ph\" : \"%c\", \"tid\" : \"%d\" , \"pid\" : \"%d\", "
     81             "\"name\" : \"%s\" },\n", trace.time, trace.type, 0, trace.tid, trace.tag.c_str());
     82   }
     83   fclose(f);
     84   traces.clear();
     85 }
     86 
     87 } // namespace tracebuffer
     88 
     89 void BeginTrace(const std::string& tag) {
     90   tracebuffer::Add(tag, tracebuffer::kBegin);
     91 }
     92 
     93 void EndTrace() {
     94   tracebuffer::Add("", tracebuffer::kEnd);
     95 }
     96 
     97 Trace::Trace(const std::string& tag) {
     98   tracebuffer::Add(tag, tracebuffer::kBegin);
     99 }
    100 
    101 Trace::Trace(const std::string& tag, const std::vector<android::StringPiece>& args) {
    102   std::stringstream s;
    103   s << tag;
    104   s << " ";
    105   for (auto& arg : args) {
    106     s << arg.to_string();
    107     s << " ";
    108   }
    109   tracebuffer::Add(s.str(), tracebuffer::kBegin);
    110 }
    111 
    112 Trace::~Trace() {
    113   tracebuffer::Add("", tracebuffer::kEnd);
    114 }
    115 
    116 FlushTrace::FlushTrace(const std::string& basepath, const std::string& tag)
    117     : basepath_(basepath)  {
    118   tracebuffer::Add(tag, tracebuffer::kBegin);
    119 }
    120 
    121 FlushTrace::FlushTrace(const std::string& basepath, const std::string& tag,
    122     const std::vector<android::StringPiece>& args) : basepath_(basepath) {
    123   std::stringstream s;
    124   s << tag;
    125   s << " ";
    126   for (auto& arg : args) {
    127     s << arg.to_string();
    128     s << " ";
    129   }
    130   tracebuffer::Add(s.str(), tracebuffer::kBegin);
    131 }
    132 
    133 FlushTrace::FlushTrace(const std::string& basepath, const std::string& tag,
    134     const std::vector<std::string>& args) : basepath_(basepath){
    135   std::stringstream s;
    136   s << tag;
    137   s << " ";
    138   for (auto& arg : args) {
    139     s << arg;
    140     s << " ";
    141   }
    142   tracebuffer::Add(s.str(), tracebuffer::kBegin);
    143 }
    144 
    145 FlushTrace::~FlushTrace() {
    146   tracebuffer::Add("", tracebuffer::kEnd);
    147   tracebuffer::Flush(basepath_);
    148 }
    149 
    150 } // namespace aapt
    151 
    152