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

Side by Side Diff: components/domain_reliability/context.cc

Issue 1180223006: Domain Reliability: Simplify configs and reports (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix memory leak in unittests Created 5 years 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
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 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 "components/domain_reliability/context.h" 5 #include "components/domain_reliability/context.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/json/json_writer.h" 10 #include "base/json/json_writer.h"
11 #include "base/logging.h" 11 #include "base/logging.h"
12 #include "base/metrics/histogram.h" 12 #include "base/metrics/histogram.h"
13 #include "base/metrics/sparse_histogram.h" 13 #include "base/metrics/sparse_histogram.h"
14 #include "base/values.h" 14 #include "base/values.h"
15 #include "components/domain_reliability/dispatcher.h" 15 #include "components/domain_reliability/dispatcher.h"
16 #include "components/domain_reliability/uploader.h" 16 #include "components/domain_reliability/uploader.h"
17 #include "components/domain_reliability/util.h" 17 #include "components/domain_reliability/util.h"
18 #include "net/base/net_errors.h" 18 #include "net/base/net_errors.h"
19 #include "net/url_request/url_request_context_getter.h" 19 #include "net/url_request/url_request_context_getter.h"
20 20
21 using base::DictionaryValue; 21 using base::DictionaryValue;
22 using base::ListValue; 22 using base::ListValue;
23 using base::Value; 23 using base::Value;
24 24
25 namespace domain_reliability { 25 namespace domain_reliability {
26 26
27 namespace { 27 namespace {
28 typedef std::deque<DomainReliabilityBeacon> BeaconDeque; 28 void LogOnBeaconDidEvictHistogram(bool evicted) {
29 typedef BeaconDeque::iterator BeaconIterator; 29 UMA_HISTOGRAM_BOOLEAN("DomainReliability.OnBeaconDidEvict", evicted);
30 typedef BeaconDeque::const_iterator BeaconConstIterator; 30 }
31 } // namespace 31 } // namespace
32 32
33 DomainReliabilityContext::Factory::~Factory() { 33 DomainReliabilityContext::Factory::~Factory() {
34 } 34 }
35 35
36 class DomainReliabilityContext::ResourceState {
37 public:
38 ResourceState(DomainReliabilityContext* context,
39 const DomainReliabilityConfig::Resource* config)
40 : context(context),
41 config(config),
42 successful_requests(0),
43 failed_requests(0),
44 uploading_successful_requests(0),
45 uploading_failed_requests(0) {}
46 ~ResourceState() {}
47
48 // Serializes the resource state into a Value to be included in an upload.
49 // If there is nothing to report (no beacons and all request counters are 0),
50 // returns a scoped_ptr to NULL instead so the resource can be omitted.
51 scoped_ptr<base::Value> ToValue(base::TimeTicks upload_time) const {
52 if (successful_requests == 0 && failed_requests == 0)
53 return scoped_ptr<base::Value>();
54
55 DictionaryValue* resource_value = new DictionaryValue();
56 resource_value->SetString("name", config->name);
57 resource_value->SetInteger("successful_requests", successful_requests);
58 resource_value->SetInteger("failed_requests", failed_requests);
59
60 return scoped_ptr<Value>(resource_value);
61 }
62
63 // Remembers the current state of the resource data when an upload starts.
64 void MarkUpload() {
65 DCHECK_EQ(0u, uploading_successful_requests);
66 DCHECK_EQ(0u, uploading_failed_requests);
67 uploading_successful_requests = successful_requests;
68 uploading_failed_requests = failed_requests;
69 }
70
71 // Uses the state remembered by |MarkUpload| to remove successfully uploaded
72 // data but keep beacons and request counts added after the upload started.
73 void CommitUpload() {
74 successful_requests -= uploading_successful_requests;
75 failed_requests -= uploading_failed_requests;
76 uploading_successful_requests = 0;
77 uploading_failed_requests = 0;
78 }
79
80 void RollbackUpload() {
81 uploading_successful_requests = 0;
82 uploading_failed_requests = 0;
83 }
84
85 DomainReliabilityContext* context;
86 const DomainReliabilityConfig::Resource* config;
87
88 uint32 successful_requests;
89 uint32 failed_requests;
90
91 // State saved during uploads; if an upload succeeds, these are used to
92 // remove uploaded data from the beacon list and request counters.
93 uint32 uploading_successful_requests;
94 uint32 uploading_failed_requests;
95
96 private:
97 DISALLOW_COPY_AND_ASSIGN(ResourceState);
98 };
99
100 // static 36 // static
101 const size_t DomainReliabilityContext::kMaxQueuedBeacons = 150; 37 const size_t DomainReliabilityContext::kMaxQueuedBeacons = 150;
102 38
103 DomainReliabilityContext::DomainReliabilityContext( 39 DomainReliabilityContext::DomainReliabilityContext(
104 MockableTime* time, 40 MockableTime* time,
105 const DomainReliabilityScheduler::Params& scheduler_params, 41 const DomainReliabilityScheduler::Params& scheduler_params,
106 const std::string& upload_reporter_string, 42 const std::string& upload_reporter_string,
107 const base::TimeTicks* last_network_change_time, 43 const base::TimeTicks* last_network_change_time,
108 DomainReliabilityDispatcher* dispatcher, 44 DomainReliabilityDispatcher* dispatcher,
109 DomainReliabilityUploader* uploader, 45 DomainReliabilityUploader* uploader,
110 scoped_ptr<const DomainReliabilityConfig> config) 46 scoped_ptr<const DomainReliabilityConfig> config)
111 : config_(config.Pass()), 47 : config_(config.Pass()),
112 time_(time), 48 time_(time),
113 upload_reporter_string_(upload_reporter_string), 49 upload_reporter_string_(upload_reporter_string),
114 scheduler_(time, 50 scheduler_(time,
115 config_->collectors.size(), 51 config_->collectors.size(),
116 scheduler_params, 52 scheduler_params,
117 base::Bind(&DomainReliabilityContext::ScheduleUpload, 53 base::Bind(&DomainReliabilityContext::ScheduleUpload,
118 base::Unretained(this))), 54 base::Unretained(this))),
119 dispatcher_(dispatcher), 55 dispatcher_(dispatcher),
120 uploader_(uploader), 56 uploader_(uploader),
121 uploading_beacons_size_(0), 57 uploading_beacons_size_(0),
122 last_network_change_time_(last_network_change_time), 58 last_network_change_time_(last_network_change_time),
123 weak_factory_(this) { 59 weak_factory_(this) {
124 InitializeResourceStates();
125 } 60 }
126 61
127 DomainReliabilityContext::~DomainReliabilityContext() {} 62 DomainReliabilityContext::~DomainReliabilityContext() {
63 ClearBeacons();
64 }
128 65
129 void DomainReliabilityContext::OnBeacon(const GURL& url, 66 void DomainReliabilityContext::OnBeacon(
130 const DomainReliabilityBeacon& beacon) { 67 scoped_ptr<DomainReliabilityBeacon> beacon) {
131 size_t index = config_->GetResourceIndexForUrl(url); 68 bool success = (beacon->status == "ok");
132 if (index == DomainReliabilityConfig::kInvalidResourceIndex) 69
70 bool reported = config().DecideIfShouldReportRequest(success);
71 UMA_HISTOGRAM_BOOLEAN("DomainReliability.BeaconReported", reported);
72 if (!reported) {
73 // If the beacon isn't queued to be reported, it definitely cannot evict
74 // an older beacon. (This histogram is also logged below based on whether
75 // an older beacon was actually evicted.)
76 LogOnBeaconDidEvictHistogram(false);
133 return; 77 return;
134 DCHECK_GT(states_.size(), index);
135
136 bool success = (beacon.status == "ok");
137
138 ResourceState* state = states_[index];
139 if (success)
140 ++state->successful_requests;
141 else
142 ++state->failed_requests;
143
144 bool reported = false;
145 bool evicted = false;
146 if (state->config->DecideIfShouldReportRequest(success)) {
147 beacons_.push_back(beacon);
148 beacons_.back().resource = state->config->name;
149 if (beacons_.size() > kMaxQueuedBeacons) {
150 RemoveOldestBeacon();
151 evicted = true;
152 }
153 scheduler_.OnBeaconAdded();
154 reported = true;
155 UMA_HISTOGRAM_SPARSE_SLOWLY("DomainReliability.ReportedBeaconError",
156 -beacon.chrome_error);
157 if (!beacon.server_ip.empty()) {
158 UMA_HISTOGRAM_SPARSE_SLOWLY(
159 "DomainReliability.ReportedBeaconError_HasServerIP",
160 -beacon.chrome_error);
161 }
162 // TODO(ttuttle): Histogram HTTP response code?
163 } 78 }
164 79
165 UMA_HISTOGRAM_BOOLEAN("DomainReliability.BeaconReported", reported); 80 bool evicted = false;
166 UMA_HISTOGRAM_BOOLEAN("DomainReliability.OnBeaconDidEvict", evicted); 81
82 UMA_HISTOGRAM_SPARSE_SLOWLY("DomainReliability.ReportedBeaconError",
83 -beacon->chrome_error);
84 if (!beacon->server_ip.empty()) {
85 UMA_HISTOGRAM_SPARSE_SLOWLY(
86 "DomainReliability.ReportedBeaconError_HasServerIP",
87 -beacon->chrome_error);
88 }
89 // TODO(ttuttle): Histogram HTTP response code?
90
91 beacons_.push_back(beacon.release());
92 if (beacons_.size() > kMaxQueuedBeacons) {
93 RemoveOldestBeacon();
94 evicted = true;
95 }
96
97 scheduler_.OnBeaconAdded();
98
99 LogOnBeaconDidEvictHistogram(evicted);
167 } 100 }
168 101
169 void DomainReliabilityContext::ClearBeacons() { 102 void DomainReliabilityContext::ClearBeacons() {
170 for (auto& state : states_) { 103 STLDeleteElements(&beacons_);
171 state->successful_requests = 0;
172 state->failed_requests = 0;
173 state->uploading_successful_requests = 0;
174 state->uploading_failed_requests = 0;
175 }
176 beacons_.clear(); 104 beacons_.clear();
177 uploading_beacons_size_ = 0; 105 uploading_beacons_size_ = 0;
178 } 106 }
179 107
180 scoped_ptr<base::Value> DomainReliabilityContext::GetWebUIData() const { 108 scoped_ptr<Value> DomainReliabilityContext::GetWebUIData() const {
181 base::DictionaryValue* context_value = new base::DictionaryValue(); 109 DictionaryValue* context_value = new DictionaryValue();
182 110
183 context_value->SetString("domain", config().domain); 111 context_value->SetString("origin", config().origin.spec());
184 context_value->SetInteger("beacon_count", static_cast<int>(beacons_.size())); 112 context_value->SetInteger("beacon_count", static_cast<int>(beacons_.size()));
185 context_value->SetInteger("uploading_beacon_count", 113 context_value->SetInteger("uploading_beacon_count",
186 static_cast<int>(uploading_beacons_size_)); 114 static_cast<int>(uploading_beacons_size_));
187 context_value->Set("scheduler", scheduler_.GetWebUIData()); 115 context_value->Set("scheduler", scheduler_.GetWebUIData());
188 116
189 return scoped_ptr<base::Value>(context_value); 117 return scoped_ptr<Value>(context_value);
190 } 118 }
191 119
192 void DomainReliabilityContext::GetQueuedBeaconsForTesting( 120 void DomainReliabilityContext::GetQueuedBeaconsForTesting(
193 std::vector<DomainReliabilityBeacon>* beacons_out) const { 121 std::vector<const DomainReliabilityBeacon*>* beacons_out) const {
122 DCHECK(this);
123 DCHECK(beacons_out);
194 beacons_out->assign(beacons_.begin(), beacons_.end()); 124 beacons_out->assign(beacons_.begin(), beacons_.end());
195 } 125 }
196 126
197 void DomainReliabilityContext::GetRequestCountsForTesting(
198 size_t resource_index,
199 uint32_t* successful_requests_out,
200 uint32_t* failed_requests_out) const {
201 DCHECK_NE(DomainReliabilityConfig::kInvalidResourceIndex, resource_index);
202 DCHECK_GT(states_.size(), resource_index);
203
204 const ResourceState& state = *states_[resource_index];
205 *successful_requests_out = state.successful_requests;
206 *failed_requests_out = state.failed_requests;
207 }
208
209 void DomainReliabilityContext::InitializeResourceStates() {
210 for (auto& resource : config_->resources)
211 states_.push_back(new ResourceState(this, resource));
212 }
213
214 void DomainReliabilityContext::ScheduleUpload( 127 void DomainReliabilityContext::ScheduleUpload(
215 base::TimeDelta min_delay, 128 base::TimeDelta min_delay,
216 base::TimeDelta max_delay) { 129 base::TimeDelta max_delay) {
217 dispatcher_->ScheduleTask( 130 dispatcher_->ScheduleTask(
218 base::Bind( 131 base::Bind(
219 &DomainReliabilityContext::StartUpload, 132 &DomainReliabilityContext::StartUpload,
220 weak_factory_.GetWeakPtr()), 133 weak_factory_.GetWeakPtr()),
221 min_delay, 134 min_delay,
222 max_delay); 135 max_delay);
223 } 136 }
224 137
225 void DomainReliabilityContext::StartUpload() { 138 void DomainReliabilityContext::StartUpload() {
226 MarkUpload(); 139 MarkUpload();
227 140
228 DCHECK(upload_time_.is_null()); 141 DCHECK(upload_time_.is_null());
229 upload_time_ = time_->NowTicks(); 142 upload_time_ = time_->NowTicks();
143 size_t collector_index = scheduler_.OnUploadStart();
144 const GURL& collector_url = *config().collectors[collector_index];
145
230 std::string report_json; 146 std::string report_json;
231 base::JSONWriter::Write(*CreateReport(upload_time_), &report_json); 147 scoped_ptr<const Value> report = CreateReport(upload_time_, collector_url);
232 148 base::JSONWriter::Write(*report, &report_json);
233 size_t collector_index = scheduler_.OnUploadStart(); 149 report.reset();
234 150
235 uploader_->UploadReport( 151 uploader_->UploadReport(
236 report_json, 152 report_json, collector_url,
237 config_->collectors[collector_index]->upload_url, 153 base::Bind(&DomainReliabilityContext::OnUploadComplete,
238 base::Bind( 154 weak_factory_.GetWeakPtr()));
239 &DomainReliabilityContext::OnUploadComplete,
240 weak_factory_.GetWeakPtr()));
241 155
242 UMA_HISTOGRAM_SPARSE_SLOWLY("DomainReliability.UploadCollectorIndex", 156 UMA_HISTOGRAM_SPARSE_SLOWLY("DomainReliability.UploadCollectorIndex",
243 static_cast<int>(collector_index)); 157 static_cast<int>(collector_index));
244 if (!last_upload_time_.is_null()) { 158 if (!last_upload_time_.is_null()) {
245 UMA_HISTOGRAM_LONG_TIMES("DomainReliability.UploadInterval", 159 UMA_HISTOGRAM_LONG_TIMES("DomainReliability.UploadInterval",
246 upload_time_ - last_upload_time_); 160 upload_time_ - last_upload_time_);
247 } 161 }
248 } 162 }
249 163
250 void DomainReliabilityContext::OnUploadComplete( 164 void DomainReliabilityContext::OnUploadComplete(
(...skipping 12 matching lines...) Expand all
263 DCHECK(!upload_time_.is_null()); 177 DCHECK(!upload_time_.is_null());
264 UMA_HISTOGRAM_MEDIUM_TIMES("DomainReliability.UploadDuration", 178 UMA_HISTOGRAM_MEDIUM_TIMES("DomainReliability.UploadDuration",
265 now - upload_time_); 179 now - upload_time_);
266 UMA_HISTOGRAM_LONG_TIMES("DomainReliability.UploadCollectorRetryDelay", 180 UMA_HISTOGRAM_LONG_TIMES("DomainReliability.UploadCollectorRetryDelay",
267 scheduler_.last_collector_retry_delay()); 181 scheduler_.last_collector_retry_delay());
268 last_upload_time_ = upload_time_; 182 last_upload_time_ = upload_time_;
269 upload_time_ = base::TimeTicks(); 183 upload_time_ = base::TimeTicks();
270 } 184 }
271 185
272 scoped_ptr<const Value> DomainReliabilityContext::CreateReport( 186 scoped_ptr<const Value> DomainReliabilityContext::CreateReport(
273 base::TimeTicks upload_time) const { 187 base::TimeTicks upload_time,
188 const GURL& collector_url) const {
274 scoped_ptr<ListValue> beacons_value(new ListValue()); 189 scoped_ptr<ListValue> beacons_value(new ListValue());
275 for (const auto& beacon : beacons_) { 190 for (const auto& beacon : beacons_) {
276 beacons_value->Append( 191 beacons_value->Append(beacon->ToValue(upload_time,
277 beacon.ToValue(upload_time, *last_network_change_time_)); 192 *last_network_change_time_,
278 } 193 collector_url,
279 194 config().path_prefixes));
280 scoped_ptr<ListValue> resources_value(new ListValue());
281 for (const auto& state : states_) {
282 scoped_ptr<Value> resource_report = state->ToValue(upload_time);
283 if (resource_report)
284 resources_value->Append(resource_report.release());
285 } 195 }
286 196
287 scoped_ptr<DictionaryValue> report_value(new DictionaryValue()); 197 scoped_ptr<DictionaryValue> report_value(new DictionaryValue());
288 if (!config().version.empty())
289 report_value->SetString("config_version", config().version);
290 report_value->SetString("reporter", upload_reporter_string_); 198 report_value->SetString("reporter", upload_reporter_string_);
291 report_value->Set("entries", beacons_value.release()); 199 report_value->Set("entries", beacons_value.release());
292 if (!resources_value->empty())
293 report_value->Set("resources", resources_value.release());
294 200
295 return report_value.Pass(); 201 return report_value.Pass();
296 } 202 }
297 203
298 void DomainReliabilityContext::MarkUpload() { 204 void DomainReliabilityContext::MarkUpload() {
299 for (auto& state : states_)
300 state->MarkUpload();
301 DCHECK_EQ(0u, uploading_beacons_size_); 205 DCHECK_EQ(0u, uploading_beacons_size_);
302 uploading_beacons_size_ = beacons_.size(); 206 uploading_beacons_size_ = beacons_.size();
303 DCHECK_NE(0u, uploading_beacons_size_); 207 DCHECK_NE(0u, uploading_beacons_size_);
304 } 208 }
305 209
306 void DomainReliabilityContext::CommitUpload() { 210 void DomainReliabilityContext::CommitUpload() {
307 for (auto& state : states_) 211 auto begin = beacons_.begin();
308 state->CommitUpload(); 212 auto end = begin + uploading_beacons_size_;
309 BeaconIterator begin = beacons_.begin(); 213 STLDeleteContainerPointers(begin, end);
310 BeaconIterator end = begin + uploading_beacons_size_;
311 beacons_.erase(begin, end); 214 beacons_.erase(begin, end);
312 DCHECK_NE(0u, uploading_beacons_size_); 215 DCHECK_NE(0u, uploading_beacons_size_);
313 uploading_beacons_size_ = 0; 216 uploading_beacons_size_ = 0;
314 } 217 }
315 218
316 void DomainReliabilityContext::RollbackUpload() { 219 void DomainReliabilityContext::RollbackUpload() {
317 for (auto& state : states_)
318 state->RollbackUpload();
319 DCHECK_NE(0u, uploading_beacons_size_); 220 DCHECK_NE(0u, uploading_beacons_size_);
320 uploading_beacons_size_ = 0; 221 uploading_beacons_size_ = 0;
321 } 222 }
322 223
323 void DomainReliabilityContext::RemoveOldestBeacon() { 224 void DomainReliabilityContext::RemoveOldestBeacon() {
324 DCHECK(!beacons_.empty()); 225 DCHECK(!beacons_.empty());
325 226
326 VLOG(1) << "Beacon queue for " << config().domain << " full; " 227 VLOG(1) << "Beacon queue for " << config().origin << " full; "
327 << "removing oldest beacon"; 228 << "removing oldest beacon";
328 229
230 delete beacons_.front();
329 beacons_.pop_front(); 231 beacons_.pop_front();
330 232
331 // If that just removed a beacon counted in uploading_beacons_size_, decrement 233 // If that just removed a beacon counted in uploading_beacons_size_, decrement
332 // that. 234 // that.
333 if (uploading_beacons_size_ > 0) 235 if (uploading_beacons_size_ > 0)
334 --uploading_beacons_size_; 236 --uploading_beacons_size_;
335 } 237 }
336 238
337 } // namespace domain_reliability 239 } // namespace domain_reliability
OLDNEW
« no previous file with comments | « components/domain_reliability/context.h ('k') | components/domain_reliability/context_manager.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698