OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |