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

Side by Side Diff: chrome/browser/performance_monitor/database.cc

Issue 10907121: Add guards to metric values; erase bad events/metrics from db (Closed) Base URL: http://git.chromium.org/chromium/src.git@dc_use_units
Patch Set: Eriq's requests Created 8 years, 3 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
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 "chrome/browser/performance_monitor/database.h" 5 #include "chrome/browser/performance_monitor/database.h"
6 6
7 #include "base/file_path.h" 7 #include "base/file_path.h"
8 #include "base/file_util.h" 8 #include "base/file_util.h"
9 #include "base/json/json_reader.h" 9 #include "base/json/json_reader.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/path_service.h" 12 #include "base/path_service.h"
13 #include "base/stl_util.h" 13 #include "base/stl_util.h"
14 #include "base/string_number_conversions.h" 14 #include "base/string_number_conversions.h"
15 #include "base/time.h" 15 #include "base/time.h"
16 #include "base/utf_string_conversions.h" 16 #include "base/utf_string_conversions.h"
17 #include "chrome/browser/performance_monitor/key_builder.h" 17 #include "chrome/browser/performance_monitor/key_builder.h"
18 #include "chrome/common/chrome_paths.h" 18 #include "chrome/common/chrome_paths.h"
19 #include "content/public/browser/browser_thread.h" 19 #include "content/public/browser/browser_thread.h"
20 #include "third_party/leveldatabase/src/include/leveldb/db.h" 20 #include "third_party/leveldatabase/src/include/leveldb/db.h"
21 #include "third_party/leveldatabase/src/include/leveldb/iterator.h"
22 #include "third_party/leveldatabase/src/include/leveldb/write_batch.h"
21 23
22 namespace performance_monitor { 24 namespace performance_monitor {
23 namespace { 25 namespace {
24 const char kDbDir[] = "Performance Monitor Databases"; 26 const char kDbDir[] = "Performance Monitor Databases";
25 const char kRecentDb[] = "Recent Metrics"; 27 const char kRecentDb[] = "Recent Metrics";
26 const char kMaxValueDb[] = "Max Value Metrics"; 28 const char kMaxValueDb[] = "Max Value Metrics";
27 const char kEventDb[] = "Events"; 29 const char kEventDb[] = "Events";
28 const char kStateDb[] = "Configuration"; 30 const char kStateDb[] = "Configuration";
29 const char kActiveIntervalDb[] = "Active Interval"; 31 const char kActiveIntervalDb[] = "Active Interval";
30 const char kMetricDb[] = "Metrics"; 32 const char kMetricDb[] = "Metrics";
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
138 140
139 Database::EventVector Database::GetEvents(EventType type, 141 Database::EventVector Database::GetEvents(EventType type,
140 const base::Time& start, 142 const base::Time& start,
141 const base::Time& end) { 143 const base::Time& end) {
142 CHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 144 CHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
143 EventVector events; 145 EventVector events;
144 std::string start_key = 146 std::string start_key =
145 key_builder_->CreateEventKey(start, EVENT_UNDEFINED); 147 key_builder_->CreateEventKey(start, EVENT_UNDEFINED);
146 std::string end_key = 148 std::string end_key =
147 key_builder_->CreateEventKey(end, EVENT_NUMBER_OF_EVENTS); 149 key_builder_->CreateEventKey(end, EVENT_NUMBER_OF_EVENTS);
150 leveldb::WriteBatch invalid_entries;
148 scoped_ptr<leveldb::Iterator> it(event_db_->NewIterator(read_options_)); 151 scoped_ptr<leveldb::Iterator> it(event_db_->NewIterator(read_options_));
149 for (it->Seek(start_key); 152 for (it->Seek(start_key);
150 it->Valid() && it->key().ToString() <= end_key; 153 it->Valid() && it->key().ToString() <= end_key;
151 it->Next()) { 154 it->Next()) {
152 if (type != EVENT_UNDEFINED) { 155 if (type != EVENT_UNDEFINED) {
153 EventType key_type = 156 EventType key_type =
154 key_builder_->EventKeyToEventType(it->key().ToString()); 157 key_builder_->EventKeyToEventType(it->key().ToString());
155 if (key_type != type) 158 if (key_type != type)
156 continue; 159 continue;
157 } 160 }
161 Value* value = NULL;
158 base::DictionaryValue* dict = NULL; 162 base::DictionaryValue* dict = NULL;
159 if (!base::JSONReader::Read( 163 scoped_ptr<Event> event;
160 it->value().ToString())->GetAsDictionary(&dict)) { 164 if (!(value = base::JSONReader::Read(it->value().ToString())) ||
Yoyo Zhou 2012/09/10 23:52:44 Assignment inline inside conditionals isn't recomm
Devlin 2012/09/11 18:52:17 Done.
161 LOG(ERROR) << "Unable to convert database event to JSON."; 165 !value->GetAsDictionary(&dict) ||
166 !(event =
167 Event::FromValue(scoped_ptr<base::DictionaryValue>(dict))).get()) {
168 invalid_entries.Delete(it->key());
169 LOG(ERROR) << "Unable to convert database event to JSON. Erasing the "
Yoyo Zhou 2012/09/10 23:52:44 You should log something identifiable about the ev
Devlin 2012/09/11 18:52:17 Done.
170 "event from the database.";
162 continue; 171 continue;
163 } 172 }
164 scoped_ptr<Event> event =
165 Event::FromValue(scoped_ptr<base::DictionaryValue>(dict));
166 if (!event.get())
167 continue;
168 events.push_back(linked_ptr<Event>(event.release())); 173 events.push_back(linked_ptr<Event>(event.release()));
169 } 174 }
175 event_db_->Write(write_options_, &invalid_entries);
170 return events; 176 return events;
171 } 177 }
172 178
173 Database::EventTypeSet Database::GetEventTypes(const base::Time& start, 179 Database::EventTypeSet Database::GetEventTypes(const base::Time& start,
174 const base::Time& end) { 180 const base::Time& end) {
175 CHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 181 CHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
176 EventTypeSet results; 182 EventTypeSet results;
177 std::string start_key = 183 std::string start_key =
178 key_builder_->CreateEventKey(start, EVENT_UNDEFINED); 184 key_builder_->CreateEventKey(start, EVENT_UNDEFINED);
179 std::string end_key = 185 std::string end_key =
180 key_builder_->CreateEventKey(end, EVENT_NUMBER_OF_EVENTS); 186 key_builder_->CreateEventKey(end, EVENT_NUMBER_OF_EVENTS);
181 scoped_ptr<leveldb::Iterator> it(event_db_->NewIterator(read_options_)); 187 scoped_ptr<leveldb::Iterator> it(event_db_->NewIterator(read_options_));
182 for (it->Seek(start_key); 188 for (it->Seek(start_key);
183 it->Valid() && it->key().ToString() <= end_key; 189 it->Valid() && it->key().ToString() <= end_key;
184 it->Next()) { 190 it->Next()) {
185 EventType key_type = 191 EventType key_type =
186 key_builder_->EventKeyToEventType(it->key().ToString()); 192 key_builder_->EventKeyToEventType(it->key().ToString());
187 results.insert(key_type); 193 results.insert(key_type);
188 } 194 }
189 return results; 195 return results;
190 } 196 }
191 197
192 bool Database::AddMetric(const std::string& activity, 198 bool Database::AddMetric(const std::string& activity,
193 MetricType metric, 199 const Metric& metric) {
194 const std::string& value) {
195 CHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 200 CHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
201 if (!metric.Validate()) {
202 LOG(ERROR) << "Metric is not valid; ignoring.";
Yoyo Zhou 2012/09/10 23:52:44 Same here. What is the invalid metric?
Devlin 2012/09/11 18:52:17 Done.
203 return false;
204 }
205
196 UpdateActiveInterval(); 206 UpdateActiveInterval();
197 base::Time timestamp = clock_->GetTime();
198 std::string recent_key = 207 std::string recent_key =
199 key_builder_->CreateRecentKey(timestamp, metric, activity); 208 key_builder_->CreateRecentKey(metric.time, metric.type, activity);
200 std::string metric_key = 209 std::string metric_key =
201 key_builder_->CreateMetricKey(timestamp, metric, activity); 210 key_builder_->CreateMetricKey(metric.time, metric.type, activity);
202 std::string recent_map_key = 211 std::string recent_map_key =
203 key_builder_->CreateRecentMapKey(metric, activity); 212 key_builder_->CreateRecentMapKey(metric.type, activity);
204 // Use recent_map_ to quickly find the key that must be removed. 213 // Use recent_map_ to quickly find the key that must be removed.
205 RecentMap::iterator old_it = recent_map_.find(recent_map_key); 214 RecentMap::iterator old_it = recent_map_.find(recent_map_key);
206 if (old_it != recent_map_.end()) 215 if (old_it != recent_map_.end())
207 recent_db_->Delete(write_options_, old_it->second); 216 recent_db_->Delete(write_options_, old_it->second);
208 recent_map_[recent_map_key] = recent_key; 217 recent_map_[recent_map_key] = recent_key;
209 leveldb::Status recent_status = 218 leveldb::Status recent_status =
210 recent_db_->Put(write_options_, recent_key, value); 219 recent_db_->Put(write_options_, recent_key, metric.ValueAsString());
211 leveldb::Status metric_status = 220 leveldb::Status metric_status =
212 metric_db_->Put(write_options_, metric_key, value); 221 metric_db_->Put(write_options_, metric_key, metric.ValueAsString());
213 222
214 bool max_value_success = UpdateMaxValue(activity, metric, value); 223 bool max_value_success =
224 UpdateMaxValue(activity, metric.type, metric.ValueAsString());
215 return recent_status.ok() && metric_status.ok() && max_value_success; 225 return recent_status.ok() && metric_status.ok() && max_value_success;
216 } 226 }
217 227
218 bool Database::UpdateMaxValue(const std::string& activity, 228 bool Database::UpdateMaxValue(const std::string& activity,
219 MetricType metric, 229 MetricType metric,
220 const std::string& value) { 230 const std::string& value) {
221 std::string max_value_key( 231 std::string max_value_key(
222 key_builder_->CreateMaxValueKey(metric, activity)); 232 key_builder_->CreateMaxValueKey(metric, activity));
223 bool has_key = ContainsKey(max_value_map_, max_value_key); 233 bool has_key = ContainsKey(max_value_map_, max_value_key);
224 if ((has_key && StringToDouble(value) > max_value_map_[max_value_key]) || 234 if ((has_key && StringToDouble(value) > max_value_map_[max_value_key]) ||
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
314 CHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 324 CHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
315 std::string recent_map_key = 325 std::string recent_map_key =
316 key_builder_->CreateRecentMapKey(metric_type, activity); 326 key_builder_->CreateRecentMapKey(metric_type, activity);
317 if (!ContainsKey(recent_map_, recent_map_key)) 327 if (!ContainsKey(recent_map_, recent_map_key))
318 return false; 328 return false;
319 std::string recent_key = recent_map_[recent_map_key]; 329 std::string recent_key = recent_map_[recent_map_key];
320 330
321 std::string result; 331 std::string result;
322 leveldb::Status status = recent_db_->Get(read_options_, recent_key, &result); 332 leveldb::Status status = recent_db_->Get(read_options_, recent_key, &result);
323 if (status.ok()) 333 if (status.ok())
324 *metric = Metric(key_builder_->SplitRecentKey(recent_key).time, result); 334 *metric = Metric(metric_type,
335 key_builder_->SplitRecentKey(recent_key).time,
336 result);
325 return status.ok(); 337 return status.ok();
326 } 338 }
327 339
328 Database::MetricVector Database::GetStatsForActivityAndMetric( 340 Database::MetricVector Database::GetStatsForActivityAndMetric(
329 const std::string& activity, 341 const std::string& activity,
330 MetricType metric_type, 342 MetricType metric_type,
331 const base::Time& start, 343 const base::Time& start,
332 const base::Time& end) { 344 const base::Time& end) {
333 CHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 345 CHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
334 MetricVector results; 346 MetricVector results;
335 std::string start_key = 347 std::string start_key =
336 key_builder_->CreateMetricKey(start, metric_type, activity); 348 key_builder_->CreateMetricKey(start, metric_type, activity);
337 std::string end_key = 349 std::string end_key =
338 key_builder_->CreateMetricKey(end, metric_type, activity); 350 key_builder_->CreateMetricKey(end, metric_type, activity);
351 leveldb::WriteBatch invalid_entries;
339 scoped_ptr<leveldb::Iterator> it(metric_db_->NewIterator(read_options_)); 352 scoped_ptr<leveldb::Iterator> it(metric_db_->NewIterator(read_options_));
340 for (it->Seek(start_key); 353 for (it->Seek(start_key);
341 it->Valid() && it->key().ToString() <= end_key; 354 it->Valid() && it->key().ToString() <= end_key;
342 it->Next()) { 355 it->Next()) {
343 MetricKey split_key = 356 MetricKey split_key =
344 key_builder_->SplitMetricKey(it->key().ToString()); 357 key_builder_->SplitMetricKey(it->key().ToString());
345 if (split_key.activity == activity) 358 if (split_key.activity == activity) {
346 results.push_back(Metric(split_key.time, it->value().ToString())); 359 Metric metric(metric_type, split_key.time, it->value().ToString());
360 if (!metric.Validate()) {
361 LOG(ERROR) << "Found bad metric in database. Erasing the metric from "
Yoyo Zhou 2012/09/10 23:52:44 Same comment, etc.
Devlin 2012/09/11 18:52:17 Done.
362 "the database.";
363 invalid_entries.Delete(it->key());
364 continue;
365 }
366 results.push_back(Metric(metric_type,
Yoyo Zhou 2012/09/10 23:52:44 This is already called 'metric'
Devlin 2012/09/11 18:52:17 Done.
367 split_key.time,
368 it->value().ToString()));
369 }
347 } 370 }
371 metric_db_->Write(write_options_, &invalid_entries);
348 return results; 372 return results;
349 } 373 }
350 374
351 Database::MetricVectorMap Database::GetStatsForMetricByActivity( 375 Database::MetricVectorMap Database::GetStatsForMetricByActivity(
352 MetricType metric_type, 376 MetricType metric_type,
353 const base::Time& start, 377 const base::Time& start,
354 const base::Time& end) { 378 const base::Time& end) {
355 CHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 379 CHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
356 MetricVectorMap results; 380 MetricVectorMap results;
357 std::string start_key = 381 std::string start_key =
358 key_builder_->CreateMetricKey(start, metric_type, std::string()); 382 key_builder_->CreateMetricKey(start, metric_type, std::string());
359 std::string end_key = 383 std::string end_key =
360 key_builder_->CreateMetricKey(end, metric_type, std::string()); 384 key_builder_->CreateMetricKey(end, metric_type, std::string());
385 leveldb::WriteBatch invalid_entries;
361 scoped_ptr<leveldb::Iterator> it(metric_db_->NewIterator(read_options_)); 386 scoped_ptr<leveldb::Iterator> it(metric_db_->NewIterator(read_options_));
362 for (it->Seek(start_key); 387 for (it->Seek(start_key);
363 it->Valid() && it->key().ToString() <= end_key; 388 it->Valid() && it->key().ToString() <= end_key;
364 it->Next()) { 389 it->Next()) {
365 MetricKey split_key = key_builder_->SplitMetricKey(it->key().ToString()); 390 MetricKey split_key = key_builder_->SplitMetricKey(it->key().ToString());
366 if (!results[split_key.activity].get()) { 391 if (!results[split_key.activity].get()) {
367 results[split_key.activity] = 392 results[split_key.activity] =
368 linked_ptr<MetricVector >(new MetricVector()); 393 linked_ptr<MetricVector >(new MetricVector());
369 } 394 }
395 Metric metric(metric_type, split_key.time, it->value().ToString());
396 if (!metric.Validate()) {
397 LOG(ERROR) << "Found bad metric in database. Erasing the metric from "
398 "the database.";
399 invalid_entries.Delete(it->key());
400 continue;
401 }
370 results[split_key.activity]->push_back( 402 results[split_key.activity]->push_back(
371 Metric(split_key.time, it->value().ToString())); 403 Metric(metric_type, split_key.time, it->value().ToString()));
Yoyo Zhou 2012/09/10 23:52:44 ditto
Devlin 2012/09/11 18:52:17 Done.
372 } 404 }
405 metric_db_->Write(write_options_, &invalid_entries);
373 return results; 406 return results;
374 } 407 }
375 408
376 Database::Database(const FilePath& path) 409 Database::Database(const FilePath& path)
377 : key_builder_(new KeyBuilder()), 410 : key_builder_(new KeyBuilder()),
378 path_(path), 411 path_(path),
379 read_options_(leveldb::ReadOptions()), 412 read_options_(leveldb::ReadOptions()),
380 write_options_(leveldb::WriteOptions()) { 413 write_options_(leveldb::WriteOptions()) {
381 InitDBs(); 414 InitDBs();
382 LoadRecents(); 415 LoadRecents();
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
482 start_time_key_ = key_builder_->CreateActiveIntervalKey(current_time); 515 start_time_key_ = key_builder_->CreateActiveIntervalKey(current_time);
483 end_time = start_time_key_; 516 end_time = start_time_key_;
484 } else { 517 } else {
485 end_time = key_builder_->CreateActiveIntervalKey(clock_->GetTime()); 518 end_time = key_builder_->CreateActiveIntervalKey(clock_->GetTime());
486 } 519 }
487 last_update_time_ = current_time; 520 last_update_time_ = current_time;
488 active_interval_db_->Put(write_options_, start_time_key_, end_time); 521 active_interval_db_->Put(write_options_, start_time_key_, end_time);
489 } 522 }
490 523
491 } // namespace performance_monitor 524 } // namespace performance_monitor
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698