Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(303)

Side by Side Diff: content/browser/tracing/trace_subscriber_stdio.cc

Issue 23125009: Add support for writing system traces at startup (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/browser/tracing/trace_subscriber_stdio.h" 5 #include "content/browser/tracing/trace_subscriber_stdio.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/debug/trace_event.h" 8 #include "base/debug/trace_event.h"
9 #include "base/file_util.h" 9 #include "base/file_util.h"
10 #include "base/logging.h" 10 #include "base/logging.h"
11 #include "base/threading/sequenced_worker_pool.h" 11 #include "base/threading/sequenced_worker_pool.h"
12 #include "content/public/browser/browser_thread.h" 12 #include "content/public/browser/browser_thread.h"
13 13
14 namespace content { 14 namespace content {
15 15
16 // All method calls on this class are done on a SequencedWorkerPool thread. 16 // All method calls on this class are done on a SequencedWorkerPool thread.
17 class TraceSubscriberStdioImpl 17 class TraceSubscriberStdio::TraceSubscriberStdioWorker
18 : public base::RefCountedThreadSafe<TraceSubscriberStdioImpl> { 18 : public base::RefCountedThreadSafe<TraceSubscriberStdioWorker> {
19 public: 19 public:
20 explicit TraceSubscriberStdioImpl(const base::FilePath& path) 20 explicit TraceSubscriberStdioWorker(const base::FilePath& path,
21 FileType file_type,
22 bool has_system_trace)
21 : path_(path), 23 : path_(path),
22 file_(0) {} 24 file_type_(file_type),
25 has_system_trace_(has_system_trace),
26 file_(0),
27 needs_comma_(false),
28 wrote_trace_(false),
29 has_pending_system_trace_(false),
30 wrote_system_trace_(false) {}
23 31
24 void OnStart() { 32 void OnTraceStart() {
25 DCHECK(!file_); 33 DCHECK(!file_);
26 trace_buffer_.SetOutputCallback(
27 base::Bind(&TraceSubscriberStdioImpl::Write, this));
28 file_ = file_util::OpenFile(path_, "w+"); 34 file_ = file_util::OpenFile(path_, "w+");
29 if (IsValid()) { 35 if (!IsValid()) {
30 LOG(INFO) << "Logging performance trace to file: " << path_.value(); 36 LOG(ERROR) << "Failed to open performance trace file: " << path_.value();
31 trace_buffer_.Start(); 37 return;
38 }
39
40 LOG(INFO) << "Logging performance trace to file: " << path_.value();
41 if (file_type_ == FILE_TYPE_PROPERTY_LIST)
42 WriteString("{\"traceEvents\":");
43 WriteString("[");
44 }
45
46 void OnTraceData(const scoped_refptr<base::RefCountedString>& data_ptr) {
47 if (!IsValid())
48 return;
49 if (needs_comma_)
50 WriteString(",");
51 WriteString(data_ptr->data());
52 needs_comma_ = true;
53 }
54
55 void OnSystemTraceData(
56 const scoped_refptr<base::RefCountedString>& data_ptr) {
dsinclair 2013/08/19 20:12:26 nit: indenting.
DaveMoore 2013/08/19 22:07:46 Done.
57 if (wrote_trace_) {
58 WriteSystemTrace(data_ptr);
59 End();
32 } else { 60 } else {
33 LOG(ERROR) << "Failed to open performance trace file: " << path_.value(); 61 pending_system_trace_ = data_ptr;
62 has_pending_system_trace_ = true;
34 } 63 }
35 } 64 }
36 65
37 void OnData(const scoped_refptr<base::RefCountedString>& data_ptr) { 66 void OnTraceEnd() {
38 trace_buffer_.AddFragment(data_ptr->data()); 67 if (!IsValid())
68 return;
69 WriteString("]");
70
71 wrote_trace_ = true;
72
73 if (!has_system_trace_ || wrote_system_trace_) {
74 End();
75 return;
76 }
77
78 WriteString(",");
79 if (has_pending_system_trace_) {
80 WriteSystemTrace(pending_system_trace_);
81 End();
82 }
39 } 83 }
40 84
41 void OnEnd() { 85 private:
42 trace_buffer_.Finish(); 86 friend class base::RefCountedThreadSafe<TraceSubscriberStdioWorker>;
87
88 ~TraceSubscriberStdioWorker() {
43 CloseFile(); 89 CloseFile();
44 } 90 }
45 91
46 private:
47 friend class base::RefCountedThreadSafe<TraceSubscriberStdioImpl>;
48
49 ~TraceSubscriberStdioImpl() {
50 CloseFile();
51 }
52
53 bool IsValid() const { 92 bool IsValid() const {
54 return file_ && (0 == ferror(file_)); 93 return file_ && (0 == ferror(file_));
55 } 94 }
56 95
57 void CloseFile() { 96 void CloseFile() {
58 if (file_) { 97 if (file_) {
59 fclose(file_); 98 fclose(file_);
60 file_ = 0; 99 file_ = 0;
100
61 } 101 }
62 // This is important, as it breaks a reference cycle.
63 trace_buffer_.SetOutputCallback(
64 base::debug::TraceResultBuffer::OutputCallback());
65 } 102 }
66 103
67 void Write(const std::string& output_str) { 104 void End() {
105 if (file_type_ == FILE_TYPE_PROPERTY_LIST)
106 WriteString("}");
107 CloseFile();
108 }
109
110 void WriteSystemTrace(const scoped_refptr<base::RefCountedString>& data_ptr) {
111 // Newlines need to be replaced with the string "\n" to be parsed correctly.
112 std::string data = data_ptr->data();
113 const char* chars = data.data();
dsinclair 2013/08/19 20:12:26 Is it guaranteed that data() won't have any "'s in
DaveMoore 2013/08/19 22:07:46 Done.
114 WriteString("\"systemTraceEvents\":\"");
115 int old_index = 0;
116 for (size_t new_index = data.find('\n');
117 std::string::npos != new_index;
118 old_index = new_index + 1, new_index = data.find('\n', old_index)) {
119 WriteChars(chars + old_index, new_index - old_index);
120 WriteChars("\\n", 2);
121 }
122 WriteChars(chars + old_index, data.size() - old_index);
123 WriteString("\"");
124 wrote_system_trace_ = true;
125 }
126
127 void WriteChars(const char* output_chars, size_t size) {
68 if (IsValid()) { 128 if (IsValid()) {
dsinclair 2013/08/19 20:12:26 We seem to be doing if (!IsValid()) early returns
69 size_t written = fwrite(output_str.data(), 1, output_str.size(), file_); 129 size_t written = fwrite(output_chars, 1, size, file_);
70 if (written != output_str.size()) { 130 if (written != size) {
71 LOG(ERROR) << "Error " << ferror(file_) << " in fwrite() to trace file"; 131 LOG(ERROR) << "Error " << ferror(file_) << " in fwrite() to trace file";
72 CloseFile(); 132 CloseFile();
73 } 133 }
74 } 134 }
75 } 135 }
76 136
137 void WriteString(const std::string& output_str) {
138 WriteChars(output_str.data(), output_str.size());
139 }
140
77 base::FilePath path_; 141 base::FilePath path_;
142 FileType file_type_;
143 bool has_system_trace_;
78 FILE* file_; 144 FILE* file_;
79 base::debug::TraceResultBuffer trace_buffer_; 145 bool needs_comma_;
146 bool wrote_trace_;
147 bool has_pending_system_trace_;
148 bool wrote_system_trace_;
149 scoped_refptr<base::RefCountedString> pending_system_trace_;
80 }; 150 };
81 151
82 TraceSubscriberStdio::TraceSubscriberStdio(const base::FilePath& path) 152 TraceSubscriberStdio::TraceSubscriberStdio(const base::FilePath& path,
83 : impl_(new TraceSubscriberStdioImpl(path)) { 153 FileType file_type,
154 bool has_system_trace)
155 : worker_(new TraceSubscriberStdioWorker(path,
156 file_type,
157 has_system_trace)) {
158 if (has_system_trace)
159 CHECK_EQ(FILE_TYPE_PROPERTY_LIST, file_type);
84 BrowserThread::PostBlockingPoolSequencedTask( 160 BrowserThread::PostBlockingPoolSequencedTask(
85 __FILE__, FROM_HERE, 161 __FILE__, FROM_HERE,
86 base::Bind(&TraceSubscriberStdioImpl::OnStart, impl_)); 162 base::Bind(&TraceSubscriberStdioWorker::OnTraceStart, worker_));
87 } 163 }
88 164
89 TraceSubscriberStdio::~TraceSubscriberStdio() { 165 TraceSubscriberStdio::~TraceSubscriberStdio() {
90 } 166 }
91 167
92 void TraceSubscriberStdio::OnEndTracingComplete() { 168 void TraceSubscriberStdio::OnEndTracingComplete() {
93 BrowserThread::PostBlockingPoolSequencedTask( 169 BrowserThread::PostBlockingPoolSequencedTask(
94 __FILE__, FROM_HERE, 170 __FILE__, FROM_HERE,
95 base::Bind(&TraceSubscriberStdioImpl::OnEnd, impl_)); 171 base::Bind(&TraceSubscriberStdioWorker::OnTraceEnd, worker_));
96 } 172 }
97 173
98 void TraceSubscriberStdio::OnTraceDataCollected( 174 void TraceSubscriberStdio::OnTraceDataCollected(
99 const scoped_refptr<base::RefCountedString>& data_ptr) { 175 const scoped_refptr<base::RefCountedString>& data_ptr) {
100 BrowserThread::PostBlockingPoolSequencedTask( 176 BrowserThread::PostBlockingPoolSequencedTask(
101 __FILE__, FROM_HERE, 177 __FILE__, FROM_HERE,
102 base::Bind(&TraceSubscriberStdioImpl::OnData, impl_, data_ptr)); 178 base::Bind(&TraceSubscriberStdioWorker::OnTraceData, worker_, data_ptr));
179 }
180
181 void TraceSubscriberStdio::OnEndSystemTracing(
182 const scoped_refptr<base::RefCountedString>& events_str_ptr) {
183 BrowserThread::PostBlockingPoolSequencedTask(
184 __FILE__, FROM_HERE,
185 base::Bind(&TraceSubscriberStdioWorker::OnSystemTraceData,
186 worker_,
187 events_str_ptr));
103 } 188 }
104 189
105 } // namespace content 190 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698