Home | History | Annotate | Download | only in test
      1 // Copyright (c) 2014 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "base/test/trace_to_file.h"
      6 
      7 #include "base/base_switches.h"
      8 #include "base/command_line.h"
      9 #include "base/debug/trace_event_impl.h"
     10 #include "base/files/file_util.h"
     11 #include "base/run_loop.h"
     12 
     13 namespace base {
     14 namespace test {
     15 
     16 TraceToFile::TraceToFile() : started_(false) {
     17 }
     18 
     19 TraceToFile::~TraceToFile() {
     20   EndTracingIfNeeded();
     21 }
     22 
     23 void TraceToFile::BeginTracingFromCommandLineOptions() {
     24   DCHECK(CommandLine::InitializedForCurrentProcess());
     25   DCHECK(!started_);
     26 
     27   if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kTraceToFile))
     28     return;
     29 
     30   // Empty filter (i.e. just --trace-to-file) turns into default categories in
     31   // TraceEventImpl
     32   std::string filter = CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
     33       switches::kTraceToFile);
     34 
     35   FilePath path;
     36   if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kTraceToFileName)) {
     37     path = FilePath(CommandLine::ForCurrentProcess()
     38                         ->GetSwitchValuePath(switches::kTraceToFileName));
     39   } else {
     40     path = FilePath(FILE_PATH_LITERAL("trace.json"));
     41   }
     42 
     43   BeginTracing(path, filter);
     44 }
     45 
     46 void TraceToFile::BeginTracing(const FilePath& path,
     47                                const std::string& categories) {
     48   DCHECK(!started_);
     49   started_ = true;
     50   path_ = path;
     51   WriteFileHeader();
     52 
     53   debug::TraceLog::GetInstance()->SetEnabled(
     54       debug::CategoryFilter(categories),
     55       debug::TraceLog::RECORDING_MODE,
     56       debug::TraceOptions(debug::RECORD_UNTIL_FULL));
     57 }
     58 
     59 void TraceToFile::WriteFileHeader() {
     60   const char str[] = "{\"traceEvents\": [";
     61   WriteFile(path_, str, static_cast<int>(strlen(str)));
     62 }
     63 
     64 void TraceToFile::AppendFileFooter() {
     65   const char str[] = "]}";
     66   AppendToFile(path_, str, static_cast<int>(strlen(str)));
     67 }
     68 
     69 void TraceToFile::TraceOutputCallback(const std::string& data) {
     70   int ret = AppendToFile(path_, data.c_str(), static_cast<int>(data.size()));
     71   DCHECK_NE(-1, ret);
     72 }
     73 
     74 static void OnTraceDataCollected(
     75     Closure quit_closure,
     76     debug::TraceResultBuffer* buffer,
     77     const scoped_refptr<RefCountedString>& json_events_str,
     78     bool has_more_events) {
     79   buffer->AddFragment(json_events_str->data());
     80   if (!has_more_events)
     81     quit_closure.Run();
     82 }
     83 
     84 void TraceToFile::EndTracingIfNeeded() {
     85   if (!started_)
     86     return;
     87   started_ = false;
     88 
     89   debug::TraceLog::GetInstance()->SetDisabled();
     90 
     91   debug::TraceResultBuffer buffer;
     92   buffer.SetOutputCallback(
     93       Bind(&TraceToFile::TraceOutputCallback, Unretained(this)));
     94 
     95   RunLoop run_loop;
     96   debug::TraceLog::GetInstance()->Flush(
     97       Bind(&OnTraceDataCollected, run_loop.QuitClosure(), Unretained(&buffer)));
     98   run_loop.Run();
     99 
    100   AppendFileFooter();
    101 }
    102 
    103 }  // namespace test
    104 }  // namespace base
    105