Commit ee8e7062 authored by holte's avatar holte Committed by Commit bot

Create a mechanism for reporting rappor metrics from non-UMA

users.

BUG=418242

Review URL: https://codereview.chromium.org/509203002

Cr-Commit-Position: refs/heads/master@{#302682}
parent 3fba1a6a
...@@ -51,8 +51,9 @@ class TestRapporService : public rappor::RapporService { ...@@ -51,8 +51,9 @@ class TestRapporService : public rappor::RapporService {
TestRapporService::TestRapporService() TestRapporService::TestRapporService()
: rappor::RapporService(&prefs_) { : rappor::RapporService(&prefs_) {
// Initialize the RapporService for testing. // Initialize the RapporService for testing.
SetCohortForTesting(0); Initialize(0,
SetSecretForTesting(rappor::HmacByteVectorGenerator::GenerateEntropyInput()); rappor::HmacByteVectorGenerator::GenerateEntropyInput(),
rappor::FINE_LEVEL);
} }
TestRapporService::~TestRapporService() {} TestRapporService::~TestRapporService() {}
......
...@@ -21,6 +21,9 @@ RapporMetric::RapporMetric(const std::string& metric_name, ...@@ -21,6 +21,9 @@ RapporMetric::RapporMetric(const std::string& metric_name,
parameters.bloom_filter_hash_function_count) { parameters.bloom_filter_hash_function_count) {
DCHECK_GE(cohort_seed, 0); DCHECK_GE(cohort_seed, 0);
DCHECK_LT(cohort_seed, RapporParameters::kMaxCohorts); DCHECK_LT(cohort_seed, RapporParameters::kMaxCohorts);
// Since cohort_seed is in the range [0, kMaxCohorts), num_cohorts should
// divide kMaxCohorts for each cohort to have equal weight.
DCHECK_EQ(0, RapporParameters::kMaxCohorts % parameters.num_cohorts);
} }
RapporMetric::~RapporMetric() {} RapporMetric::~RapporMetric() {}
......
...@@ -19,7 +19,8 @@ const RapporParameters kTestRapporParameters = { ...@@ -19,7 +19,8 @@ const RapporParameters kTestRapporParameters = {
PROBABILITY_75 /* Fake data probability */, PROBABILITY_75 /* Fake data probability */,
PROBABILITY_50 /* Fake one probability */, PROBABILITY_50 /* Fake one probability */,
PROBABILITY_75 /* One coin probability */, PROBABILITY_75 /* One coin probability */,
PROBABILITY_50 /* Zero coin probability */}; PROBABILITY_50 /* Zero coin probability */,
FINE_LEVEL /* Reporting level (not used) */};
const RapporParameters kTestStatsRapporParameters = { const RapporParameters kTestStatsRapporParameters = {
1 /* Num cohorts */, 1 /* Num cohorts */,
...@@ -28,7 +29,8 @@ const RapporParameters kTestStatsRapporParameters = { ...@@ -28,7 +29,8 @@ const RapporParameters kTestStatsRapporParameters = {
PROBABILITY_75 /* Fake data probability */, PROBABILITY_75 /* Fake data probability */,
PROBABILITY_50 /* Fake one probability */, PROBABILITY_50 /* Fake one probability */,
PROBABILITY_75 /* One coin probability */, PROBABILITY_75 /* One coin probability */,
PROBABILITY_50 /* Zero coin probability */}; PROBABILITY_50 /* Zero coin probability */,
FINE_LEVEL /* Reporting level (not used) */};
// Check for basic syntax and use. // Check for basic syntax and use.
TEST(RapporMetricTest, BasicMetric) { TEST(RapporMetricTest, BasicMetric) {
......
...@@ -10,14 +10,15 @@ ...@@ -10,14 +10,15 @@
namespace rappor { namespace rappor {
std::string RapporParameters::ToString() const { std::string RapporParameters::ToString() const {
return base::StringPrintf("{ %d, %d, %d, %d, %d, %d, %d }", return base::StringPrintf("{ %d, %d, %d, %d, %d, %d, %d, %d }",
num_cohorts, num_cohorts,
bloom_filter_size_bytes, bloom_filter_size_bytes,
bloom_filter_hash_function_count, bloom_filter_hash_function_count,
fake_prob, fake_prob,
fake_one_prob, fake_one_prob,
one_coin_prob, one_coin_prob,
zero_coin_prob); zero_coin_prob,
reporting_level);
} }
const int RapporParameters::kMaxCohorts = 512; const int RapporParameters::kMaxCohorts = 512;
......
...@@ -15,6 +15,18 @@ enum Probability { ...@@ -15,6 +15,18 @@ enum Probability {
PROBABILITY_25, // 25% PROBABILITY_25, // 25%
}; };
// A metric is reported when it's reporting level is >= the reporting level
// passed in to RapporService::Start()
enum ReportingLevel {
// No metrics are reported at this level.
REPORTING_DISABLED = 0,
// Metrics suitable for broader populations.
COARSE_LEVEL,
// Metrics suitable for UMA opt-in users.
FINE_LEVEL,
};
// An object describing a rappor metric and the parameters used to generate it. // An object describing a rappor metric and the parameters used to generate it.
// //
// For a full description of the rappor metrics, see // For a full description of the rappor metrics, see
...@@ -27,6 +39,8 @@ struct RapporParameters { ...@@ -27,6 +39,8 @@ struct RapporParameters {
static const int kMaxCohorts; static const int kMaxCohorts;
// The number of cohorts to divide the reports for this metric into. // The number of cohorts to divide the reports for this metric into.
// This should divide kMaxCohorts evenly so that each cohort has an equal
// probability of being assigned users.
int num_cohorts; int num_cohorts;
// The number of bytes stored in the Bloom filter. // The number of bytes stored in the Bloom filter.
...@@ -43,6 +57,9 @@ struct RapporParameters { ...@@ -43,6 +57,9 @@ struct RapporParameters {
Probability one_coin_prob; Probability one_coin_prob;
// The probability that a zero bit in the redacted data reports as one. // The probability that a zero bit in the redacted data reports as one.
Probability zero_coin_prob; Probability zero_coin_prob;
// The reporting level this metric is reported at.
ReportingLevel reporting_level;
}; };
} // namespace rappor } // namespace rappor
......
...@@ -37,18 +37,10 @@ const char kRapporRolloutFieldTrialName[] = "RapporRollout"; ...@@ -37,18 +37,10 @@ const char kRapporRolloutFieldTrialName[] = "RapporRollout";
// Constant for the finch parameter name for the server URL // Constant for the finch parameter name for the server URL
const char kRapporRolloutServerUrlParam[] = "ServerUrl"; const char kRapporRolloutServerUrlParam[] = "ServerUrl";
// Constant for the finch parameter name for the server URL
const char kRapporRolloutRequireUmaParam[] = "RequireUma";
// The rappor server's URL. // The rappor server's URL.
const char kDefaultServerUrl[] = "https://clients4.google.com/rappor"; const char kDefaultServerUrl[] = "https://clients4.google.com/rappor";
GURL GetServerUrl(bool metrics_enabled) { GURL GetServerUrl() {
bool require_uma = variations::GetVariationParamValue(
kRapporRolloutFieldTrialName,
kRapporRolloutRequireUmaParam) != "False";
if (!metrics_enabled && require_uma)
return GURL(); // Invalid URL disables Rappor.
std::string server_url = variations::GetVariationParamValue( std::string server_url = variations::GetVariationParamValue(
kRapporRolloutFieldTrialName, kRapporRolloutFieldTrialName,
kRapporRolloutServerUrlParam); kRapporRolloutServerUrlParam);
...@@ -66,7 +58,17 @@ const RapporParameters kRapporParametersForType[NUM_RAPPOR_TYPES] = { ...@@ -66,7 +58,17 @@ const RapporParameters kRapporParametersForType[NUM_RAPPOR_TYPES] = {
rappor::PROBABILITY_50 /* Fake data probability */, rappor::PROBABILITY_50 /* Fake data probability */,
rappor::PROBABILITY_50 /* Fake one probability */, rappor::PROBABILITY_50 /* Fake one probability */,
rappor::PROBABILITY_75 /* One coin probability */, rappor::PROBABILITY_75 /* One coin probability */,
rappor::PROBABILITY_25 /* Zero coin probability */}, rappor::PROBABILITY_25 /* Zero coin probability */,
FINE_LEVEL /* Reporting level */},
// COARSE_RAPPOR_TYPE
{128 /* Num cohorts */,
1 /* Bloom filter size bytes */,
2 /* Bloom filter hash count */,
rappor::PROBABILITY_50 /* Fake data probability */,
rappor::PROBABILITY_50 /* Fake one probability */,
rappor::PROBABILITY_75 /* One coin probability */,
rappor::PROBABILITY_25 /* Zero coin probability */,
COARSE_LEVEL /* Reporting level */},
}; };
} // namespace } // namespace
...@@ -75,8 +77,9 @@ RapporService::RapporService(PrefService* pref_service) ...@@ -75,8 +77,9 @@ RapporService::RapporService(PrefService* pref_service)
: pref_service_(pref_service), : pref_service_(pref_service),
cohort_(-1), cohort_(-1),
daily_event_(pref_service, daily_event_(pref_service,
prefs::kRapporLastDailySample, prefs::kRapporLastDailySample,
kRapporDailyEventHistogram) { kRapporDailyEventHistogram),
reporting_level_(REPORTING_DISABLED) {
} }
RapporService::~RapporService() { RapporService::~RapporService() {
...@@ -90,16 +93,22 @@ void RapporService::AddDailyObserver( ...@@ -90,16 +93,22 @@ void RapporService::AddDailyObserver(
void RapporService::Start(net::URLRequestContextGetter* request_context, void RapporService::Start(net::URLRequestContextGetter* request_context,
bool metrics_enabled) { bool metrics_enabled) {
const GURL server_url = GetServerUrl(metrics_enabled); const GURL server_url = GetServerUrl();
if (!server_url.is_valid()) { if (!server_url.is_valid()) {
DVLOG(1) << server_url.spec() << " is invalid. " DVLOG(1) << server_url.spec() << " is invalid. "
<< "RapporService not started."; << "RapporService not started.";
return; return;
} }
// TODO(holte): Consider moving this logic once we've determined the
// conditions for COARSE metrics.
ReportingLevel reporting_level = metrics_enabled ?
FINE_LEVEL : REPORTING_DISABLED;
DVLOG(1) << "RapporService reporting_level_? " << reporting_level;
if (reporting_level <= REPORTING_DISABLED)
return;
DVLOG(1) << "RapporService started. Reporting to " << server_url.spec(); DVLOG(1) << "RapporService started. Reporting to " << server_url.spec();
DCHECK(!uploader_); DCHECK(!uploader_);
LoadSecret(); Initialize(LoadCohort(), LoadSecret(), reporting_level_);
LoadCohort();
uploader_.reset(new LogUploader(server_url, kMimeType, request_context)); uploader_.reset(new LogUploader(server_url, kMimeType, request_context));
log_rotation_timer_.Start( log_rotation_timer_.Start(
FROM_HERE, FROM_HERE,
...@@ -108,6 +117,16 @@ void RapporService::Start(net::URLRequestContextGetter* request_context, ...@@ -108,6 +117,16 @@ void RapporService::Start(net::URLRequestContextGetter* request_context,
&RapporService::OnLogInterval); &RapporService::OnLogInterval);
} }
void RapporService::Initialize(int32_t cohort,
const std::string& secret,
const ReportingLevel& reporting_level) {
DCHECK(!IsInitialized());
DCHECK(secret_.empty());
cohort_ = cohort;
secret_ = secret;
reporting_level_ = reporting_level;
}
void RapporService::OnLogInterval() { void RapporService::OnLogInterval() {
DCHECK(uploader_); DCHECK(uploader_);
DVLOG(2) << "RapporService::OnLogInterval"; DVLOG(2) << "RapporService::OnLogInterval";
...@@ -136,39 +155,40 @@ void RapporService::RegisterPrefs(PrefRegistrySimple* registry) { ...@@ -136,39 +155,40 @@ void RapporService::RegisterPrefs(PrefRegistrySimple* registry) {
prefs::kRapporLastDailySample); prefs::kRapporLastDailySample);
} }
void RapporService::LoadCohort() { int32_t RapporService::LoadCohort() {
DCHECK(!IsInitialized());
// Ignore and delete old cohort parameter. // Ignore and delete old cohort parameter.
pref_service_->ClearPref(prefs::kRapporCohortDeprecated); pref_service_->ClearPref(prefs::kRapporCohortDeprecated);
cohort_ = pref_service_->GetInteger(prefs::kRapporCohortSeed); int32_t cohort = pref_service_->GetInteger(prefs::kRapporCohortSeed);
// If the user is already assigned to a valid cohort, we're done. // If the user is already assigned to a valid cohort, we're done.
if (cohort_ >= 0 && cohort_ < RapporParameters::kMaxCohorts) if (cohort >= 0 && cohort < RapporParameters::kMaxCohorts)
return; return cohort;
// This is the first time the client has started the service (or their // This is the first time the client has started the service (or their
// preferences were corrupted). Randomly assign them to a cohort. // preferences were corrupted). Randomly assign them to a cohort.
cohort_ = base::RandGenerator(RapporParameters::kMaxCohorts); cohort = base::RandGenerator(RapporParameters::kMaxCohorts);
DVLOG(2) << "Selected a new Rappor cohort: " << cohort_; DVLOG(2) << "Selected a new Rappor cohort: " << cohort;
pref_service_->SetInteger(prefs::kRapporCohortSeed, cohort_); pref_service_->SetInteger(prefs::kRapporCohortSeed, cohort);
return cohort;
} }
void RapporService::LoadSecret() { std::string RapporService::LoadSecret() {
DCHECK(secret_.empty()); std::string secret;
std::string secret_base64 = pref_service_->GetString(prefs::kRapporSecret); std::string secret_base64 = pref_service_->GetString(prefs::kRapporSecret);
if (!secret_base64.empty()) { if (!secret_base64.empty()) {
bool decoded = base::Base64Decode(secret_base64, &secret_); bool decoded = base::Base64Decode(secret_base64, &secret);
if (decoded && secret_.size() == HmacByteVectorGenerator::kEntropyInputSize) if (decoded && secret_.size() == HmacByteVectorGenerator::kEntropyInputSize)
return; return secret;
// If the preference fails to decode, or is the wrong size, it must be // If the preference fails to decode, or is the wrong size, it must be
// corrupt, so continue as though it didn't exist yet and generate a new // corrupt, so continue as though it didn't exist yet and generate a new
// one. // one.
} }
DVLOG(2) << "Generated a new Rappor secret."; DVLOG(2) << "Generated a new Rappor secret.";
secret_ = HmacByteVectorGenerator::GenerateEntropyInput(); secret = HmacByteVectorGenerator::GenerateEntropyInput();
base::Base64Encode(secret_, &secret_base64); base::Base64Encode(secret, &secret_base64);
pref_service_->SetString(prefs::kRapporSecret, secret_base64); pref_service_->SetString(prefs::kRapporSecret, secret_base64);
return secret;
} }
bool RapporService::ExportMetrics(RapporReports* reports) { bool RapporService::ExportMetrics(RapporReports* reports) {
...@@ -203,16 +223,21 @@ void RapporService::RecordSample(const std::string& metric_name, ...@@ -203,16 +223,21 @@ void RapporService::RecordSample(const std::string& metric_name,
if (!IsInitialized()) if (!IsInitialized())
return; return;
DCHECK_LT(type, NUM_RAPPOR_TYPES); DCHECK_LT(type, NUM_RAPPOR_TYPES);
const RapporParameters& parameters = kRapporParametersForType[type];
DVLOG(2) << "Recording sample \"" << sample DVLOG(2) << "Recording sample \"" << sample
<< "\" for metric \"" << metric_name << "\" for metric \"" << metric_name
<< "\" of type: " << type; << "\" of type: " << type;
RecordSampleInternal(metric_name, kRapporParametersForType[type], sample); RecordSampleInternal(metric_name, parameters, sample);
} }
void RapporService::RecordSampleInternal(const std::string& metric_name, void RapporService::RecordSampleInternal(const std::string& metric_name,
const RapporParameters& parameters, const RapporParameters& parameters,
const std::string& sample) { const std::string& sample) {
DCHECK(IsInitialized()); DCHECK(IsInitialized());
// Skip this metric if it's reporting level is less than the enabled
// reporting level.
if (reporting_level_ < parameters.reporting_level)
return;
RapporMetric* metric = LookUpMetric(metric_name, parameters); RapporMetric* metric = LookUpMetric(metric_name, parameters);
metric->AddSample(sample); metric->AddSample(sample);
} }
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include "base/memory/scoped_ptr.h" #include "base/memory/scoped_ptr.h"
#include "base/timer/timer.h" #include "base/timer/timer.h"
#include "components/metrics/daily_event.h" #include "components/metrics/daily_event.h"
#include "components/rappor/rappor_parameters.h"
class PrefRegistrySimple; class PrefRegistrySimple;
class PrefService; class PrefService;
...@@ -26,12 +27,12 @@ namespace rappor { ...@@ -26,12 +27,12 @@ namespace rappor {
class LogUploader; class LogUploader;
class RapporMetric; class RapporMetric;
class RapporReports; class RapporReports;
struct RapporParameters;
// The type of data stored in a metric. // The type of data stored in a metric.
enum RapporType { enum RapporType {
// For sampling the eTLD+1 of a URL. // For sampling the eTLD+1 of a URL.
ETLD_PLUS_ONE_RAPPOR_TYPE = 0, ETLD_PLUS_ONE_RAPPOR_TYPE = 0,
COARSE_RAPPOR_TYPE,
NUM_RAPPOR_TYPES NUM_RAPPOR_TYPES
}; };
...@@ -49,6 +50,7 @@ class RapporService { ...@@ -49,6 +50,7 @@ class RapporService {
void AddDailyObserver(scoped_ptr<metrics::DailyEvent::Observer> observer); void AddDailyObserver(scoped_ptr<metrics::DailyEvent::Observer> observer);
// Starts the periodic generation of reports and upload attempts. // Starts the periodic generation of reports and upload attempts.
// |metrics enabled| should be true if UMA users have opted in.
void Start(net::URLRequestContextGetter* context, void Start(net::URLRequestContextGetter* context,
bool metrics_enabled); bool metrics_enabled);
...@@ -58,25 +60,24 @@ class RapporService { ...@@ -58,25 +60,24 @@ class RapporService {
RapporType type, RapporType type,
const std::string& sample); const std::string& sample);
// Sets the cohort value. For use by tests only.
void SetCohortForTesting(uint32_t cohort) { cohort_ = cohort; }
// Sets the secret value. For use by tests only.
void SetSecretForTesting(const std::string& secret) { secret_ = secret; }
// Registers the names of all of the preferences used by RapporService in the // Registers the names of all of the preferences used by RapporService in the
// provided PrefRegistry. This should be called before calling Start(). // provided PrefRegistry. This should be called before calling Start().
static void RegisterPrefs(PrefRegistrySimple* registry); static void RegisterPrefs(PrefRegistrySimple* registry);
protected: protected:
// Initializes the state of the RapporService.
void Initialize(int32_t cohort,
const std::string& secret,
const ReportingLevel& reporting_level);
// Retrieves the cohort number this client was assigned to, generating it if // Retrieves the cohort number this client was assigned to, generating it if
// doesn't already exist. The cohort should be persistent. // doesn't already exist. The cohort should be persistent.
void LoadCohort(); int32_t LoadCohort();
// Retrieves the value for secret_ from preferences, generating it if doesn't // Retrieves the value for secret_ from preferences, generating it if doesn't
// already exist. The secret should be persistent, so that additional bits // already exist. The secret should be persistent, so that additional bits
// from the client do not get exposed over time. // from the client do not get exposed over time.
void LoadSecret(); std::string LoadSecret();
// Logs all of the collected metrics to the reports proto message and clears // Logs all of the collected metrics to the reports proto message and clears
// the internal map. Exposed for tests. Returns true if any metrics were // the internal map. Exposed for tests. Returns true if any metrics were
...@@ -121,6 +122,9 @@ class RapporService { ...@@ -121,6 +122,9 @@ class RapporService {
// A private LogUploader instance for sending reports to the server. // A private LogUploader instance for sending reports to the server.
scoped_ptr<LogUploader> uploader_; scoped_ptr<LogUploader> uploader_;
// What reporting level of metrics are being reported.
ReportingLevel reporting_level_;
// We keep all registered metrics in a map, from name to metric. // We keep all registered metrics in a map, from name to metric.
// The map owns the metrics it contains. // The map owns the metrics it contains.
std::map<std::string, RapporMetric*> metrics_map_; std::map<std::string, RapporMetric*> metrics_map_;
......
...@@ -16,34 +16,53 @@ namespace rappor { ...@@ -16,34 +16,53 @@ namespace rappor {
class TestRapporService : public RapporService { class TestRapporService : public RapporService {
public: public:
TestRapporService() : RapporService(&prefs_) { TestRapporService(ReportingLevel reporting_level) : RapporService(&prefs) {
RegisterPrefs(prefs_.registry()); RegisterPrefs(prefs.registry());
prefs_.SetInteger(prefs::kRapporCohortSeed, 0); Initialize(0,
std::string secret = HmacByteVectorGenerator::GenerateEntropyInput(); HmacByteVectorGenerator::GenerateEntropyInput(),
std::string secret_base64; reporting_level);
base::Base64Encode(secret, &secret_base64);
prefs_.SetString(prefs::kRapporSecret, secret_base64);
LoadCohort();
LoadSecret();
} }
void GetReports(RapporReports* reports) { void GetReports(RapporReports* reports) {
ExportMetrics(reports); ExportMetrics(reports);
} }
int32_t TestLoadCohort() {
return LoadCohort();
}
std::string TestLoadSecret() {
return LoadSecret();
}
void TestRecordSample(const std::string& metric_name, void TestRecordSample(const std::string& metric_name,
const RapporParameters& parameters, const RapporParameters& parameters,
const std::string& sample) { const std::string& sample) {
RecordSampleInternal(metric_name, parameters, sample); RecordSampleInternal(metric_name, parameters, sample);
} }
protected: TestingPrefServiceSimple prefs;
TestingPrefServiceSimple prefs_;
private: private:
DISALLOW_COPY_AND_ASSIGN(TestRapporService); DISALLOW_COPY_AND_ASSIGN(TestRapporService);
}; };
TEST(RapporServiceTest, LoadCohort) {
TestRapporService rappor_service(REPORTING_DISABLED);
rappor_service.prefs.SetInteger(prefs::kRapporCohortSeed, 1);
EXPECT_EQ(1, rappor_service.TestLoadCohort());
}
TEST(RapporServiceTest, LoadSecret) {
TestRapporService rappor_service(REPORTING_DISABLED);
std::string secret = HmacByteVectorGenerator::GenerateEntropyInput();
std::string secret_base64;
base::Base64Encode(secret, &secret_base64);
rappor_service.prefs.SetString(prefs::kRapporSecret, secret_base64);
EXPECT_EQ(secret, rappor_service.TestLoadSecret());
}
// Check that samples can be recorded and exported.
TEST(RapporServiceTest, RecordAndExportMetrics) { TEST(RapporServiceTest, RecordAndExportMetrics) {
const RapporParameters kTestRapporParameters = { const RapporParameters kTestRapporParameters = {
1 /* Num cohorts */, 1 /* Num cohorts */,
...@@ -52,10 +71,12 @@ TEST(RapporServiceTest, RecordAndExportMetrics) { ...@@ -52,10 +71,12 @@ TEST(RapporServiceTest, RecordAndExportMetrics) {
PROBABILITY_75 /* Fake data probability */, PROBABILITY_75 /* Fake data probability */,
PROBABILITY_50 /* Fake one probability */, PROBABILITY_50 /* Fake one probability */,
PROBABILITY_75 /* One coin probability */, PROBABILITY_75 /* One coin probability */,
PROBABILITY_50 /* Zero coin probability */}; PROBABILITY_50 /* Zero coin probability */,
COARSE_LEVEL};
TestRapporService rappor_service; TestRapporService rappor_service(COARSE_LEVEL);
// Multiple samples for the same metric should only generate one report.
rappor_service.TestRecordSample("MyMetric", kTestRapporParameters, "foo"); rappor_service.TestRecordSample("MyMetric", kTestRapporParameters, "foo");
rappor_service.TestRecordSample("MyMetric", kTestRapporParameters, "bar"); rappor_service.TestRecordSample("MyMetric", kTestRapporParameters, "bar");
...@@ -68,4 +89,25 @@ TEST(RapporServiceTest, RecordAndExportMetrics) { ...@@ -68,4 +89,25 @@ TEST(RapporServiceTest, RecordAndExportMetrics) {
EXPECT_EQ(16u, report.bits().size()); EXPECT_EQ(16u, report.bits().size());
} }
// Check that the reporting level is respected.
TEST(RapporServiceTest, ReportingLevel) {
const RapporParameters kFineRapporParameters = {
1 /* Num cohorts */,
16 /* Bloom filter size bytes */,
4 /* Bloom filter hash count */,
PROBABILITY_75 /* Fake data probability */,
PROBABILITY_50 /* Fake one probability */,
PROBABILITY_75 /* One coin probability */,
PROBABILITY_50 /* Zero coin probability */,
FINE_LEVEL};
TestRapporService rappor_service(COARSE_LEVEL);
rappor_service.TestRecordSample("FineMetric", kFineRapporParameters, "foo");
RapporReports reports;
rappor_service.GetReports(&reports);
EXPECT_EQ(0, reports.report_size());
}
} // namespace rappor } // namespace rappor
...@@ -15,6 +15,46 @@ TODO(holte): Add validation and pretty printing scripts. ...@@ -15,6 +15,46 @@ TODO(holte): Add validation and pretty printing scripts.
<rappor-configuration> <rappor-configuration>
<!--
Parameters that rappor metrics can be collected with. This list should be
kept in sync with parameter type definitions in
components/rappor/rappor_service.cc.
-->
<rappor-parameter-types>
<rappor-parameters name="ETLD_PLUS_ONE">
<summary>
Parameters suitable for collecting the domain and registry of a URL from
UMA opt-in users.
</summary>
<parameters num-cohorts="128"
bytes="16"
hash-functions="2"
fake-prob=".5"
fake-one-prob=".5"
one-coin-prob=".75"
zero-coin-prob=".25"
reporting-level="FINE">
</parameters>
</rappor-parameters>
<rappor-parameters name="COARSE_RAPPOR_TYPE">
<summary>
Stricter parameters for metrics collected from a broader population.
</summary>
<parameters num-cohorts="128"
bytes="1"
hash-functions="2"
fake-prob=".5"
fake-one-prob=".5"
one-coin-prob=".75"
zero-coin-prob=".25"
reporting-level="COARSE">
</rappor-parameters>
</rappor-parameter-types>
<!-- Rappor metric definitions --> <!-- Rappor metric definitions -->
<rappor-metrics> <rappor-metrics>
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment