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

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: Estade'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 12 matching lines...) Expand all
43 base::Time::FromInternalValue(end_time_int)); 45 base::Time::FromInternalValue(end_time_int));
44 } 46 }
45 47
46 double StringToDouble(const std::string& s) { 48 double StringToDouble(const std::string& s) {
47 double value = 0.0; 49 double value = 0.0;
48 if (!base::StringToDouble(s, &value)) 50 if (!base::StringToDouble(s, &value))
49 LOG(ERROR) << "Failed to convert " << s << " to double."; 51 LOG(ERROR) << "Failed to convert " << s << " to double.";
50 return value; 52 return value;
51 } 53 }
52 54
55 // Returns an event from the given JSON string; the scoped_ptr will be NULL if
56 // we are unable to properly parse the JSON.
57 scoped_ptr<Event> EventFromJSON(const std::string& data) {
58 Value* value = base::JSONReader::Read(data);
59 DictionaryValue* dict = NULL;
60 if (!value || !value->GetAsDictionary(&dict))
61 return scoped_ptr<Event>();
62
63 return Event::FromValue(scoped_ptr<DictionaryValue>(dict));
64 }
65
53 } // namespace 66 } // namespace
54 67
55 const char Database::kDatabaseSequenceToken[] = 68 const char Database::kDatabaseSequenceToken[] =
56 "_performance_monitor_db_sequence_token_"; 69 "_performance_monitor_db_sequence_token_";
57 70
58 TimeRange::TimeRange() { 71 TimeRange::TimeRange() {
59 } 72 }
60 73
61 TimeRange::TimeRange(base::Time start_time, base::Time end_time) 74 TimeRange::TimeRange(base::Time start_time, base::Time end_time)
62 : start(start_time), 75 : start(start_time),
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
138 151
139 Database::EventVector Database::GetEvents(EventType type, 152 Database::EventVector Database::GetEvents(EventType type,
140 const base::Time& start, 153 const base::Time& start,
141 const base::Time& end) { 154 const base::Time& end) {
142 CHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 155 CHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
143 EventVector events; 156 EventVector events;
144 std::string start_key = 157 std::string start_key =
145 key_builder_->CreateEventKey(start, EVENT_UNDEFINED); 158 key_builder_->CreateEventKey(start, EVENT_UNDEFINED);
146 std::string end_key = 159 std::string end_key =
147 key_builder_->CreateEventKey(end, EVENT_NUMBER_OF_EVENTS); 160 key_builder_->CreateEventKey(end, EVENT_NUMBER_OF_EVENTS);
161 leveldb::WriteBatch invalid_entries;
148 scoped_ptr<leveldb::Iterator> it(event_db_->NewIterator(read_options_)); 162 scoped_ptr<leveldb::Iterator> it(event_db_->NewIterator(read_options_));
149 for (it->Seek(start_key); 163 for (it->Seek(start_key);
150 it->Valid() && it->key().ToString() <= end_key; 164 it->Valid() && it->key().ToString() <= end_key;
151 it->Next()) { 165 it->Next()) {
152 if (type != EVENT_UNDEFINED) { 166 if (type != EVENT_UNDEFINED) {
153 EventType key_type = 167 EventType key_type =
154 key_builder_->EventKeyToEventType(it->key().ToString()); 168 key_builder_->EventKeyToEventType(it->key().ToString());
155 if (key_type != type) 169 if (key_type != type)
156 continue; 170 continue;
157 } 171 }
158 base::DictionaryValue* dict = NULL; 172 scoped_ptr<Event> event = EventFromJSON(it->value().ToString());
159 if (!base::JSONReader::Read( 173 if (!event.get()) {
160 it->value().ToString())->GetAsDictionary(&dict)) { 174 invalid_entries.Delete(it->key());
161 LOG(ERROR) << "Unable to convert database event to JSON."; 175 LOG(ERROR) << "Found invalid event in the database. JSON: '"
176 << it->value().ToString()
177 << "'. Erasing event from the database.";
162 continue; 178 continue;
163 } 179 }
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())); 180 events.push_back(linked_ptr<Event>(event.release()));
169 } 181 }
182 event_db_->Write(write_options_, &invalid_entries);
170 return events; 183 return events;
171 } 184 }
172 185
173 Database::EventTypeSet Database::GetEventTypes(const base::Time& start, 186 Database::EventTypeSet Database::GetEventTypes(const base::Time& start,
174 const base::Time& end) { 187 const base::Time& end) {
175 CHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 188 CHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
176 EventTypeSet results; 189 EventTypeSet results;
177 std::string start_key = 190 std::string start_key =
178 key_builder_->CreateEventKey(start, EVENT_UNDEFINED); 191 key_builder_->CreateEventKey(start, EVENT_UNDEFINED);
179 std::string end_key = 192 std::string end_key =
180 key_builder_->CreateEventKey(end, EVENT_NUMBER_OF_EVENTS); 193 key_builder_->CreateEventKey(end, EVENT_NUMBER_OF_EVENTS);
181 scoped_ptr<leveldb::Iterator> it(event_db_->NewIterator(read_options_)); 194 scoped_ptr<leveldb::Iterator> it(event_db_->NewIterator(read_options_));
182 for (it->Seek(start_key); 195 for (it->Seek(start_key);
183 it->Valid() && it->key().ToString() <= end_key; 196 it->Valid() && it->key().ToString() <= end_key;
184 it->Next()) { 197 it->Next()) {
185 EventType key_type = 198 EventType key_type =
186 key_builder_->EventKeyToEventType(it->key().ToString()); 199 key_builder_->EventKeyToEventType(it->key().ToString());
187 results.insert(key_type); 200 results.insert(key_type);
188 } 201 }
189 return results; 202 return results;
190 } 203 }
191 204
192 bool Database::AddMetric(const std::string& activity, 205 bool Database::AddMetric(const std::string& activity,
193 MetricType metric, 206 const Metric& metric) {
194 const std::string& value) {
195 CHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 207 CHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
208 if (!metric.IsValid()) {
209 LOG(ERROR) << "Metric to be added is invalid. Type: " << metric.type
210 << ", Time: " << metric.time.ToInternalValue()
211 << ", Value: " << metric.value << ". Ignoring.";
212 return false;
213 }
214
196 UpdateActiveInterval(); 215 UpdateActiveInterval();
197 base::Time timestamp = clock_->GetTime();
198 std::string recent_key = 216 std::string recent_key =
199 key_builder_->CreateRecentKey(timestamp, metric, activity); 217 key_builder_->CreateRecentKey(metric.time, metric.type, activity);
200 std::string metric_key = 218 std::string metric_key =
201 key_builder_->CreateMetricKey(timestamp, metric, activity); 219 key_builder_->CreateMetricKey(metric.time, metric.type, activity);
202 std::string recent_map_key = 220 std::string recent_map_key =
203 key_builder_->CreateRecentMapKey(metric, activity); 221 key_builder_->CreateRecentMapKey(metric.type, activity);
204 // Use recent_map_ to quickly find the key that must be removed. 222 // Use recent_map_ to quickly find the key that must be removed.
205 RecentMap::iterator old_it = recent_map_.find(recent_map_key); 223 RecentMap::iterator old_it = recent_map_.find(recent_map_key);
206 if (old_it != recent_map_.end()) 224 if (old_it != recent_map_.end())
207 recent_db_->Delete(write_options_, old_it->second); 225 recent_db_->Delete(write_options_, old_it->second);
208 recent_map_[recent_map_key] = recent_key; 226 recent_map_[recent_map_key] = recent_key;
209 leveldb::Status recent_status = 227 leveldb::Status recent_status =
210 recent_db_->Put(write_options_, recent_key, value); 228 recent_db_->Put(write_options_, recent_key, metric.ValueAsString());
211 leveldb::Status metric_status = 229 leveldb::Status metric_status =
212 metric_db_->Put(write_options_, metric_key, value); 230 metric_db_->Put(write_options_, metric_key, metric.ValueAsString());
213 231
214 bool max_value_success = UpdateMaxValue(activity, metric, value); 232 bool max_value_success =
233 UpdateMaxValue(activity, metric.type, metric.ValueAsString());
215 return recent_status.ok() && metric_status.ok() && max_value_success; 234 return recent_status.ok() && metric_status.ok() && max_value_success;
216 } 235 }
217 236
218 bool Database::UpdateMaxValue(const std::string& activity, 237 bool Database::UpdateMaxValue(const std::string& activity,
219 MetricType metric, 238 MetricType metric,
220 const std::string& value) { 239 const std::string& value) {
221 std::string max_value_key( 240 std::string max_value_key(
222 key_builder_->CreateMaxValueKey(metric, activity)); 241 key_builder_->CreateMaxValueKey(metric, activity));
223 bool has_key = ContainsKey(max_value_map_, max_value_key); 242 bool has_key = ContainsKey(max_value_map_, max_value_key);
224 if ((has_key && StringToDouble(value) > max_value_map_[max_value_key]) || 243 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)); 333 CHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
315 std::string recent_map_key = 334 std::string recent_map_key =
316 key_builder_->CreateRecentMapKey(metric_type, activity); 335 key_builder_->CreateRecentMapKey(metric_type, activity);
317 if (!ContainsKey(recent_map_, recent_map_key)) 336 if (!ContainsKey(recent_map_, recent_map_key))
318 return false; 337 return false;
319 std::string recent_key = recent_map_[recent_map_key]; 338 std::string recent_key = recent_map_[recent_map_key];
320 339
321 std::string result; 340 std::string result;
322 leveldb::Status status = recent_db_->Get(read_options_, recent_key, &result); 341 leveldb::Status status = recent_db_->Get(read_options_, recent_key, &result);
323 if (status.ok()) 342 if (status.ok())
324 *metric = Metric(key_builder_->SplitRecentKey(recent_key).time, result); 343 *metric = Metric(metric_type,
344 key_builder_->SplitRecentKey(recent_key).time,
345 result);
325 return status.ok(); 346 return status.ok();
326 } 347 }
327 348
328 Database::MetricVector Database::GetStatsForActivityAndMetric( 349 Database::MetricVector Database::GetStatsForActivityAndMetric(
329 const std::string& activity, 350 const std::string& activity,
330 MetricType metric_type, 351 MetricType metric_type,
331 const base::Time& start, 352 const base::Time& start,
332 const base::Time& end) { 353 const base::Time& end) {
333 CHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 354 CHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
334 MetricVector results; 355 MetricVector results;
335 std::string start_key = 356 std::string start_key =
336 key_builder_->CreateMetricKey(start, metric_type, activity); 357 key_builder_->CreateMetricKey(start, metric_type, activity);
337 std::string end_key = 358 std::string end_key =
338 key_builder_->CreateMetricKey(end, metric_type, activity); 359 key_builder_->CreateMetricKey(end, metric_type, activity);
360 leveldb::WriteBatch invalid_entries;
339 scoped_ptr<leveldb::Iterator> it(metric_db_->NewIterator(read_options_)); 361 scoped_ptr<leveldb::Iterator> it(metric_db_->NewIterator(read_options_));
340 for (it->Seek(start_key); 362 for (it->Seek(start_key);
341 it->Valid() && it->key().ToString() <= end_key; 363 it->Valid() && it->key().ToString() <= end_key;
342 it->Next()) { 364 it->Next()) {
343 MetricKey split_key = 365 MetricKey split_key =
344 key_builder_->SplitMetricKey(it->key().ToString()); 366 key_builder_->SplitMetricKey(it->key().ToString());
345 if (split_key.activity == activity) 367 if (split_key.activity == activity) {
346 results.push_back(Metric(split_key.time, it->value().ToString())); 368 Metric metric(metric_type, split_key.time, it->value().ToString());
369 if (!metric.IsValid()) {
370 invalid_entries.Delete(it->key());
371 LOG(ERROR) << "Found bad metric in the database. Type: "
372 << metric.type << ", Time: " << metric.time.ToInternalValue()
373 << ", Value: " << metric.value
374 << ". Erasing metric from database.";
375 continue;
376 }
377 results.push_back(metric);
378 }
347 } 379 }
380 metric_db_->Write(write_options_, &invalid_entries);
348 return results; 381 return results;
349 } 382 }
350 383
351 Database::MetricVectorMap Database::GetStatsForMetricByActivity( 384 Database::MetricVectorMap Database::GetStatsForMetricByActivity(
352 MetricType metric_type, 385 MetricType metric_type,
353 const base::Time& start, 386 const base::Time& start,
354 const base::Time& end) { 387 const base::Time& end) {
355 CHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 388 CHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
356 MetricVectorMap results; 389 MetricVectorMap results;
357 std::string start_key = 390 std::string start_key =
358 key_builder_->CreateMetricKey(start, metric_type, std::string()); 391 key_builder_->CreateMetricKey(start, metric_type, std::string());
359 std::string end_key = 392 std::string end_key =
360 key_builder_->CreateMetricKey(end, metric_type, std::string()); 393 key_builder_->CreateMetricKey(end, metric_type, std::string());
394 leveldb::WriteBatch invalid_entries;
361 scoped_ptr<leveldb::Iterator> it(metric_db_->NewIterator(read_options_)); 395 scoped_ptr<leveldb::Iterator> it(metric_db_->NewIterator(read_options_));
362 for (it->Seek(start_key); 396 for (it->Seek(start_key);
363 it->Valid() && it->key().ToString() <= end_key; 397 it->Valid() && it->key().ToString() <= end_key;
364 it->Next()) { 398 it->Next()) {
365 MetricKey split_key = key_builder_->SplitMetricKey(it->key().ToString()); 399 MetricKey split_key = key_builder_->SplitMetricKey(it->key().ToString());
366 if (!results[split_key.activity].get()) { 400 if (!results[split_key.activity].get()) {
367 results[split_key.activity] = 401 results[split_key.activity] =
368 linked_ptr<MetricVector >(new MetricVector()); 402 linked_ptr<MetricVector >(new MetricVector());
369 } 403 }
370 results[split_key.activity]->push_back( 404 Metric metric(metric_type, split_key.time, it->value().ToString());
371 Metric(split_key.time, it->value().ToString())); 405 if (!metric.IsValid()) {
406 invalid_entries.Delete(it->key());
407 LOG(ERROR) << "Found bad metric in the database. Type: "
408 << metric.type << ", Time: " << metric.time.ToInternalValue()
409 << ", Value: " << metric.value
410 << ". Erasing metric from database.";
411 continue;
412 }
413 results[split_key.activity]->push_back(metric);
372 } 414 }
415 metric_db_->Write(write_options_, &invalid_entries);
373 return results; 416 return results;
374 } 417 }
375 418
376 Database::Database(const FilePath& path) 419 Database::Database(const FilePath& path)
377 : key_builder_(new KeyBuilder()), 420 : key_builder_(new KeyBuilder()),
378 path_(path), 421 path_(path),
379 read_options_(leveldb::ReadOptions()), 422 read_options_(leveldb::ReadOptions()),
380 write_options_(leveldb::WriteOptions()) { 423 write_options_(leveldb::WriteOptions()) {
381 InitDBs(); 424 InitDBs();
382 LoadRecents(); 425 LoadRecents();
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
482 start_time_key_ = key_builder_->CreateActiveIntervalKey(current_time); 525 start_time_key_ = key_builder_->CreateActiveIntervalKey(current_time);
483 end_time = start_time_key_; 526 end_time = start_time_key_;
484 } else { 527 } else {
485 end_time = key_builder_->CreateActiveIntervalKey(clock_->GetTime()); 528 end_time = key_builder_->CreateActiveIntervalKey(clock_->GetTime());
486 } 529 }
487 last_update_time_ = current_time; 530 last_update_time_ = current_time;
488 active_interval_db_->Put(write_options_, start_time_key_, end_time); 531 active_interval_db_->Put(write_options_, start_time_key_, end_time);
489 } 532 }
490 533
491 } // namespace performance_monitor 534 } // namespace performance_monitor
OLDNEW
« no previous file with comments | « chrome/browser/performance_monitor/database.h ('k') | chrome/browser/performance_monitor/database_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698