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
3 // found in the LICENSE file.
5 #include "content/browser/tracing/trace_subscriber_stdio.h"
8 #include "base/debug/trace_event.h"
9 #include "base/file_util.h"
10 #include "base/logging.h"
11 #include "base/threading/sequenced_worker_pool.h"
12 #include "content/public/browser/browser_thread.h"
16 // All method calls on this class are done on a SequencedWorkerPool thread.
17 class TraceSubscriberStdio::TraceSubscriberStdioWorker
18 : public base::RefCountedThreadSafe
<TraceSubscriberStdioWorker
> {
20 TraceSubscriberStdioWorker(const base::FilePath
& path
,
22 bool has_system_trace
)
24 file_type_(file_type
),
25 has_system_trace_(has_system_trace
),
29 has_pending_system_trace_(false),
30 wrote_system_trace_(false) {}
34 file_
= file_util::OpenFile(path_
, "w+");
36 LOG(ERROR
) << "Failed to open performance trace file: " << path_
.value();
40 LOG(INFO
) << "Logging performance trace to file: " << path_
.value();
41 if (file_type_
== FILE_TYPE_PROPERTY_LIST
)
42 WriteString("{\"traceEvents\":");
46 void OnTraceData(const scoped_refptr
<base::RefCountedString
>& data_ptr
) {
49 DCHECK(!data_ptr
->data().empty());
52 WriteString(data_ptr
->data());
56 void OnSystemTraceData(
57 const scoped_refptr
<base::RefCountedString
>& data_ptr
) {
59 WriteSystemTrace(data_ptr
);
62 pending_system_trace_
= data_ptr
;
63 has_pending_system_trace_
= true;
74 if (!has_system_trace_
|| wrote_system_trace_
) {
80 if (has_pending_system_trace_
) {
81 WriteSystemTrace(pending_system_trace_
);
87 friend class base::RefCountedThreadSafe
<TraceSubscriberStdioWorker
>;
89 ~TraceSubscriberStdioWorker() {
93 bool IsValid() const {
94 return file_
&& (0 == ferror(file_
));
106 if (file_type_
== FILE_TYPE_PROPERTY_LIST
)
111 void WriteSystemTrace(const scoped_refptr
<base::RefCountedString
>& data_ptr
) {
112 // Newlines need to be replaced with the string "\n" to be parsed correctly.
113 // Double quotes need to be replaced with the string "\"".
114 // System logs are ASCII.
115 const std::string
& data
= data_ptr
->data();
116 const char* chars
= data
.c_str();
117 WriteString("\"systemTraceEvents\":\"");
118 size_t old_index
= 0;
119 for (size_t new_index
= data
.find_first_of("\n\"");
120 std::string::npos
!= new_index
;
121 old_index
= new_index
+ 1,
122 new_index
= data
.find_first_of("\n\"", old_index
)) {
123 WriteChars(chars
+ old_index
, new_index
- old_index
);
124 if (chars
[new_index
] == '\n')
125 WriteChars("\\n", 2);
127 WriteChars("\\\"", 2);
129 WriteChars(chars
+ old_index
, data
.size() - old_index
);
131 wrote_system_trace_
= true;
134 void WriteChars(const char* output_chars
, size_t size
) {
139 size_t written
= fwrite(output_chars
, 1, size
, file_
);
140 if (written
!= size
) {
141 LOG(ERROR
) << "Error " << ferror(file_
) << " in fwrite() to trace file";
147 void WriteString(const std::string
& output_str
) {
148 WriteChars(output_str
.data(), output_str
.size());
151 base::FilePath path_
;
152 const FileType file_type_
;
153 const bool has_system_trace_
;
157 bool has_pending_system_trace_
;
158 bool wrote_system_trace_
;
159 scoped_refptr
<base::RefCountedString
> pending_system_trace_
;
160 DISALLOW_COPY_AND_ASSIGN(TraceSubscriberStdioWorker
);
163 TraceSubscriberStdio::TraceSubscriberStdio(const base::FilePath
& path
,
165 bool has_system_trace
)
166 : worker_(new TraceSubscriberStdioWorker(path
,
169 if (has_system_trace
)
170 CHECK_EQ(FILE_TYPE_PROPERTY_LIST
, file_type
);
171 BrowserThread::PostBlockingPoolSequencedTask(
173 base::Bind(&TraceSubscriberStdioWorker::OnTraceStart
, worker_
));
176 TraceSubscriberStdio::~TraceSubscriberStdio() {
179 void TraceSubscriberStdio::OnEndTracingComplete() {
180 BrowserThread::PostBlockingPoolSequencedTask(
182 base::Bind(&TraceSubscriberStdioWorker::OnTraceEnd
, worker_
));
185 void TraceSubscriberStdio::OnTraceDataCollected(
186 const scoped_refptr
<base::RefCountedString
>& data_ptr
) {
187 BrowserThread::PostBlockingPoolSequencedTask(
189 base::Bind(&TraceSubscriberStdioWorker::OnTraceData
, worker_
, data_ptr
));
192 void TraceSubscriberStdio::OnEndSystemTracing(
193 const scoped_refptr
<base::RefCountedString
>& events_str_ptr
) {
194 BrowserThread::PostBlockingPoolSequencedTask(
196 base::Bind(&TraceSubscriberStdioWorker::OnSystemTraceData
,
201 } // namespace content