• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/bind.h"
9 #include "base/command_line.h"
10 #include "base/files/file_util.h"
11 #include "base/memory/ref_counted_memory.h"
12 #include "base/run_loop.h"
13 #include "base/trace_event/trace_buffer.h"
14 #include "base/trace_event/trace_log.h"
15 
16 namespace base {
17 namespace test {
18 
TraceToFile()19 TraceToFile::TraceToFile() : started_(false) {
20 }
21 
~TraceToFile()22 TraceToFile::~TraceToFile() {
23   EndTracingIfNeeded();
24 }
25 
BeginTracingFromCommandLineOptions()26 void TraceToFile::BeginTracingFromCommandLineOptions() {
27   DCHECK(CommandLine::InitializedForCurrentProcess());
28   DCHECK(!started_);
29 
30   if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kTraceToFile))
31     return;
32 
33   // Empty filter (i.e. just --trace-to-file) turns into default categories in
34   // TraceEventImpl
35   std::string filter = CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
36       switches::kTraceToFile);
37 
38   FilePath path;
39   if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kTraceToFileName)) {
40     path = FilePath(CommandLine::ForCurrentProcess()
41                         ->GetSwitchValuePath(switches::kTraceToFileName));
42   } else {
43     path = FilePath(FILE_PATH_LITERAL("trace.json"));
44   }
45 
46   BeginTracing(path, filter);
47 }
48 
BeginTracing(const FilePath & path,const std::string & categories)49 void TraceToFile::BeginTracing(const FilePath& path,
50                                const std::string& categories) {
51   DCHECK(!started_);
52   started_ = true;
53   path_ = path;
54   WriteFileHeader();
55 
56   trace_event::TraceLog::GetInstance()->SetEnabled(
57       trace_event::TraceConfig(categories, trace_event::RECORD_UNTIL_FULL),
58       trace_event::TraceLog::RECORDING_MODE);
59 }
60 
WriteFileHeader()61 void TraceToFile::WriteFileHeader() {
62   const char str[] = "{\"traceEvents\": [";
63   WriteFile(path_, str, static_cast<int>(strlen(str)));
64 }
65 
AppendFileFooter()66 void TraceToFile::AppendFileFooter() {
67   const char str[] = "]}";
68   AppendToFile(path_, str, static_cast<int>(strlen(str)));
69 }
70 
TraceOutputCallback(const std::string & data)71 void TraceToFile::TraceOutputCallback(const std::string& data) {
72   bool ret = AppendToFile(path_, data.c_str(), static_cast<int>(data.size()));
73   DCHECK(ret);
74 }
75 
OnTraceDataCollected(Closure quit_closure,trace_event::TraceResultBuffer * buffer,const scoped_refptr<RefCountedString> & json_events_str,bool has_more_events)76 static void OnTraceDataCollected(
77     Closure quit_closure,
78     trace_event::TraceResultBuffer* buffer,
79     const scoped_refptr<RefCountedString>& json_events_str,
80     bool has_more_events) {
81   buffer->AddFragment(json_events_str->data());
82   if (!has_more_events)
83     quit_closure.Run();
84 }
85 
EndTracingIfNeeded()86 void TraceToFile::EndTracingIfNeeded() {
87   if (!started_)
88     return;
89   started_ = false;
90 
91   trace_event::TraceLog::GetInstance()->SetDisabled();
92 
93   trace_event::TraceResultBuffer buffer;
94   buffer.SetOutputCallback(
95       Bind(&TraceToFile::TraceOutputCallback, Unretained(this)));
96 
97   RunLoop run_loop;
98   trace_event::TraceLog::GetInstance()->Flush(
99       Bind(&OnTraceDataCollected, run_loop.QuitClosure(), Unretained(&buffer)));
100   run_loop.Run();
101 
102   AppendFileFooter();
103 }
104 
105 }  // namespace test
106 }  // namespace base
107