summaryrefslogtreecommitdiffstats
path: root/chrome/browser
diff options
context:
space:
mode:
authorrdevlin.cronin@chromium.org <rdevlin.cronin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-09-07 07:02:32 +0000
committerrdevlin.cronin@chromium.org <rdevlin.cronin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-09-07 07:02:32 +0000
commit0e9f3e321842c50f7011cca1b40db01d5e798889 (patch)
tree2051637d729c3ab0b7ae083e277213e94e970cc4 /chrome/browser
parentcaf6670cff5c72fd2c5f48db8ddd3f4670baeca4 (diff)
downloadchromium_src-0e9f3e321842c50f7011cca1b40db01d5e798889.zip
chromium_src-0e9f3e321842c50f7011cca1b40db01d5e798889.tar.gz
chromium_src-0e9f3e321842c50f7011cca1b40db01d5e798889.tar.bz2
Make CPM DB use chars for key prefixes
This allows us to edit (reorder, insert, delete) the metric/event enums without compromising the db. BUG=130212 TBR=thakis@chromium.org for gypi change Review URL: https://chromiumcodereview.appspot.com/10916026 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@155346 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser')
-rw-r--r--chrome/browser/performance_monitor/database.cc250
-rw-r--r--chrome/browser/performance_monitor/database.h5
-rw-r--r--chrome/browser/performance_monitor/event.h11
-rw-r--r--chrome/browser/performance_monitor/key_builder.cc247
-rw-r--r--chrome/browser/performance_monitor/key_builder.h98
-rw-r--r--chrome/browser/performance_monitor/metric.h12
6 files changed, 423 insertions, 200 deletions
diff --git a/chrome/browser/performance_monitor/database.cc b/chrome/browser/performance_monitor/database.cc
index 56b9c0c..27108e3 100644
--- a/chrome/browser/performance_monitor/database.cc
+++ b/chrome/browser/performance_monitor/database.cc
@@ -6,17 +6,15 @@
#include "base/file_path.h"
#include "base/file_util.h"
-#include "base/format_macros.h"
#include "base/json/json_reader.h"
#include "base/json/json_writer.h"
#include "base/logging.h"
#include "base/path_service.h"
#include "base/stl_util.h"
#include "base/string_number_conversions.h"
-#include "base/string_split.h"
-#include "base/stringprintf.h"
#include "base/time.h"
#include "base/utf_string_conversions.h"
+#include "chrome/browser/performance_monitor/key_builder.h"
#include "chrome/common/chrome_paths.h"
#include "content/public/browser/browser_thread.h"
#include "third_party/leveldatabase/src/include/leveldb/db.h"
@@ -30,159 +28,11 @@ const char kEventDb[] = "Events";
const char kStateDb[] = "Configuration";
const char kActiveIntervalDb[] = "Active Interval";
const char kMetricDb[] = "Metrics";
-const char kDelimiter = '!';
const double kDefaultMaxValue = 0.0;
-struct RecentKey {
- RecentKey(const std::string& recent_time,
- MetricType recent_type,
- const std::string& recent_activity)
- : time(recent_time),
- type(recent_type),
- activity(recent_activity) {}
- ~RecentKey() {}
-
- const std::string time;
- const MetricType type;
- const std::string activity;
-};
-
-struct MaxValueKey {
- MaxValueKey(MetricType max_value_type,
- const std::string& max_value_activity)
- : type(max_value_type),
- activity(max_value_activity) {}
- ~MaxValueKey() {}
-
- const MetricType type;
- const std::string activity;
-};
-
-struct MetricKey {
- MetricKey(const std::string& metric_time,
- MetricType metric_type,
- const std::string& metric_activity)
- : time(metric_time),
- type(metric_type),
- activity(metric_activity) {}
- ~MetricKey() {}
-
- const std::string time;
- const MetricType type;
- const std::string activity;
-};
-
-// The position of different elements in the key for the event db.
-enum EventKeyPosition {
- EVENT_TIME, // The time the event was generated.
- EVENT_TYPE // The type of event.
-};
-
-// The position of different elements in the key for the recent db.
-enum RecentKeyPosition {
- RECENT_TIME, // The time the stat was gathered.
- RECENT_TYPE, // The unique identifier for the type of metric gathered.
- RECENT_ACTIVITY // The unique identifier for the activity.
-};
-
-// The position of different elements in the key for the max value db.
-enum MaxValueKeyPosition {
- MAX_VALUE_TYPE, // The unique identifier for the type of metric gathered.
- MAX_VALUE_ACTIVITY // The unique identifier for the activity.
-};
-
-// The position of different elements in the key for a metric db.
-enum MetricKeyPosition {
- METRIC_TYPE, // The unique identifier for the metric.
- METRIC_TIME, // The time the stat was gathered.
- METRIC_ACTIVITY // The unique identifier for the activity.
-};
-
// If the db is quiet for this number of minutes, then it is considered down.
const base::TimeDelta kActiveIntervalTimeout = base::TimeDelta::FromMinutes(5);
-// Create the key used for internal active interval monitoring.
-// Key Schema: <Time>
-std::string CreateActiveIntervalKey(const base::Time& time) {
- return StringPrintf("%016" PRId64, time.ToInternalValue());
-}
-
-// Create the database key for a particular event.
-// Key Schema: <Time>-<Event Type>
-// Where '-' represents the delimiter.
-std::string CreateEventKey(const base::Time& time, EventType event_type) {
- return StringPrintf("%016" PRId64 "%c%04d", time.ToInternalValue(),
- kDelimiter, static_cast<int>(event_type));
-}
-
-// Create the database key for a certain metric to go in the "Recent" database.
-// Key Schema: <Time>-<Metric>-<Activity>
-std::string CreateRecentKey(const base::Time& time,
- MetricType metric_type,
- const std::string& activity) {
- return StringPrintf("%016" PRId64 "%c%04d%c%s", time.ToInternalValue(),
- kDelimiter, metric_type, kDelimiter, activity.c_str());
-}
-
-// Create the database key for a certain metric to go in the "Max Value"
-// database.
-// Key Schema: <Metric>-<Activity>
-std::string CreateMaxValueKey(MetricType metric_type,
- const std::string& activity) {
- return StringPrintf("%04d%c%s", metric_type, kDelimiter, activity.c_str());
-}
-
-EventType EventKeyToEventType(const std::string& event_key) {
- std::vector<std::string> split;
- base::SplitString(event_key, kDelimiter, &split);
- int event_type = 0;
- base::StringToInt(split[EVENT_TYPE], &event_type);
- return static_cast<EventType>(event_type);
-}
-
-MetricType StringToMetricType(const std::string& metric_type) {
- int metric_type_int = 0;
- base::StringToInt(metric_type, &metric_type_int);
- return static_cast<MetricType>(metric_type_int);
-}
-
-RecentKey SplitRecentKey(const std::string& key) {
- std::vector<std::string> split;
- base::SplitString(key, kDelimiter, &split);
- return RecentKey(split[RECENT_TIME], StringToMetricType(split[RECENT_TYPE]),
- split[RECENT_ACTIVITY]);
-}
-
-MaxValueKey SplitMaxValueKey(const std::string& key) {
- std::vector<std::string> split;
- base::SplitString(key, kDelimiter, &split);
- return MaxValueKey(StringToMetricType(split[MAX_VALUE_TYPE]),
- split[MAX_VALUE_ACTIVITY]);
-}
-
-// Create the database key for a statistic of a certain metric.
-// Key Schema: <Metric>-<Time>-<Activity>
-std::string CreateMetricKey(const base::Time& time,
- MetricType metric_type,
- const std::string& activity) {
- return StringPrintf("%04d%c%016" PRId64 "%c%s", metric_type, kDelimiter,
- time.ToInternalValue(), kDelimiter, activity.c_str());
-}
-
-MetricKey SplitMetricKey(const std::string& key) {
- std::vector<std::string> split;
- base::SplitString(key, kDelimiter, &split);
- return MetricKey(split[METRIC_TIME], StringToMetricType(split[METRIC_TYPE]),
- split[METRIC_ACTIVITY]);
-}
-
-// Create the key for recent_map_.
-// Key Schema: <Activity>-<Metric>
-std::string CreateRecentMapKey(MetricType metric_type,
- const std::string& activity) {
- return StringPrintf("%s%c%04d", activity.c_str(), kDelimiter, metric_type);
-}
-
TimeRange ActiveIntervalToTimeRange(const std::string& start_time,
const std::string& end_time) {
int64 start_time_int = 0;
@@ -251,7 +101,7 @@ bool Database::AddEvent(const Event& event) {
UpdateActiveInterval();
std::string value;
base::JSONWriter::Write(event.data(), &value);
- std::string key = CreateEventKey(event.time(), event.type());
+ std::string key = key_builder_->CreateEventKey(event.time(), event.type());
leveldb::Status status = event_db_->Put(write_options_, key, value);
return status.ok();
}
@@ -260,8 +110,8 @@ std::vector<TimeRange> Database::GetActiveIntervals(const base::Time& start,
const base::Time& end) {
CHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
std::vector<TimeRange> results;
- std::string start_key = CreateActiveIntervalKey(start);
- std::string end_key = CreateActiveIntervalKey(end);
+ std::string start_key = key_builder_->CreateActiveIntervalKey(start);
+ std::string end_key = key_builder_->CreateActiveIntervalKey(end);
scoped_ptr<leveldb::Iterator> it(active_interval_db_->NewIterator(
read_options_));
it->Seek(start_key);
@@ -291,14 +141,17 @@ Database::EventVector Database::GetEvents(EventType type,
const base::Time& end) {
CHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
EventVector events;
- std::string start_key = CreateEventKey(start, EVENT_UNDEFINED);
- std::string end_key = CreateEventKey(end, EVENT_NUMBER_OF_EVENTS);
+ std::string start_key =
+ key_builder_->CreateEventKey(start, EVENT_UNDEFINED);
+ std::string end_key =
+ key_builder_->CreateEventKey(end, EVENT_NUMBER_OF_EVENTS);
scoped_ptr<leveldb::Iterator> it(event_db_->NewIterator(read_options_));
for (it->Seek(start_key);
it->Valid() && it->key().ToString() <= end_key;
it->Next()) {
if (type != EVENT_UNDEFINED) {
- EventType key_type = EventKeyToEventType(it->key().ToString());
+ EventType key_type =
+ key_builder_->EventKeyToEventType(it->key().ToString());
if (key_type != type)
continue;
}
@@ -321,13 +174,16 @@ Database::EventTypeSet Database::GetEventTypes(const base::Time& start,
const base::Time& end) {
CHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
EventTypeSet results;
- std::string start_key = CreateEventKey(start, EVENT_UNDEFINED);
- std::string end_key = CreateEventKey(end, EVENT_NUMBER_OF_EVENTS);
+ std::string start_key =
+ key_builder_->CreateEventKey(start, EVENT_UNDEFINED);
+ std::string end_key =
+ key_builder_->CreateEventKey(end, EVENT_NUMBER_OF_EVENTS);
scoped_ptr<leveldb::Iterator> it(event_db_->NewIterator(read_options_));
for (it->Seek(start_key);
it->Valid() && it->key().ToString() <= end_key;
it->Next()) {
- EventType key_type = EventKeyToEventType(it->key().ToString());
+ EventType key_type =
+ key_builder_->EventKeyToEventType(it->key().ToString());
results.insert(key_type);
}
return results;
@@ -339,9 +195,12 @@ bool Database::AddMetric(const std::string& activity,
CHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
UpdateActiveInterval();
base::Time timestamp = clock_->GetTime();
- std::string recent_key = CreateRecentKey(timestamp, metric, activity);
- std::string metric_key = CreateMetricKey(timestamp, metric, activity);
- std::string recent_map_key = CreateRecentMapKey(metric, activity);
+ std::string recent_key =
+ key_builder_->CreateRecentKey(timestamp, metric, activity);
+ std::string metric_key =
+ key_builder_->CreateMetricKey(timestamp, metric, activity);
+ std::string recent_map_key =
+ key_builder_->CreateRecentMapKey(metric, activity);
// Use recent_map_ to quickly find the key that must be removed.
RecentMap::iterator old_it = recent_map_.find(recent_map_key);
if (old_it != recent_map_.end())
@@ -359,7 +218,8 @@ bool Database::AddMetric(const std::string& activity,
bool Database::UpdateMaxValue(const std::string& activity,
MetricType metric,
const std::string& value) {
- std::string max_value_key(CreateMaxValueKey(metric, activity));
+ std::string max_value_key(
+ key_builder_->CreateMaxValueKey(metric, activity));
bool has_key = ContainsKey(max_value_map_, max_value_key);
if ((has_key && StringToDouble(value) > max_value_map_[max_value_key]) ||
!has_key) {
@@ -373,11 +233,11 @@ bool Database::UpdateMaxValue(const std::string& activity,
Database::MetricTypeSet Database::GetActiveMetrics(const base::Time& start,
const base::Time& end) {
CHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
- std::string recent_start_key = CreateRecentKey(
+ std::string recent_start_key = key_builder_->CreateRecentKey(
start, static_cast<MetricType>(0), std::string());
- std::string recent_end_key = CreateRecentKey(
+ std::string recent_end_key = key_builder_->CreateRecentKey(
end, METRIC_NUMBER_OF_METRICS, std::string());
- std::string recent_end_of_time_key = CreateRecentKey(
+ std::string recent_end_of_time_key = key_builder_->CreateRecentKey(
clock_->GetTime(), METRIC_NUMBER_OF_METRICS, std::string());
MetricTypeSet active_metrics;
@@ -387,7 +247,8 @@ Database::MetricTypeSet Database::GetActiveMetrics(const base::Time& start,
for (recent_it->Seek(recent_start_key);
recent_it->Valid() && recent_it->key().ToString() <= recent_end_key;
recent_it->Next()) {
- RecentKey split_key = SplitRecentKey(recent_it->key().ToString());
+ RecentKey split_key =
+ key_builder_->SplitRecentKey(recent_it->key().ToString());
active_metrics.insert(split_key.type);
}
// Get all the possible metrics (metrics that may have been updated after
@@ -397,7 +258,8 @@ Database::MetricTypeSet Database::GetActiveMetrics(const base::Time& start,
recent_it->Valid() &&
recent_it->key().ToString() <= recent_end_of_time_key;
recent_it->Next()) {
- RecentKey split_key = SplitRecentKey(recent_it->key().ToString());
+ RecentKey split_key =
+ key_builder_->SplitRecentKey(recent_it->key().ToString());
possible_metrics.insert(split_key.type);
}
MetricTypeSet::iterator possible_it;
@@ -406,10 +268,10 @@ Database::MetricTypeSet Database::GetActiveMetrics(const base::Time& start,
for (possible_it = possible_metrics.begin();
possible_it != possible_metrics.end();
++possible_it) {
- std::string metric_start_key = CreateMetricKey(start, *possible_it,
- std::string());
- std::string metric_end_key = CreateMetricKey(end, *possible_it,
- std::string());
+ std::string metric_start_key =
+ key_builder_->CreateMetricKey(start, *possible_it,std::string());
+ std::string metric_end_key =
+ key_builder_->CreateMetricKey(end, *possible_it, std::string());
metric_it->Seek(metric_start_key);
// Stats in the timerange from any activity makes the metric active.
if (metric_it->Valid() && metric_it->key().ToString() <= metric_end_key) {
@@ -424,11 +286,12 @@ std::set<std::string> Database::GetActiveActivities(MetricType metric_type,
const base::Time& start) {
CHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
std::set<std::string> results;
- std::string start_key = CreateRecentKey(
+ std::string start_key = key_builder_->CreateRecentKey(
start, static_cast<MetricType>(0), std::string());
scoped_ptr<leveldb::Iterator> it(recent_db_->NewIterator(read_options_));
for (it->Seek(start_key); it->Valid(); it->Next()) {
- RecentKey split_key = SplitRecentKey(it->key().ToString());
+ RecentKey split_key =
+ key_builder_->SplitRecentKey(it->key().ToString());
if (split_key.type == metric_type)
results.insert(split_key.activity);
}
@@ -438,7 +301,8 @@ std::set<std::string> Database::GetActiveActivities(MetricType metric_type,
double Database::GetMaxStatsForActivityAndMetric(const std::string& activity,
MetricType metric) {
CHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
- std::string max_value_key(CreateMaxValueKey(metric, activity));
+ std::string max_value_key(
+ key_builder_->CreateMaxValueKey(metric, activity));
if (ContainsKey(max_value_map_, max_value_key))
return max_value_map_[max_value_key];
return kDefaultMaxValue;
@@ -448,7 +312,8 @@ bool Database::GetRecentStatsForActivityAndMetric(const std::string& activity,
MetricType metric_type,
Metric* metric) {
CHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
- std::string recent_map_key = CreateRecentMapKey(metric_type, activity);
+ std::string recent_map_key =
+ key_builder_->CreateRecentMapKey(metric_type, activity);
if (!ContainsKey(recent_map_, recent_map_key))
return false;
std::string recent_key = recent_map_[recent_map_key];
@@ -456,7 +321,7 @@ bool Database::GetRecentStatsForActivityAndMetric(const std::string& activity,
std::string result;
leveldb::Status status = recent_db_->Get(read_options_, recent_key, &result);
if (status.ok())
- *metric = Metric(SplitRecentKey(recent_key).time, result);
+ *metric = Metric(key_builder_->SplitRecentKey(recent_key).time, result);
return status.ok();
}
@@ -467,13 +332,16 @@ Database::MetricVector Database::GetStatsForActivityAndMetric(
const base::Time& end) {
CHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
MetricVector results;
- std::string start_key = CreateMetricKey(start, metric_type, activity);
- std::string end_key = CreateMetricKey(end, metric_type, activity);
+ std::string start_key =
+ key_builder_->CreateMetricKey(start, metric_type, activity);
+ std::string end_key =
+ key_builder_->CreateMetricKey(end, metric_type, activity);
scoped_ptr<leveldb::Iterator> it(metric_db_->NewIterator(read_options_));
for (it->Seek(start_key);
it->Valid() && it->key().ToString() <= end_key;
it->Next()) {
- MetricKey split_key = SplitMetricKey(it->key().ToString());
+ MetricKey split_key =
+ key_builder_->SplitMetricKey(it->key().ToString());
if (split_key.activity == activity)
results.push_back(Metric(split_key.time, it->value().ToString()));
}
@@ -486,13 +354,15 @@ Database::MetricVectorMap Database::GetStatsForMetricByActivity(
const base::Time& end) {
CHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
MetricVectorMap results;
- std::string start_key = CreateMetricKey(start, metric_type, std::string());
- std::string end_key = CreateMetricKey(end, metric_type, std::string());
+ std::string start_key =
+ key_builder_->CreateMetricKey(start, metric_type, std::string());
+ std::string end_key =
+ key_builder_->CreateMetricKey(end, metric_type, std::string());
scoped_ptr<leveldb::Iterator> it(metric_db_->NewIterator(read_options_));
for (it->Seek(start_key);
it->Valid() && it->key().ToString() <= end_key;
it->Next()) {
- MetricKey split_key = SplitMetricKey(it->key().ToString());
+ MetricKey split_key = key_builder_->SplitMetricKey(it->key().ToString());
if (!results[split_key.activity].get()) {
results[split_key.activity] =
linked_ptr<MetricVector >(new MetricVector());
@@ -504,7 +374,8 @@ Database::MetricVectorMap Database::GetStatsForMetricByActivity(
}
Database::Database(const FilePath& path)
- : path_(path),
+ : key_builder_(new KeyBuilder()),
+ path_(path),
read_options_(leveldb::ReadOptions()),
write_options_(leveldb::WriteOptions()) {
InitDBs();
@@ -582,8 +453,9 @@ void Database::LoadRecents() {
recent_map_.clear();
scoped_ptr<leveldb::Iterator> it(recent_db_->NewIterator(read_options_));
for (it->SeekToFirst(); it->Valid(); it->Next()) {
- RecentKey split_key = SplitRecentKey(it->key().ToString());
- recent_map_[CreateRecentMapKey(split_key.type, split_key.activity)] =
+ RecentKey split_key = key_builder_->SplitRecentKey(it->key().ToString());
+ recent_map_[key_builder_->
+ CreateRecentMapKey(split_key.type, split_key.activity)] =
it->key().ToString();
}
}
@@ -607,10 +479,10 @@ void Database::UpdateActiveInterval() {
// If the last update was too long ago.
if (start_time_key_.empty() ||
current_time - last_update_time_ > kActiveIntervalTimeout) {
- start_time_key_ = CreateActiveIntervalKey(current_time);
+ start_time_key_ = key_builder_->CreateActiveIntervalKey(current_time);
end_time = start_time_key_;
} else {
- end_time = CreateActiveIntervalKey(clock_->GetTime());
+ end_time = key_builder_->CreateActiveIntervalKey(clock_->GetTime());
}
last_update_time_ = current_time;
active_interval_db_->Put(write_options_, start_time_key_, end_time);
diff --git a/chrome/browser/performance_monitor/database.h b/chrome/browser/performance_monitor/database.h
index 4633a9d..8cec7fc 100644
--- a/chrome/browser/performance_monitor/database.h
+++ b/chrome/browser/performance_monitor/database.h
@@ -30,6 +30,8 @@ struct TimeRange {
base::Time end;
};
+class KeyBuilder;
+
// The class supporting all performance monitor storage. This class wraps
// multiple leveldb::DB objects. All methods must be called from a background
// thread. Callers should use BrowserThread::PostBlockingPoolSequencedTask using
@@ -261,13 +263,14 @@ class Database {
// Mark the database as being active for the current time.
void UpdateActiveInterval();
-
// Updates the max_value_map_ and max_value_db_ if the value is greater than
// the current max value for the given activity and metric.
bool UpdateMaxValue(const std::string& activity,
MetricType metric,
const std::string& value);
+ scoped_ptr<KeyBuilder> key_builder_;
+
// A mapping of id,metric to the last inserted key for those parameters
// is maintained to prevent having to search through the recent db every
// insert.
diff --git a/chrome/browser/performance_monitor/event.h b/chrome/browser/performance_monitor/event.h
index a4fc2c5..c2c266b5 100644
--- a/chrome/browser/performance_monitor/event.h
+++ b/chrome/browser/performance_monitor/event.h
@@ -11,11 +11,12 @@
namespace performance_monitor {
-// IMPORTANT: This is used as an indication of the event type within the
-// performance monitor database; do not change the order! If you add new
-// event types to this list, place them above NUMBER_OF_EVENTS and add the
-// appropriate messages/functions in generated_resources.grd and in
-// chrome/browser/ui/webui/performance_monitor/l10n_util.
+// IMPORTANT: To add new events, please
+// - Place the new event above EVENT_NUMBER_OF_EVENTS.
+// - Add a member to the EventKeyChar enum in key_builder.cc.
+// - Add the appropriate messages in generated_resources.grd.
+// - Add the appropriate functions in
+// chrome/browser/ui/webui/performance_monitor/performance_monitor_l10n.h.
enum EventType {
EVENT_UNDEFINED,
EVENT_EXTENSION_INSTALL,
diff --git a/chrome/browser/performance_monitor/key_builder.cc b/chrome/browser/performance_monitor/key_builder.cc
new file mode 100644
index 0000000..cfe0e29
--- /dev/null
+++ b/chrome/browser/performance_monitor/key_builder.cc
@@ -0,0 +1,247 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/performance_monitor/key_builder.h"
+
+#include "base/format_macros.h"
+#include "base/logging.h"
+#include "base/string_number_conversions.h"
+#include "base/string_split.h"
+#include "base/stringprintf.h"
+
+namespace performance_monitor {
+
+namespace {
+
+const char kDelimiter = '!';
+
+// These values are used as the portion of the generated key which represents
+// the event/metric type when inserting values in the database. We use an ASCII
+// character as a mapping, rather than the enum of the metric or event itself,
+// so that we can edit the MetricType and EventType enums as desired, without
+// worrying about the integrity of the database.
+//
+// Once a character mapping has been set for a metric or event, do not change
+// its value! New character mappings should be greater than 34 (ASCII characters
+// below 32 have meaning, 33 is '!' - the database delimiter, and 34 is reserved
+// for the 'Undefined' character mapping). Do not repeat values within the
+// metric/event sets (repeated values between sets are okay).
+//
+// Deprecated keys: A key which is deprecated should be clearly marked as such,
+// and its use discontinued. Do not remove the key from the listing! (Otherwise,
+// a new metric may take its key and think the old data belongs to it.)
+
+enum MetricKeyChar {
+METRIC_UNDEFINED_KEY_CHAR = 34,
+METRIC_CPU_USAGE_KEY_CHAR = 35,
+METRIC_PRIVATE_MEMORY_USAGE_KEY_CHAR = 36,
+METRIC_SHARED_MEMORY_USAGE_KEY_CHAR = 37,
+METRIC_STARTUP_TIME_KEY_CHAR = 38,
+METRIC_TEST_STARTUP_TIME_KEY_CHAR = 39,
+METRIC_SESSION_RESTORE_TIME_KEY_CHAR = 40,
+METRIC_PAGE_LOAD_TIME_KEY_CHAR = 41,
+METRIC_NETWORK_BYTES_READ_KEY_CHAR = 42,
+METRIC_NUMBER_OF_METRICS_KEY_CHAR = 255,
+};
+
+enum EventKeyChar {
+EVENT_UNDEFINED_KEY_CHAR = 34,
+EVENT_EXTENSION_INSTALL_KEY_CHAR = 35,
+EVENT_EXTENSION_UNINSTALL_KEY_CHAR = 36,
+EVENT_EXTENSION_UPDATE_KEY_CHAR = 37,
+EVENT_EXTENSION_ENABLE_KEY_CHAR = 38,
+EVENT_EXTENSION_DISABLE_KEY_CHAR = 39,
+EVENT_CHROME_UPDATE_KEY_CHAR = 40,
+EVENT_RENDERER_FREEZE_KEY_CHAR = 41,
+EVENT_RENDERER_CRASH_KEY_CHAR = 42,
+EVENT_KILLED_BY_OS_CRASH_KEY_CHAR = 43,
+EVENT_UNCLEAN_EXIT_KEY_CHAR = 44,
+EVENT_NUMBER_OF_EVENTS_KEY_CHAR = 255,
+};
+
+// The position of different elements in the key for the event db.
+enum EventKeyPosition {
+ EVENT_TIME, // The time the event was generated.
+ EVENT_TYPE // The type of event.
+};
+
+// The position of different elements in the key for the recent db.
+enum RecentKeyPosition {
+ RECENT_TIME, // The time the stat was gathered.
+ RECENT_TYPE, // The unique identifier for the type of metric gathered.
+ RECENT_ACTIVITY // The unique identifier for the activity.
+};
+
+// The position of different elements in the key for the max value db.
+enum MaxValueKeyPosition {
+ MAX_VALUE_TYPE, // The unique identifier for the type of metric gathered.
+ MAX_VALUE_ACTIVITY // The unique identifier for the activity.
+};
+
+// The position of different elements in the key for a metric db.
+enum MetricKeyPosition {
+ METRIC_TYPE, // The unique identifier for the metric.
+ METRIC_TIME, // The time the stat was gathered.
+ METRIC_ACTIVITY // The unique identifier for the activity.
+};
+
+} // namespace
+
+RecentKey::RecentKey(const std::string& recent_time,
+ MetricType recent_type,
+ const std::string& recent_activity)
+ : time(recent_time), type(recent_type), activity(recent_activity) {
+}
+
+RecentKey::~RecentKey() {
+}
+
+MetricKey::MetricKey(const std::string& metric_time,
+ MetricType metric_type,
+ const std::string& metric_activity)
+ : time(metric_time), type(metric_type), activity(metric_activity) {
+}
+
+MetricKey::~MetricKey() {
+}
+
+KeyBuilder::KeyBuilder() {
+ PopulateKeyMaps();
+}
+
+KeyBuilder::~KeyBuilder() {
+}
+
+void KeyBuilder::PopulateKeyMaps() {
+ // Hard-code the generation of the map between event types and event key
+ // character mappings.
+ event_type_to_event_key_char_[EVENT_UNDEFINED] = EVENT_UNDEFINED_KEY_CHAR;
+ event_type_to_event_key_char_[EVENT_EXTENSION_INSTALL] =
+ EVENT_EXTENSION_INSTALL_KEY_CHAR;
+ event_type_to_event_key_char_[EVENT_EXTENSION_UNINSTALL] =
+ EVENT_EXTENSION_UNINSTALL_KEY_CHAR;
+ event_type_to_event_key_char_[EVENT_EXTENSION_UPDATE] =
+ EVENT_EXTENSION_UPDATE_KEY_CHAR;
+ event_type_to_event_key_char_[EVENT_EXTENSION_ENABLE] =
+ EVENT_EXTENSION_ENABLE_KEY_CHAR;
+ event_type_to_event_key_char_[EVENT_EXTENSION_DISABLE] =
+ EVENT_EXTENSION_DISABLE_KEY_CHAR;
+ event_type_to_event_key_char_[EVENT_RENDERER_FREEZE] =
+ EVENT_RENDERER_FREEZE_KEY_CHAR;
+ event_type_to_event_key_char_[EVENT_RENDERER_CRASH] =
+ EVENT_RENDERER_CRASH_KEY_CHAR;
+ event_type_to_event_key_char_[EVENT_KILLED_BY_OS_CRASH] =
+ EVENT_KILLED_BY_OS_CRASH_KEY_CHAR;
+ event_type_to_event_key_char_[EVENT_UNCLEAN_EXIT] =
+ EVENT_UNCLEAN_EXIT_KEY_CHAR;
+ event_type_to_event_key_char_[EVENT_NUMBER_OF_EVENTS] =
+ EVENT_NUMBER_OF_EVENTS_KEY_CHAR;
+ DCHECK(event_type_to_event_key_char_.size() == EVENT_NUMBER_OF_EVENTS);
+
+ // Generate the reverse map for easy look-up between event character mappings
+ // and event types.
+ for (int i = static_cast<int>(EVENT_UNDEFINED);
+ i <= static_cast<int>(EVENT_NUMBER_OF_EVENTS); ++i) {
+ event_key_char_to_event_type_[event_type_to_event_key_char_[
+ static_cast<EventType>(i)]] = static_cast<EventType>(i);
+ }
+
+ // Repeat the process for metrics.
+ metric_type_to_metric_key_char_[METRIC_UNDEFINED] = METRIC_UNDEFINED_KEY_CHAR;
+ metric_type_to_metric_key_char_[METRIC_CPU_USAGE] = METRIC_CPU_USAGE_KEY_CHAR;
+ metric_type_to_metric_key_char_[METRIC_PRIVATE_MEMORY_USAGE] =
+ METRIC_PRIVATE_MEMORY_USAGE_KEY_CHAR;
+ metric_type_to_metric_key_char_[METRIC_SHARED_MEMORY_USAGE] =
+ METRIC_SHARED_MEMORY_USAGE_KEY_CHAR;
+ metric_type_to_metric_key_char_[METRIC_STARTUP_TIME] =
+ METRIC_STARTUP_TIME_KEY_CHAR;
+ metric_type_to_metric_key_char_[METRIC_TEST_STARTUP_TIME] =
+ METRIC_TEST_STARTUP_TIME_KEY_CHAR;
+ metric_type_to_metric_key_char_[METRIC_PAGE_LOAD_TIME] =
+ METRIC_PAGE_LOAD_TIME_KEY_CHAR;
+ metric_type_to_metric_key_char_[METRIC_NETWORK_BYTES_READ] =
+ METRIC_NETWORK_BYTES_READ_KEY_CHAR;
+ metric_type_to_metric_key_char_[METRIC_NUMBER_OF_METRICS] =
+ METRIC_NUMBER_OF_METRICS_KEY_CHAR;
+ DCHECK(metric_type_to_metric_key_char_.size() == METRIC_NUMBER_OF_METRICS);
+
+ for (int i = static_cast<int>(METRIC_UNDEFINED);
+ i <= static_cast<int>(METRIC_NUMBER_OF_METRICS); ++i) {
+ metric_key_char_to_metric_type_[metric_type_to_metric_key_char_[
+ static_cast<MetricType>(i)]] = static_cast<MetricType>(i);
+ }
+}
+
+std::string KeyBuilder::CreateActiveIntervalKey(const base::Time& time) {
+ return StringPrintf("%016" PRId64, time.ToInternalValue());
+}
+
+std::string KeyBuilder::CreateMetricKey(const base::Time& time,
+ const MetricType type,
+ const std::string& activity) {
+ return StringPrintf("%c%c%016" PRId64 "%c%s",
+ metric_type_to_metric_key_char_[type],
+ kDelimiter, time.ToInternalValue(),
+ kDelimiter, activity.c_str());
+}
+
+std::string KeyBuilder::CreateEventKey(const base::Time& time,
+ const EventType type) {
+ return StringPrintf("%016" PRId64 "%c%c",
+ time.ToInternalValue(), kDelimiter,
+ event_type_to_event_key_char_[type]);
+}
+
+std::string KeyBuilder::CreateRecentKey(const base::Time& time,
+ const MetricType type,
+ const std::string& activity) {
+ return StringPrintf("%016" PRId64 "%c%c%c%s",
+ time.ToInternalValue(),
+ kDelimiter, metric_type_to_metric_key_char_[type],
+ kDelimiter, activity.c_str());
+}
+
+std::string KeyBuilder::CreateRecentMapKey(const MetricType type,
+ const std::string& activity) {
+ return StringPrintf("%s%c%c",
+ activity.c_str(),
+ kDelimiter, metric_type_to_metric_key_char_[type]);
+}
+
+std::string KeyBuilder::CreateMaxValueKey(const MetricType type,
+ const std::string& activity) {
+ return StringPrintf("%c%c%s",
+ metric_type_to_metric_key_char_[type],
+ kDelimiter, activity.c_str());
+}
+
+EventType KeyBuilder::EventKeyToEventType(const std::string& event_key) {
+ std::vector<std::string> split;
+ base::SplitString(event_key, kDelimiter, &split);
+ DCHECK(split[EVENT_TYPE].size() == 1);
+ return event_key_char_to_event_type_[
+ static_cast<int>(split[EVENT_TYPE].at(0))];
+}
+
+RecentKey KeyBuilder::SplitRecentKey(const std::string& key) {
+ std::vector<std::string> split;
+ base::SplitString(key, kDelimiter, &split);
+ DCHECK(split[RECENT_TYPE].size() == 1);
+ return RecentKey(split[RECENT_TIME],
+ metric_key_char_to_metric_type_[
+ static_cast<int>(split[RECENT_TYPE].at(0))],
+ split[RECENT_ACTIVITY]);
+}
+
+MetricKey KeyBuilder::SplitMetricKey(const std::string& key) {
+ std::vector<std::string> split;
+ base::SplitString(key, kDelimiter, &split);
+ DCHECK(split[METRIC_TYPE].size() == 1);
+ return MetricKey(split[METRIC_TIME],
+ metric_key_char_to_metric_type_[
+ static_cast<int>(split[METRIC_TYPE].at(0))],
+ split[METRIC_ACTIVITY]);
+}
+
+} // namespace performance_monitor
diff --git a/chrome/browser/performance_monitor/key_builder.h b/chrome/browser/performance_monitor/key_builder.h
new file mode 100644
index 0000000..1b4ac24
--- /dev/null
+++ b/chrome/browser/performance_monitor/key_builder.h
@@ -0,0 +1,98 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_PERFORMANCE_MONITOR_KEY_BUILDER_H_
+#define CHROME_BROWSER_PERFORMANCE_MONITOR_KEY_BUILDER_H_
+
+#include <map>
+
+#include "chrome/browser/performance_monitor/event.h"
+#include "chrome/browser/performance_monitor/metric.h"
+
+namespace performance_monitor {
+
+struct RecentKey {
+ RecentKey(const std::string& recent_time,
+ MetricType recent_type,
+ const std::string& recent_activity);
+ ~RecentKey();
+
+ const std::string time;
+ const MetricType type;
+ const std::string activity;
+};
+
+struct MaxValueKey {
+ MaxValueKey(MetricType max_value_type,
+ const std::string& max_value_activity)
+ : type(max_value_type),
+ activity(max_value_activity) {}
+ ~MaxValueKey() {}
+
+ const MetricType type;
+ const std::string activity;
+};
+
+struct MetricKey {
+ MetricKey(const std::string& metric_time,
+ MetricType metric_type,
+ const std::string& metric_activity);
+ ~MetricKey();
+
+ const std::string time;
+ const MetricType type;
+ const std::string activity;
+};
+
+// This class is responsible for building the keys which are used internally by
+// PerformanceMonitor's database. These keys should only be referenced by the
+// database, and should not be used externally.
+class KeyBuilder {
+ public:
+ KeyBuilder();
+ ~KeyBuilder();
+
+ // Key Creation: Create the keys for different databases. The schemas are
+ // listed with the methods. A '-' in the schema represents kDelimeter.
+
+ // Key Schema: <Time>
+ std::string CreateActiveIntervalKey(const base::Time& time);
+
+ // Key Schema: <Metric>-<Time>-<Activity>
+ std::string CreateMetricKey(const base::Time& time,
+ const MetricType type,
+ const std::string& activity);
+
+ // Key Schema: <Time>-<Event Type>
+ std::string CreateEventKey(const base::Time& time, const EventType type);
+
+ // Key Schema: <Time>-<Metric>-<Activity>
+ std::string CreateRecentKey(const base::Time& time,
+ const MetricType type,
+ const std::string& activity);
+
+ // Key Schema: <Activity>-<Metric>
+ std::string CreateRecentMapKey(const MetricType type,
+ const std::string& activity);
+
+ std::string CreateMaxValueKey(const MetricType type,
+ const std::string& activity);
+
+ EventType EventKeyToEventType(const std::string& key);
+ RecentKey SplitRecentKey(const std::string& key);
+ MetricKey SplitMetricKey(const std::string& key);
+
+ private:
+ // Populate the maps from [Event, Metric]Type to key characters.
+ void PopulateKeyMaps();
+
+ std::map<EventType, int> event_type_to_event_key_char_;
+ std::map<int, EventType> event_key_char_to_event_type_;
+ std::map<MetricType, int> metric_type_to_metric_key_char_;
+ std::map<int, MetricType> metric_key_char_to_metric_type_;
+};
+
+} // namespace performance_monitor
+
+#endif // CHROME_BROWSER_PERFORMANCE_MONITOR_KEY_BUILDER_H_
diff --git a/chrome/browser/performance_monitor/metric.h b/chrome/browser/performance_monitor/metric.h
index 7d717b9..76e8ded 100644
--- a/chrome/browser/performance_monitor/metric.h
+++ b/chrome/browser/performance_monitor/metric.h
@@ -10,12 +10,14 @@
namespace performance_monitor {
-// IMPORTANT: This is used as an indication of the metric type within the
-// performance monitor database; do not change the order! If you add new
-// metric types to this list, place them above METRIC_NUMBER_OF_METRICS and add
-// the appropriate messages/functions in generated_resources.grd and in
-// chrome/browser/ui/webui/performance_monitor/l10n_util.
+// IMPORTANT: To add new metrics, please
+// - Place the new metric above METRIC_NUMBER_OF_METRICS.
+// - Add a member to the MetricKeyChar enum in key_builder.cc.
+// - Add the appropriate messages in generated_resources.grd.
+// - Add the appropriate functions in
+// chrome/browser/ui/webui/performance_monitor/performance_monitor_l10n.h.
enum MetricType {
+METRIC_UNDEFINED,
METRIC_CPU_USAGE,
METRIC_PRIVATE_MEMORY_USAGE,
METRIC_SHARED_MEMORY_USAGE,