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

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: 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())) ||
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 "
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()) {
eaugusti 2012/09/07 23:10:55 Should this be a DCHECK? If this method is getting
Devlin 2012/09/10 17:49:14 Not necessarily. If this is a bad Metric, then it
202 LOG(ERROR) << "Metric is not valid; ignoring.";
203 return false;
204 }
205
196 UpdateActiveInterval(); 206 UpdateActiveInterval();
197 base::Time timestamp = clock_->GetTime(); 207 base::Time timestamp = clock_->GetTime();
eaugusti 2012/09/07 23:10:55 I don't like how Metric has time, but clock_ is st
Devlin 2012/09/10 17:49:14 Done.
198 std::string recent_key = 208 std::string recent_key =
199 key_builder_->CreateRecentKey(timestamp, metric, activity); 209 key_builder_->CreateRecentKey(timestamp, metric.type, activity);
200 std::string metric_key = 210 std::string metric_key =
201 key_builder_->CreateMetricKey(timestamp, metric, activity); 211 key_builder_->CreateMetricKey(timestamp, metric.type, activity);
202 std::string recent_map_key = 212 std::string recent_map_key =
203 key_builder_->CreateRecentMapKey(metric, activity); 213 key_builder_->CreateRecentMapKey(metric.type, activity);
204 // Use recent_map_ to quickly find the key that must be removed. 214 // Use recent_map_ to quickly find the key that must be removed.
205 RecentMap::iterator old_it = recent_map_.find(recent_map_key); 215 RecentMap::iterator old_it = recent_map_.find(recent_map_key);
206 if (old_it != recent_map_.end()) 216 if (old_it != recent_map_.end())
207 recent_db_->Delete(write_options_, old_it->second); 217 recent_db_->Delete(write_options_, old_it->second);
208 recent_map_[recent_map_key] = recent_key; 218 recent_map_[recent_map_key] = recent_key;
209 leveldb::Status recent_status = 219 leveldb::Status recent_status =
210 recent_db_->Put(write_options_, recent_key, value); 220 recent_db_->Put(write_options_, recent_key, metric.ValueAsString());
211 leveldb::Status metric_status = 221 leveldb::Status metric_status =
212 metric_db_->Put(write_options_, metric_key, value); 222 metric_db_->Put(write_options_, metric_key, metric.ValueAsString());
213 223
214 bool max_value_success = UpdateMaxValue(activity, metric, value); 224 bool max_value_success =
225 UpdateMaxValue(activity, metric.type, metric.ValueAsString());
215 return recent_status.ok() && metric_status.ok() && max_value_success; 226 return recent_status.ok() && metric_status.ok() && max_value_success;
216 } 227 }
217 228
218 bool Database::UpdateMaxValue(const std::string& activity, 229 bool Database::UpdateMaxValue(const std::string& activity,
219 MetricType metric, 230 MetricType metric,
220 const std::string& value) { 231 const std::string& value) {
221 std::string max_value_key( 232 std::string max_value_key(
222 key_builder_->CreateMaxValueKey(metric, activity)); 233 key_builder_->CreateMaxValueKey(metric, activity));
223 bool has_key = ContainsKey(max_value_map_, max_value_key); 234 bool has_key = ContainsKey(max_value_map_, max_value_key);
224 if ((has_key && StringToDouble(value) > max_value_map_[max_value_key]) || 235 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)); 325 CHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
315 std::string recent_map_key = 326 std::string recent_map_key =
316 key_builder_->CreateRecentMapKey(metric_type, activity); 327 key_builder_->CreateRecentMapKey(metric_type, activity);
317 if (!ContainsKey(recent_map_, recent_map_key)) 328 if (!ContainsKey(recent_map_, recent_map_key))
318 return false; 329 return false;
319 std::string recent_key = recent_map_[recent_map_key]; 330 std::string recent_key = recent_map_[recent_map_key];
320 331
321 std::string result; 332 std::string result;
322 leveldb::Status status = recent_db_->Get(read_options_, recent_key, &result); 333 leveldb::Status status = recent_db_->Get(read_options_, recent_key, &result);
323 if (status.ok()) 334 if (status.ok())
324 *metric = Metric(key_builder_->SplitRecentKey(recent_key).time, result); 335 *metric = Metric(metric_type,
336 key_builder_->SplitRecentKey(recent_key).time,
337 result);
325 return status.ok(); 338 return status.ok();
326 } 339 }
327 340
328 Database::MetricVector Database::GetStatsForActivityAndMetric( 341 Database::MetricVector Database::GetStatsForActivityAndMetric(
329 const std::string& activity, 342 const std::string& activity,
330 MetricType metric_type, 343 MetricType metric_type,
331 const base::Time& start, 344 const base::Time& start,
332 const base::Time& end) { 345 const base::Time& end) {
333 CHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 346 CHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
334 MetricVector results; 347 MetricVector results;
335 std::string start_key = 348 std::string start_key =
336 key_builder_->CreateMetricKey(start, metric_type, activity); 349 key_builder_->CreateMetricKey(start, metric_type, activity);
337 std::string end_key = 350 std::string end_key =
338 key_builder_->CreateMetricKey(end, metric_type, activity); 351 key_builder_->CreateMetricKey(end, metric_type, activity);
352 leveldb::WriteBatch invalid_entries;
339 scoped_ptr<leveldb::Iterator> it(metric_db_->NewIterator(read_options_)); 353 scoped_ptr<leveldb::Iterator> it(metric_db_->NewIterator(read_options_));
340 for (it->Seek(start_key); 354 for (it->Seek(start_key);
341 it->Valid() && it->key().ToString() <= end_key; 355 it->Valid() && it->key().ToString() <= end_key;
342 it->Next()) { 356 it->Next()) {
343 MetricKey split_key = 357 MetricKey split_key =
344 key_builder_->SplitMetricKey(it->key().ToString()); 358 key_builder_->SplitMetricKey(it->key().ToString());
345 if (split_key.activity == activity) 359 if (split_key.activity == activity) {
346 results.push_back(Metric(split_key.time, it->value().ToString())); 360 Metric metric(metric_type, split_key.time, it->value().ToString());
361 if (!metric.Validate()) {
362 LOG(ERROR) << "Found bad metric in database. Erasing the metric from "
eaugusti 2012/09/07 23:10:55 We may want to consider moving this to a verbose l
Devlin 2012/09/10 17:49:14 I'm a little hesitant to do this, only because the
363 "the database.";
364 invalid_entries.Delete(it->key());
365 continue;
366 }
367 results.push_back(Metric(metric_type,
368 split_key.time,
369 it->value().ToString()));
370 }
347 } 371 }
372 metric_db_->Write(write_options_, &invalid_entries);
348 return results; 373 return results;
349 } 374 }
350 375
351 Database::MetricVectorMap Database::GetStatsForMetricByActivity( 376 Database::MetricVectorMap Database::GetStatsForMetricByActivity(
352 MetricType metric_type, 377 MetricType metric_type,
353 const base::Time& start, 378 const base::Time& start,
354 const base::Time& end) { 379 const base::Time& end) {
355 CHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 380 CHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
356 MetricVectorMap results; 381 MetricVectorMap results;
357 std::string start_key = 382 std::string start_key =
358 key_builder_->CreateMetricKey(start, metric_type, std::string()); 383 key_builder_->CreateMetricKey(start, metric_type, std::string());
359 std::string end_key = 384 std::string end_key =
360 key_builder_->CreateMetricKey(end, metric_type, std::string()); 385 key_builder_->CreateMetricKey(end, metric_type, std::string());
386 leveldb::WriteBatch invalid_entries;
361 scoped_ptr<leveldb::Iterator> it(metric_db_->NewIterator(read_options_)); 387 scoped_ptr<leveldb::Iterator> it(metric_db_->NewIterator(read_options_));
362 for (it->Seek(start_key); 388 for (it->Seek(start_key);
363 it->Valid() && it->key().ToString() <= end_key; 389 it->Valid() && it->key().ToString() <= end_key;
364 it->Next()) { 390 it->Next()) {
365 MetricKey split_key = key_builder_->SplitMetricKey(it->key().ToString()); 391 MetricKey split_key = key_builder_->SplitMetricKey(it->key().ToString());
366 if (!results[split_key.activity].get()) { 392 if (!results[split_key.activity].get()) {
367 results[split_key.activity] = 393 results[split_key.activity] =
368 linked_ptr<MetricVector >(new MetricVector()); 394 linked_ptr<MetricVector >(new MetricVector());
369 } 395 }
396 Metric metric(metric_type, split_key.time, it->value().ToString());
397 if (!metric.Validate()) {
398 LOG(ERROR) << "Found bad metric in database. Erasing the metric from "
399 "the database.";
400 invalid_entries.Delete(it->key());
401 continue;
402 }
370 results[split_key.activity]->push_back( 403 results[split_key.activity]->push_back(
371 Metric(split_key.time, it->value().ToString())); 404 Metric(metric_type, split_key.time, it->value().ToString()));
372 } 405 }
406 metric_db_->Write(write_options_, &invalid_entries);
373 return results; 407 return results;
374 } 408 }
375 409
376 Database::Database(const FilePath& path) 410 Database::Database(const FilePath& path)
377 : key_builder_(new KeyBuilder()), 411 : key_builder_(new KeyBuilder()),
378 path_(path), 412 path_(path),
379 read_options_(leveldb::ReadOptions()), 413 read_options_(leveldb::ReadOptions()),
380 write_options_(leveldb::WriteOptions()) { 414 write_options_(leveldb::WriteOptions()) {
381 InitDBs(); 415 InitDBs();
382 LoadRecents(); 416 LoadRecents();
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
482 start_time_key_ = key_builder_->CreateActiveIntervalKey(current_time); 516 start_time_key_ = key_builder_->CreateActiveIntervalKey(current_time);
483 end_time = start_time_key_; 517 end_time = start_time_key_;
484 } else { 518 } else {
485 end_time = key_builder_->CreateActiveIntervalKey(clock_->GetTime()); 519 end_time = key_builder_->CreateActiveIntervalKey(clock_->GetTime());
486 } 520 }
487 last_update_time_ = current_time; 521 last_update_time_ = current_time;
488 active_interval_db_->Put(write_options_, start_time_key_, end_time); 522 active_interval_db_->Put(write_options_, start_time_key_, end_time);
489 } 523 }
490 524
491 } // namespace performance_monitor 525 } // namespace performance_monitor
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698