diff options
author | asvitkine@chromium.org <asvitkine@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-06-29 17:54:13 +0000 |
---|---|---|
committer | asvitkine@chromium.org <asvitkine@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-06-29 17:54:13 +0000 |
commit | 38b80bbab9db5a423cace41e4e7757eb4f27806c (patch) | |
tree | 83b55813af588337a42140b19df8bd5feaa6df5a /chrome/common | |
parent | 24664d6766ccc67c52034913f57ba168490b2571 (diff) | |
download | chromium_src-38b80bbab9db5a423cace41e4e7757eb4f27806c.zip chromium_src-38b80bbab9db5a423cace41e4e7757eb4f27806c.tar.gz chromium_src-38b80bbab9db5a423cace41e4e7757eb4f27806c.tar.bz2 |
[Mac] Add field trial tuples to breakpad crash reports.
This is the Mac-side of http://codereview.chromium.org/9432033.
BUG=134741
TEST=Mac crash dumps show experiment chunks.
Review URL: https://chromiumcodereview.appspot.com/10661057
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@144929 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/common')
-rw-r--r-- | chrome/common/child_process_logging.h | 5 | ||||
-rw-r--r-- | chrome/common/child_process_logging_mac.mm | 28 | ||||
-rw-r--r-- | chrome/common/metrics/experiments_helper.cc | 20 | ||||
-rw-r--r-- | chrome/common/metrics/experiments_helper.h | 8 | ||||
-rw-r--r-- | chrome/common/metrics/experiments_helper_unittest.cc | 100 |
5 files changed, 136 insertions, 25 deletions
diff --git a/chrome/common/child_process_logging.h b/chrome/common/child_process_logging.h index cc4ecad..010df4b 100644 --- a/chrome/common/child_process_logging.h +++ b/chrome/common/child_process_logging.h @@ -31,6 +31,11 @@ static const int kMaxReportedActiveExtensions = 10; // dependency. static const int kMaxReportedExperimentChunks = 15; +// The maximum size of an experiment chunk. This size was picked to be +// consistent between platforms and the value was chosen from the Windows +// limit of google_breakpad::CustomInfoEntry::kValueMaxLength. +static const size_t kMaxExperimentChunkSize = 64; + // The maximum number of prn-info-* records. static const size_t kMaxReportedPrinterRecords = 4; diff --git a/chrome/common/child_process_logging_mac.mm b/chrome/common/child_process_logging_mac.mm index 3c9ac6c..e514c87 100644 --- a/chrome/common/child_process_logging_mac.mm +++ b/chrome/common/child_process_logging_mac.mm @@ -13,6 +13,7 @@ #include "base/stringprintf.h" #include "base/sys_string_conversions.h" #include "base/utf_string_conversions.h" +#include "chrome/common/metrics/experiments_helper.h" #include "chrome/installer/util/google_update_settings.h" #include "content/public/common/gpu_info.h" #include "googleurl/src/gurl.h" @@ -220,8 +221,31 @@ void SetCommandLine(const CommandLine* command_line) { } } -void SetExperimentList(const std::vector<string16>& state) { - // TODO(mad): Implement this. +void SetExperimentList(const std::vector<string16>& experiments) { + // These should match the corresponding strings in breakpad_win.cc. + NSString* const kNumExperimentsKey = @"num-experiments"; + NSString* const kExperimentChunkFormat = @"experiment-chunk-%zu"; // 1-based. + + std::vector<string16> chunks; + experiments_helper::GenerateExperimentChunks(experiments, &chunks); + + // Store up to |kMaxReportedExperimentChunks| chunks. + for (size_t i = 0; i < kMaxReportedExperimentChunks; ++i) { + NSString* key = [NSString stringWithFormat:kExperimentChunkFormat, i + 1]; + if (i < chunks.size()) { + NSString* value = base::SysUTF16ToNSString(chunks[i]); + SetCrashKeyValue(key, value); + } else { + ClearCrashKey(key); + } + } + + // Make note of the total number of experiments, which may be greater than + // what was able to fit in |kMaxReportedExperimentChunks|. This is useful + // when correlating stability with the number of experiments running + // simultaneously. + SetCrashKeyValue(kNumExperimentsKey, + [NSString stringWithFormat:@"%zu", experiments.size()]); } void SetChannel(const std::string& channel) { diff --git a/chrome/common/metrics/experiments_helper.cc b/chrome/common/metrics/experiments_helper.cc index 3bc3aee..0fb6fa6 100644 --- a/chrome/common/metrics/experiments_helper.cc +++ b/chrome/common/metrics/experiments_helper.cc @@ -4,6 +4,7 @@ #include "chrome/common/metrics/experiments_helper.h" +#include <map> #include <vector> #include "base/memory/singleton.h" @@ -130,6 +131,25 @@ chrome_variations::ID GetGoogleVariationID(const std::string& trial_name, MakeSelectedGroupId(trial_name, group_name)); } +void GenerateExperimentChunks(const std::vector<string16>& experiments, + std::vector<string16>* chunks) { + string16 current_chunk; + for (size_t i = 0; i < experiments.size(); ++i) { + const size_t needed_length = + (current_chunk.empty() ? 1 : 0) + experiments[i].length(); + if (current_chunk.length() + needed_length > kMaxExperimentChunkSize) { + chunks->push_back(current_chunk); + current_chunk = experiments[i]; + } else { + if (!current_chunk.empty()) + current_chunk.push_back(','); + current_chunk += experiments[i]; + } + } + if (!current_chunk.empty()) + chunks->push_back(current_chunk); +} + void SetChildProcessLoggingExperimentList() { std::vector<SelectedGroupId> name_group_ids; GetFieldTrialSelectedGroupIds(&name_group_ids); diff --git a/chrome/common/metrics/experiments_helper.h b/chrome/common/metrics/experiments_helper.h index 71d1ed8..e821d4b 100644 --- a/chrome/common/metrics/experiments_helper.h +++ b/chrome/common/metrics/experiments_helper.h @@ -10,6 +10,7 @@ #include <vector> #include "base/metrics/field_trial.h" +#include "base/string16.h" #include "chrome/common/metrics/variation_ids.h" // This namespace provides various helpers that extend the functionality around @@ -101,6 +102,11 @@ void AssociateGoogleVariationIDForce(const std::string& trial_name, chrome_variations::ID GetGoogleVariationID(const std::string& trial_name, const std::string& group_name); +// Generates experiment chunks from |experiment_strings| that are suitable for +// crash reporting. +void GenerateExperimentChunks(const std::vector<string16>& experiment_strings, + std::vector<string16>* chunks); + // Get the current set of chosen FieldTrial groups (aka experiments) and send // them to the child process logging module so it can save it for crash dumps. void SetChildProcessLoggingExperimentList(); @@ -117,6 +123,6 @@ void TestGetFieldTrialSelectedGroupIdsForSelectedGroups( uint32 TestHashName(const std::string& name); -} +} // namespace testing #endif // CHROME_COMMON_METRICS_EXPERIMENTS_HELPER_H_ diff --git a/chrome/common/metrics/experiments_helper_unittest.cc b/chrome/common/metrics/experiments_helper_unittest.cc index b961a7d..268d25a 100644 --- a/chrome/common/metrics/experiments_helper_unittest.cc +++ b/chrome/common/metrics/experiments_helper_unittest.cc @@ -10,17 +10,19 @@ #include "base/message_loop.h" #include "base/metrics/field_trial.h" #include "base/time.h" +#include "base/utf_string_conversions.h" #include "chrome/common/metrics/experiments_helper.h" #include "content/public/test/test_browser_thread.h" #include "testing/gtest/include/gtest/gtest.h" +namespace experiments_helper { + namespace { // Convenience helper to retrieve the chrome_variations::ID for a FieldTrial. // Note that this will do the group assignment in |trial| if not already done. chrome_variations::ID GetIDForTrial(base::FieldTrial* trial) { - return experiments_helper::GetGoogleVariationID(trial->name(), - trial->group_name()); + return GetGoogleVariationID(trial->name(), trial->group_name()); } } // namespace @@ -72,8 +74,7 @@ TEST_F(ExperimentsHelperTest, HashName) { } TEST_F(ExperimentsHelperTest, GetFieldTrialSelectedGroups) { - typedef std::set<experiments_helper::SelectedGroupId, - experiments_helper::SelectedGroupIdCompare> SelectedGroupIdSet; + typedef std::set<SelectedGroupId, SelectedGroupIdCompare> SelectedGroupIdSet; std::string trial_one("trial one"); std::string group_one("group one"); std::string trial_two("trial two"); @@ -91,7 +92,7 @@ TEST_F(ExperimentsHelperTest, GetFieldTrialSelectedGroups) { // Create our expected groups of IDs. SelectedGroupIdSet expected_groups; - experiments_helper::SelectedGroupId name_group_id; + SelectedGroupId name_group_id; name_group_id.name = testing::TestHashName(trial_one); name_group_id.group = testing::TestHashName(group_one); expected_groups.insert(name_group_id); @@ -99,7 +100,7 @@ TEST_F(ExperimentsHelperTest, GetFieldTrialSelectedGroups) { name_group_id.group = testing::TestHashName(group_two); expected_groups.insert(name_group_id); - std::vector<experiments_helper::SelectedGroupId> selected_group_ids; + std::vector<SelectedGroupId> selected_group_ids; testing::TestGetFieldTrialSelectedGroupIdsForSelectedGroups( selected_groups, &selected_group_ids); EXPECT_EQ(2U, selected_group_ids.size()); @@ -137,9 +138,9 @@ TEST_F(ExperimentsHelperTest, DisableAfterInitialization) { base::FieldTrialList::FactoryGetFieldTrial("trial", 100, default_name, next_year_, 12, 12, NULL)); trial->AppendGroup(non_default_name, 100); - experiments_helper::AssociateGoogleVariationID( + AssociateGoogleVariationID( trial->name(), default_name, chrome_variations::kTestValueA); - experiments_helper::AssociateGoogleVariationID( + AssociateGoogleVariationID( trial->name(), non_default_name, chrome_variations::kTestValueB); ASSERT_EQ(non_default_name, trial->group_name()); ASSERT_EQ(chrome_variations::kTestValueB, GetIDForTrial(trial.get())); @@ -158,9 +159,9 @@ TEST_F(ExperimentsHelperTest, AssociateGoogleVariationID) { int winner_group = trial_true->AppendGroup(winner, 10); // Set GoogleVariationIDs so we can verify that they were chosen correctly. - experiments_helper::AssociateGoogleVariationID( + AssociateGoogleVariationID( trial_true->name(), default_name1, chrome_variations::kTestValueA); - experiments_helper::AssociateGoogleVariationID( + AssociateGoogleVariationID( trial_true->name(), winner, chrome_variations::kTestValueB); EXPECT_EQ(winner_group, trial_true->group()); @@ -174,9 +175,9 @@ TEST_F(ExperimentsHelperTest, AssociateGoogleVariationID) { const std::string loser = "ALoser"; int loser_group = trial_false->AppendGroup(loser, 0); - experiments_helper::AssociateGoogleVariationID( + AssociateGoogleVariationID( trial_false->name(), default_name2, chrome_variations::kTestValueA); - experiments_helper::AssociateGoogleVariationID( + AssociateGoogleVariationID( trial_false->name(), loser, chrome_variations::kTestValueB); EXPECT_NE(loser_group, trial_false->group()); @@ -203,17 +204,72 @@ TEST_F(ExperimentsHelperTest, NoAssociation) { // Ensure that the AssociateGoogleVariationIDForce works as expected. TEST_F(ExperimentsHelperTest, ForceAssociation) { EXPECT_EQ(chrome_variations::kEmptyID, - experiments_helper::GetGoogleVariationID("trial", "group")); - experiments_helper::AssociateGoogleVariationID("trial", "group", - chrome_variations::kTestValueA); + GetGoogleVariationID("trial", "group")); + AssociateGoogleVariationID("trial", "group", + chrome_variations::kTestValueA); EXPECT_EQ(chrome_variations::kTestValueA, - experiments_helper::GetGoogleVariationID("trial", "group")); - experiments_helper::AssociateGoogleVariationID("trial", "group", - chrome_variations::kTestValueB); + GetGoogleVariationID("trial", "group")); + AssociateGoogleVariationID("trial", "group", chrome_variations::kTestValueB); EXPECT_EQ(chrome_variations::kTestValueA, - experiments_helper::GetGoogleVariationID("trial", "group")); - experiments_helper::AssociateGoogleVariationIDForce("trial", "group", - chrome_variations::kTestValueB); + GetGoogleVariationID("trial", "group")); + AssociateGoogleVariationIDForce("trial", "group", + chrome_variations::kTestValueB); EXPECT_EQ(chrome_variations::kTestValueB, - experiments_helper::GetGoogleVariationID("trial", "group")); + GetGoogleVariationID("trial", "group")); } + +TEST_F(ExperimentsHelperTest, GenerateExperimentChunks) { + const char* kExperimentStrings[] = { + "1d3048f1-9de009d0", + "cd73da34-cf196cb", + "6214fa18-9e6dc24d", + "4dcb0cd6-d31c4ca1", + "9d5bce6-30d7d8ac", + }; + const char* kExpectedChunks1[] = { + "1d3048f1-9de009d0", + }; + const char* kExpectedChunks2[] = { + "1d3048f1-9de009d0,cd73da34-cf196cb", + }; + const char* kExpectedChunks3[] = { + "1d3048f1-9de009d0,cd73da34-cf196cb,6214fa18-9e6dc24d", + }; + const char* kExpectedChunks4[] = { + "1d3048f1-9de009d0,cd73da34-cf196cb,6214fa18-9e6dc24d", + "4dcb0cd6-d31c4ca1", + }; + const char* kExpectedChunks5[] = { + "1d3048f1-9de009d0,cd73da34-cf196cb,6214fa18-9e6dc24d", + "4dcb0cd6-d31c4ca1,9d5bce6-30d7d8ac", + }; + + struct { + size_t strings_length; + size_t expected_chunks_length; + const char** expected_chunks; + } cases[] = { + { 0, 0, NULL }, + { 1, arraysize(kExpectedChunks1), kExpectedChunks1 }, + { 2, arraysize(kExpectedChunks2), kExpectedChunks2 }, + { 3, arraysize(kExpectedChunks3), kExpectedChunks3 }, + { 4, arraysize(kExpectedChunks4), kExpectedChunks4 }, + { 5, arraysize(kExpectedChunks5), kExpectedChunks5 }, + }; + + for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); ++i) { + ASSERT_LE(cases[i].strings_length, arraysize(kExperimentStrings)); + + std::vector<string16> experiments; + for (size_t j = 0; j < cases[i].strings_length; ++j) + experiments.push_back(UTF8ToUTF16(kExperimentStrings[j])); + + std::vector<string16> chunks; + GenerateExperimentChunks(experiments, &chunks); + ASSERT_EQ(cases[i].expected_chunks_length, chunks.size()); + for (size_t j = 0; j < chunks.size(); ++j) + EXPECT_EQ(UTF8ToUTF16(cases[i].expected_chunks[j]), chunks[j]); + } +} + +} // namespace experiments_helper |