trace_to_file.cc 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  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. #include "base/test/trace_to_file.h"
  5. #include "base/base_switches.h"
  6. #include "base/bind.h"
  7. #include "base/command_line.h"
  8. #include "base/files/file_util.h"
  9. #include "base/memory/ref_counted_memory.h"
  10. #include "base/run_loop.h"
  11. #include "base/test/task_environment.h"
  12. #include "base/threading/thread_task_runner_handle.h"
  13. #include "base/trace_event/trace_buffer.h"
  14. #include "base/trace_event/trace_log.h"
  15. namespace base {
  16. namespace test {
  17. TraceToFile::TraceToFile() : started_(false) {
  18. }
  19. TraceToFile::~TraceToFile() {
  20. EndTracingIfNeeded();
  21. }
  22. void TraceToFile::BeginTracingFromCommandLineOptions() {
  23. DCHECK(CommandLine::InitializedForCurrentProcess());
  24. DCHECK(!started_);
  25. if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kTraceToFile))
  26. return;
  27. // Empty filter (i.e. just --trace-to-file) turns into default categories in
  28. // TraceEventImpl
  29. std::string filter = CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
  30. switches::kTraceToFile);
  31. FilePath path;
  32. if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kTraceToFileName)) {
  33. path = FilePath(CommandLine::ForCurrentProcess()
  34. ->GetSwitchValuePath(switches::kTraceToFileName));
  35. } else {
  36. path = FilePath(FILE_PATH_LITERAL("trace.json"));
  37. }
  38. BeginTracing(path, filter);
  39. }
  40. void TraceToFile::BeginTracing(const FilePath& path,
  41. const std::string& categories) {
  42. DCHECK(!started_);
  43. started_ = true;
  44. path_ = path;
  45. WriteFileHeader();
  46. trace_event::TraceLog::GetInstance()->SetEnabled(
  47. trace_event::TraceConfig(categories, trace_event::RECORD_UNTIL_FULL),
  48. trace_event::TraceLog::RECORDING_MODE);
  49. }
  50. void TraceToFile::WriteFileHeader() {
  51. WriteFile(path_, "{\"traceEvents\": [");
  52. }
  53. void TraceToFile::AppendFileFooter() {
  54. const char str[] = "]}";
  55. AppendToFile(path_, str);
  56. }
  57. void TraceToFile::TraceOutputCallback(const std::string& data) {
  58. bool ret = AppendToFile(path_, data);
  59. DCHECK(ret);
  60. }
  61. static void OnTraceDataCollected(
  62. OnceClosure quit_closure,
  63. trace_event::TraceResultBuffer* buffer,
  64. const scoped_refptr<RefCountedString>& json_events_str,
  65. bool has_more_events) {
  66. buffer->AddFragment(json_events_str->data());
  67. if (!has_more_events)
  68. std::move(quit_closure).Run();
  69. }
  70. void TraceToFile::EndTracingIfNeeded() {
  71. if (!started_)
  72. return;
  73. started_ = false;
  74. trace_event::TraceLog::GetInstance()->SetDisabled();
  75. trace_event::TraceResultBuffer buffer;
  76. buffer.SetOutputCallback(
  77. BindRepeating(&TraceToFile::TraceOutputCallback, Unretained(this)));
  78. // In tests we might not have a TaskEnvironment, create one if needed.
  79. std::unique_ptr<SingleThreadTaskEnvironment> task_environment;
  80. if (!ThreadTaskRunnerHandle::IsSet())
  81. task_environment = std::make_unique<SingleThreadTaskEnvironment>();
  82. RunLoop run_loop;
  83. trace_event::TraceLog::GetInstance()->Flush(BindRepeating(
  84. &OnTraceDataCollected, run_loop.QuitClosure(), Unretained(&buffer)));
  85. run_loop.Run();
  86. AppendFileFooter();
  87. }
  88. } // namespace test
  89. } // namespace base