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