summaryrefslogtreecommitdiffstats
path: root/chrome/common
diff options
context:
space:
mode:
authorasvitkine@chromium.org <asvitkine@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-06-29 17:54:13 +0000
committerasvitkine@chromium.org <asvitkine@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-06-29 17:54:13 +0000
commit38b80bbab9db5a423cace41e4e7757eb4f27806c (patch)
tree83b55813af588337a42140b19df8bd5feaa6df5a /chrome/common
parent24664d6766ccc67c52034913f57ba168490b2571 (diff)
downloadchromium_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.h5
-rw-r--r--chrome/common/child_process_logging_mac.mm28
-rw-r--r--chrome/common/metrics/experiments_helper.cc20
-rw-r--r--chrome/common/metrics/experiments_helper.h8
-rw-r--r--chrome/common/metrics/experiments_helper_unittest.cc100
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