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

Side by Side Diff: services/shell/standalone/tracer.cc

Issue 2419723002: Move services/shell to services/service_manager (Closed)
Patch Set: rebase Created 4 years, 2 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
« no previous file with comments | « services/shell/standalone/tracer.h ('k') | services/shell/switches.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2015 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 "services/shell/standalone/tracer.h"
6
7 #include <stddef.h>
8 #include <stdio.h>
9 #include <string.h>
10 #include <utility>
11
12 #include "base/message_loop/message_loop.h"
13 #include "base/single_thread_task_runner.h"
14 #include "base/strings/string_number_conversions.h"
15 #include "base/synchronization/waitable_event.h"
16 #include "base/threading/thread.h"
17 #include "base/threading/thread_task_runner_handle.h"
18 #include "base/trace_event/trace_config.h"
19 #include "base/trace_event/trace_event.h"
20
21 namespace shell {
22
23 Tracer::Tracer()
24 : tracing_(false), first_chunk_written_(false), trace_file_(nullptr) {}
25
26 Tracer::~Tracer() {
27 StopAndFlushToFile();
28 }
29
30 void Tracer::Start(const std::string& categories,
31 const std::string& duration_seconds_str,
32 const std::string& filename) {
33 tracing_ = true;
34 trace_filename_ = filename;
35 categories_ = categories;
36 base::trace_event::TraceConfig config(categories,
37 base::trace_event::RECORD_UNTIL_FULL);
38 base::trace_event::TraceLog::GetInstance()->SetEnabled(
39 config, base::trace_event::TraceLog::RECORDING_MODE);
40
41 int trace_duration_secs = 5;
42 if (!duration_seconds_str.empty()) {
43 CHECK(base::StringToInt(duration_seconds_str, &trace_duration_secs))
44 << "Could not parse --trace-startup-duration value "
45 << duration_seconds_str;
46 }
47 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
48 FROM_HERE,
49 base::Bind(&Tracer::StopAndFlushToFile, base::Unretained(this)),
50 base::TimeDelta::FromSeconds(trace_duration_secs));
51 }
52
53 void Tracer::StartCollectingFromTracingService(
54 tracing::mojom::CollectorPtr coordinator) {
55 coordinator_ = std::move(coordinator);
56 mojo::DataPipe data_pipe;
57 coordinator_->Start(std::move(data_pipe.producer_handle), categories_);
58 drainer_.reset(new mojo::common::DataPipeDrainer(
59 this, std::move(data_pipe.consumer_handle)));
60 }
61
62 void Tracer::StopAndFlushToFile() {
63 if (tracing_)
64 StopTracingAndFlushToDisk();
65 }
66
67 void Tracer::ConnectToProvider(tracing::mojom::ProviderRequest request) {
68 provider_.Bind(std::move(request));
69 }
70
71 void Tracer::StopTracingAndFlushToDisk() {
72 tracing_ = false;
73 trace_file_ = fopen(trace_filename_.c_str(), "w+");
74 PCHECK(trace_file_);
75 static const char kStart[] = "{\"traceEvents\":[";
76 PCHECK(fwrite(kStart, 1, strlen(kStart), trace_file_) == strlen(kStart));
77
78 // At this point we might be connected to the tracing service, in which case
79 // we want to tell it to stop tracing and we will send the data we've
80 // collected in process to it.
81 if (coordinator_) {
82 coordinator_->StopAndFlush();
83 } else {
84 // Or we might not be connected. If we aren't connected to the tracing
85 // service we want to collect the tracing data gathered ourselves and flush
86 // it to disk. We do this in a blocking fashion (for this thread) so we can
87 // gather as much data as possible on shutdown.
88 base::trace_event::TraceLog::GetInstance()->SetDisabled();
89 {
90 base::WaitableEvent flush_complete_event(
91 base::WaitableEvent::ResetPolicy::AUTOMATIC,
92 base::WaitableEvent::InitialState::NOT_SIGNALED);
93 // TraceLog::Flush requires a message loop but we've already shut ours
94 // down.
95 // Spin up a new thread to flush things out.
96 base::Thread flush_thread("mojo_runner_trace_event_flush");
97 flush_thread.Start();
98 flush_thread.task_runner()->PostTask(
99 FROM_HERE,
100 base::Bind(&Tracer::EndTraceAndFlush, base::Unretained(this),
101 trace_filename_,
102 base::Bind(&base::WaitableEvent::Signal,
103 base::Unretained(&flush_complete_event))));
104 base::trace_event::TraceLog::GetInstance()
105 ->SetCurrentThreadBlocksMessageLoop();
106 flush_complete_event.Wait();
107 }
108 }
109 }
110
111 void Tracer::WriteFooterAndClose() {
112 static const char kEnd[] = "]}";
113 PCHECK(fwrite(kEnd, 1, strlen(kEnd), trace_file_) == strlen(kEnd));
114 PCHECK(fclose(trace_file_) == 0);
115 trace_file_ = nullptr;
116 LOG(ERROR) << "Wrote trace data to " << trace_filename_;
117 }
118
119 void Tracer::EndTraceAndFlush(const std::string& filename,
120 const base::Closure& done_callback) {
121 base::trace_event::TraceLog::GetInstance()->SetDisabled();
122 base::trace_event::TraceLog::GetInstance()->Flush(base::Bind(
123 &Tracer::WriteTraceDataCollected, base::Unretained(this), done_callback));
124 }
125
126 void Tracer::WriteTraceDataCollected(
127 const base::Closure& done_callback,
128 const scoped_refptr<base::RefCountedString>& events_str,
129 bool has_more_events) {
130 if (events_str->size()) {
131 WriteCommaIfNeeded();
132
133 PCHECK(fwrite(events_str->data().c_str(), 1, events_str->data().length(),
134 trace_file_) == events_str->data().length());
135 }
136
137 if (!has_more_events && !done_callback.is_null())
138 done_callback.Run();
139 }
140
141 void Tracer::OnDataAvailable(const void* data, size_t num_bytes) {
142 const char* chars = static_cast<const char*>(data);
143 trace_service_data_.append(chars, num_bytes);
144 }
145
146 void Tracer::OnDataComplete() {
147 if (!trace_service_data_.empty()) {
148 WriteCommaIfNeeded();
149 const char* const chars = trace_service_data_.data();
150 size_t num_bytes = trace_service_data_.length();
151 PCHECK(fwrite(chars, 1, num_bytes, trace_file_) == num_bytes);
152 trace_service_data_ = std::string();
153 }
154 drainer_.reset();
155 coordinator_.reset();
156 WriteFooterAndClose();
157 }
158
159 void Tracer::WriteCommaIfNeeded() {
160 if (first_chunk_written_)
161 PCHECK(fwrite(",", 1, 1, trace_file_) == 1);
162 first_chunk_written_ = true;
163 }
164
165 } // namespace shell
OLDNEW
« no previous file with comments | « services/shell/standalone/tracer.h ('k') | services/shell/switches.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698