// Copyright (c) 2014 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "base/test/trace_to_file.h" #include "base/base_switches.h" #include "base/command_line.h" #include "base/debug/trace_event_impl.h" #include "base/files/file_util.h" #include "base/run_loop.h" namespace base { namespace test { TraceToFile::TraceToFile() : started_(false) { } TraceToFile::~TraceToFile() { EndTracingIfNeeded(); } void TraceToFile::BeginTracingFromCommandLineOptions() { DCHECK(CommandLine::InitializedForCurrentProcess()); DCHECK(!started_); if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kTraceToFile)) return; // Empty filter (i.e. just --trace-to-file) turns into default categories in // TraceEventImpl std::string filter = CommandLine::ForCurrentProcess()->GetSwitchValueASCII( switches::kTraceToFile); FilePath path; if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kTraceToFileName)) { path = FilePath(CommandLine::ForCurrentProcess() ->GetSwitchValuePath(switches::kTraceToFileName)); } else { path = FilePath(FILE_PATH_LITERAL("trace.json")); } BeginTracing(path, filter); } void TraceToFile::BeginTracing(const FilePath& path, const std::string& categories) { DCHECK(!started_); started_ = true; path_ = path; WriteFileHeader(); debug::TraceLog::GetInstance()->SetEnabled( debug::CategoryFilter(categories), debug::TraceLog::RECORDING_MODE, debug::TraceOptions(debug::RECORD_UNTIL_FULL)); } void TraceToFile::WriteFileHeader() { const char str[] = "{\"traceEvents\": ["; WriteFile(path_, str, static_cast<int>(strlen(str))); } void TraceToFile::AppendFileFooter() { const char str[] = "]}"; AppendToFile(path_, str, static_cast<int>(strlen(str))); } void TraceToFile::TraceOutputCallback(const std::string& data) { int ret = AppendToFile(path_, data.c_str(), static_cast<int>(data.size())); DCHECK_NE(-1, ret); } static void OnTraceDataCollected( Closure quit_closure, debug::TraceResultBuffer* buffer, const scoped_refptr<RefCountedString>& json_events_str, bool has_more_events) { buffer->AddFragment(json_events_str->data()); if (!has_more_events) quit_closure.Run(); } void TraceToFile::EndTracingIfNeeded() { if (!started_) return; started_ = false; debug::TraceLog::GetInstance()->SetDisabled(); debug::TraceResultBuffer buffer; buffer.SetOutputCallback( Bind(&TraceToFile::TraceOutputCallback, Unretained(this))); RunLoop run_loop; debug::TraceLog::GetInstance()->Flush( Bind(&OnTraceDataCollected, run_loop.QuitClosure(), Unretained(&buffer))); run_loop.Run(); AppendFileFooter(); } } // namespace test } // namespace base