Skip to content

Commit

Permalink
Add metrics to track Policies' sources.
Browse files Browse the repository at this point in the history
Metrics track the management style of the device. Record if policies are
set from cloud or platform management.

Bug: 1316012
Change-Id: I002c539dea8d91a54cceefd6ee4679092ff18d46
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3601053
Reviewed-by: Yann Dago <ydago@chromium.org>
Commit-Queue: Owen Min <zmin@chromium.org>
Cr-Commit-Position: refs/heads/main@{#996876}
  • Loading branch information
Owen Min authored and Chromium LUCI CQ committed Apr 27, 2022
1 parent 8251a76 commit 90552bd
Show file tree
Hide file tree
Showing 5 changed files with 230 additions and 71 deletions.
118 changes: 93 additions & 25 deletions components/policy/core/common/policy_statistics_collector.cc
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@
#include "base/metrics/histogram_functions.h"
#include "base/notreached.h"
#include "base/task/task_runner.h"
#include "base/time/time.h"
#include "components/policy/core/common/cloud/enterprise_metrics.h"
#include "components/policy/core/common/policy_map.h"
#include "components/policy/core/common/policy_pref_names.h"
#include "components/policy/core/common/policy_service.h"
#include "components/policy/core/common/policy_types.h"
Expand All @@ -22,8 +25,71 @@

namespace policy {

const int PolicyStatisticsCollector::kStatisticsUpdateRate =
24 * 60 * 60 * 1000; // 24 hours.
namespace {

constexpr char kPoliciesSourceMetricsName[] = "Enterprise.Policies.Sources";

constexpr const char* kCBCMEnrollmentPolicies[] = {
"CloudManagementEnrollmentToken", "CloudManagementEnrollmentMandatory"};

enum SimplePolicySource {
kNone = 0,
kCloud = 1 << 0,
kPlatform = 1 << 1,
kMerge = kCloud | kPlatform,
kEnrollment = 1 << 2,
};

SimplePolicySource SimplifyPolicySource(PolicySource source,
const std::string& policy_name) {
switch (source) {
case POLICY_SOURCE_CLOUD:
case POLICY_SOURCE_CLOUD_FROM_ASH:
return kCloud;
case POLICY_SOURCE_PLATFORM:
case POLICY_SOURCE_ACTIVE_DIRECTORY:
// Adjust for enrollment policies which can never be set from cloud.
// Count them as cloud policy so that a device is considered as cloud
// managed even if there is enrollment token only.
for (const char* enrollment_policy : kCBCMEnrollmentPolicies) {
if (policy_name == enrollment_policy)
return kEnrollment;
}
return kPlatform;
case POLICY_SOURCE_MERGED:
return kMerge;
default:
// Other sources are only used for speicial cases and will not be counted.
return kNone;
}
}

void RecordPoliciesSources(SimplePolicySource source) {
if ((source & kMerge) == kMerge) {
base::UmaHistogramEnumeration(kPoliciesSourceMetricsName,
PoliciesSources::kHybrid);
} else if (source & kPlatform) {
base::UmaHistogramEnumeration(kPoliciesSourceMetricsName,
PoliciesSources::kPlatformOnly);
} else if (source & kCloud) {
if (source & kEnrollment) {
base::UmaHistogramEnumeration(
kPoliciesSourceMetricsName,
PoliciesSources::kCloudOnlyExceptEnrollment);
} else {
base::UmaHistogramEnumeration(kPoliciesSourceMetricsName,
PoliciesSources::kCloudOnly);
}
} else if (source & kEnrollment) {
base::UmaHistogramEnumeration(kPoliciesSourceMetricsName,
PoliciesSources::kEnrollmentOnly);
}
}

} // namespace

const base::TimeDelta PolicyStatisticsCollector::kStatisticsUpdateRate =
base::Days(1);

PolicyStatisticsCollector::PolicyStatisticsCollector(
const GetChromePolicyDetailsCallback& get_details,
Expand All @@ -35,22 +101,19 @@ PolicyStatisticsCollector::PolicyStatisticsCollector(
chrome_schema_(chrome_schema),
policy_service_(policy_service),
prefs_(prefs),
task_runner_(task_runner) {
}
task_runner_(task_runner) {}

PolicyStatisticsCollector::~PolicyStatisticsCollector() {
}
PolicyStatisticsCollector::~PolicyStatisticsCollector() = default;

void PolicyStatisticsCollector::Initialize() {
using base::Time;

base::TimeDelta update_rate = base::Milliseconds(kStatisticsUpdateRate);
Time last_update = prefs_->GetTime(policy_prefs::kLastPolicyStatisticsUpdate);
base::TimeDelta delay = std::max(Time::Now() - last_update, base::Days(0));
if (delay >= update_rate)
base::Time last_update =
prefs_->GetTime(policy_prefs::kLastPolicyStatisticsUpdate);
base::TimeDelta delay =
std::max(base::Time::Now() - last_update, base::TimeDelta());
if (delay >= kStatisticsUpdateRate)
CollectStatistics();
else
ScheduleUpdate(update_rate - delay);
ScheduleUpdate(kStatisticsUpdateRate - delay);
}

// static
Expand Down Expand Up @@ -80,22 +143,25 @@ void PolicyStatisticsCollector::CollectStatistics() {
const PolicyMap& policies = policy_service_->GetPolicies(
PolicyNamespace(POLICY_DOMAIN_CHROME, std::string()));

int source = kNone;
// Collect statistics.
for (Schema::Iterator it(chrome_schema_.GetPropertiesIterator());
!it.IsAtEnd(); it.Advance()) {
if (policies.Get(it.key())) {
const PolicyDetails* details = get_details_.Run(it.key());
if (details) {
RecordPolicyUse(details->id, kDefault);
if (policies.Get(it.key())->level == POLICY_LEVEL_MANDATORY) {
RecordPolicyUse(details->id, kMandatory);
} else {
RecordPolicyUse(details->id, kRecommended);
}
const PolicyMap::Entry* policy_entry = policies.Get(it.key());
if (!policy_entry)
continue;
const PolicyDetails* details = get_details_.Run(it.key());
if (details) {
RecordPolicyUse(details->id, kDefault);
if (policies.Get(it.key())->level == POLICY_LEVEL_MANDATORY) {
RecordPolicyUse(details->id, kMandatory);
} else {
NOTREACHED();
RecordPolicyUse(details->id, kRecommended);
}
} else {
NOTREACHED();
}
source |= SimplifyPolicySource(policy_entry->source, it.key());
}

for (size_t i = 0; i < kPolicyAtomicGroupMappingsLength; ++i) {
Expand All @@ -114,9 +180,11 @@ void PolicyStatisticsCollector::CollectStatistics() {
}
}

RecordPoliciesSources(static_cast<SimplePolicySource>(source));

// Take care of next update.
prefs_->SetTime(policy_prefs::kLastPolicyStatisticsUpdate, base::Time::Now());
ScheduleUpdate(base::Milliseconds(kStatisticsUpdateRate));
ScheduleUpdate(kStatisticsUpdateRate);
}

void PolicyStatisticsCollector::ScheduleUpdate(base::TimeDelta delay) {
Expand All @@ -125,4 +193,4 @@ void PolicyStatisticsCollector::ScheduleUpdate(base::TimeDelta delay) {
task_runner_->PostDelayedTask(FROM_HERE, update_callback_.callback(), delay);
}

} // namespace policy
} // namespace policy
18 changes: 12 additions & 6 deletions components/policy/core/common/policy_statistics_collector.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,20 @@ enum Condition {
kIgnoredByAtomicGroup,
};

enum class PoliciesSources {
kCloudOnly = 0,
kCloudOnlyExceptEnrollment = 1,
kPlatformOnly = 2,
kHybrid = 3,
kEnrollmentOnly = 4,
kMaxValue = kEnrollmentOnly,
};

// Manages regular updates of policy usage UMA histograms.
class POLICY_EXPORT PolicyStatisticsCollector {
public:
// Policy usage statistics update rate, in milliseconds.
static const int kStatisticsUpdateRate;
static const base::TimeDelta kStatisticsUpdateRate;

// Neither |policy_service| nor |prefs| can be NULL and must stay valid
// throughout the lifetime of PolicyStatisticsCollector.
Expand All @@ -55,11 +64,8 @@ class POLICY_EXPORT PolicyStatisticsCollector {

static void RegisterPrefs(PrefRegistrySimple* registry);

protected:
// protected virtual for mocking.
virtual void RecordPolicyUse(int id, Condition condition);

private:
void RecordPolicyUse(int id, Condition condition);
void CollectStatistics();
void ScheduleUpdate(base::TimeDelta delay);

Expand All @@ -75,4 +81,4 @@ class POLICY_EXPORT PolicyStatisticsCollector {

} // namespace policy

#endif // COMPONENTS_POLICY_CORE_COMMON_POLICY_STATISTICS_COLLECTOR_H_
#endif // COMPONENTS_POLICY_CORE_COMMON_POLICY_STATISTICS_COLLECTOR_H_
Loading

0 comments on commit 90552bd

Please sign in to comment.