Commit 3880edde authored by Steven Holte's avatar Steven Holte Committed by Commit Bot

Create an opaque type for UKM SourceIds.

Bug: 873866
Change-Id: I260aaf9bb1b7162e651d09595231b565d56c1958
Reviewed-on: https://chromium-review.googlesource.com/1173022Reviewed-by: default avatarYaron Friedman <yfriedman@chromium.org>
Reviewed-by: default avatarRobert Kaplow (slow) <rkaplow@chromium.org>
Commit-Queue: Steven Holte <holte@chromium.org>
Cr-Commit-Position: refs/heads/master@{#583897}
parent 7a4a5b1b
...@@ -617,6 +617,8 @@ jumbo_component("base") { ...@@ -617,6 +617,8 @@ jumbo_component("base") {
"metrics/sparse_histogram.h", "metrics/sparse_histogram.h",
"metrics/statistics_recorder.cc", "metrics/statistics_recorder.cc",
"metrics/statistics_recorder.h", "metrics/statistics_recorder.h",
"metrics/ukm_source_id.cc",
"metrics/ukm_source_id.h",
"metrics/user_metrics.cc", "metrics/user_metrics.cc",
"metrics/user_metrics.h", "metrics/user_metrics.h",
"metrics/user_metrics_action.h", "metrics/user_metrics_action.h",
......
// Copyright 2018 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 "base/metrics/ukm_source_id.h"
#include "base/atomic_sequence_num.h"
#include "base/logging.h"
#include "base/rand_util.h"
namespace base {
namespace {
const int64_t kLowBitsMask = (INT64_C(1) << 32) - 1;
const int64_t kNumTypeBits = 2;
const int64_t kTypeMask = (INT64_C(1) << kNumTypeBits) - 1;
} // namespace
// static
UkmSourceId UkmSourceId::New() {
// Generate some bits which are unique to this process, so we can generate
// IDs independently in different processes. IDs generated by this method may
// collide, but it should be sufficiently rare enough to not impact data
// quality.
const static int64_t process_id_bits =
static_cast<int64_t>(RandUint64()) & ~kLowBitsMask;
// Generate some bits which are unique within the process, using a counter.
static AtomicSequenceNumber seq;
UkmSourceId local_id = FromOtherId(seq.GetNext() + 1, UkmSourceId::Type::UKM);
// Combine the local and process bits to generate a unique ID.
return UkmSourceId((local_id.value_ & kLowBitsMask) | process_id_bits);
}
// static
UkmSourceId UkmSourceId::FromOtherId(int64_t other_id, UkmSourceId::Type type) {
const int64_t type_bits = static_cast<int64_t>(type);
DCHECK_EQ(type_bits, type_bits & kTypeMask);
// Stores the the type ID in the low bits of the source id, and shift the rest
// of the ID to make room. This could cause the original ID to overflow, but
// that should be rare enough that it won't matter for UKM's purposes.
return UkmSourceId((other_id << kNumTypeBits) | type_bits);
}
UkmSourceId::Type UkmSourceId::GetType() const {
return static_cast<UkmSourceId::Type>(value_ & kTypeMask);
}
} // namespace base
// Copyright 2018 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 BASE_METRICS_UKM_SOURCE_ID_H_
#define BASE_METRICS_UKM_SOURCE_ID_H_
#include <stdint.h>
#include "base/base_export.h"
namespace base {
// An ID used to identify a Source to UKM, for recording information about it.
// These objects are copyable, assignable, and occupy 64-bits per instance.
// Prefer passing them by value.
class BASE_EXPORT UkmSourceId {
public:
enum class Type : int64_t {
UKM = 0,
NAVIGATION_ID = 1,
APP_ID = 2,
};
// Default constructor has the invalid value.
constexpr UkmSourceId() : value_(0) {}
constexpr UkmSourceId& operator=(UkmSourceId other) {
value_ = other.value_;
return *this;
}
// Allow identity comparisons.
constexpr bool operator==(UkmSourceId other) const {
return value_ == other.value_;
}
constexpr bool operator!=(UkmSourceId other) const {
return value_ != other.value_;
}
// Allow coercive comparisons to simplify test migration.
// TODO(crbug/873866): Remove these once callers are migrated.
constexpr bool operator==(int64_t other) const { return value_ == other; }
constexpr bool operator!=(int64_t other) const { return value_ == other; }
// Extract the Type of the SourceId.
Type GetType() const;
// Return the ID as an int64.
constexpr int64_t ToInt64() const { return value_; }
// Convert an int64 ID value to an ID.
static constexpr UkmSourceId FromInt64(int64_t internal_value) {
return UkmSourceId(internal_value);
}
// Get a new UKM-Type SourceId, which is unique within the scope of a
// browser session.
static UkmSourceId New();
// Utility for converting other unique ids to source ids.
static UkmSourceId FromOtherId(int64_t value, Type type);
private:
constexpr explicit UkmSourceId(int64_t value) : value_(value) {}
int64_t value_;
};
constexpr UkmSourceId kInvalidUkmSourceId = UkmSourceId();
} // namespace base
#endif // BASE_METRICS_UKM_SOURCE_ID_H_
...@@ -36,6 +36,7 @@ class TestUkmRecorder : public UkmRecorderImpl { ...@@ -36,6 +36,7 @@ class TestUkmRecorder : public UkmRecorderImpl {
size_t entries_count() const { return entries().size(); } size_t entries_count() const { return entries().size(); }
using UkmRecorderImpl::UpdateSourceURL; using UkmRecorderImpl::UpdateSourceURL;
using UkmRecorderImpl::RecordOtherURL;
// Gets all recorded UkmSource data. // Gets all recorded UkmSource data.
const std::map<ukm::SourceId, std::unique_ptr<UkmSource>>& GetSources() const std::map<ukm::SourceId, std::unique_ptr<UkmSource>>& GetSources()
......
...@@ -84,6 +84,7 @@ class UkmRecorderImpl : public UkmRecorder { ...@@ -84,6 +84,7 @@ class UkmRecorderImpl : public UkmRecorder {
// UkmRecorder: // UkmRecorder:
void UpdateSourceURL(SourceId source_id, const GURL& url) override; void UpdateSourceURL(SourceId source_id, const GURL& url) override;
void UpdateAppURL(SourceId source_id, const GURL& url) override; void UpdateAppURL(SourceId source_id, const GURL& url) override;
using UkmRecorder::RecordOtherURL;
virtual bool ShouldRestrictToWhitelistedSourceIds() const; virtual bool ShouldRestrictToWhitelistedSourceIds() const;
......
...@@ -19,6 +19,13 @@ UkmEntryBuilderBase::UkmEntryBuilderBase(ukm::SourceId source_id, ...@@ -19,6 +19,13 @@ UkmEntryBuilderBase::UkmEntryBuilderBase(ukm::SourceId source_id,
entry_->event_hash = event_hash; entry_->event_hash = event_hash;
} }
UkmEntryBuilderBase::UkmEntryBuilderBase(base::UkmSourceId source_id,
uint64_t event_hash)
: entry_(mojom::UkmEntry::New()) {
entry_->source_id = source_id.ToInt64();
entry_->event_hash = event_hash;
}
UkmEntryBuilderBase::~UkmEntryBuilderBase() = default; UkmEntryBuilderBase::~UkmEntryBuilderBase() = default;
void UkmEntryBuilderBase::SetMetricInternal(uint64_t metric_hash, void UkmEntryBuilderBase::SetMetricInternal(uint64_t metric_hash,
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include <string> #include <string>
#include "base/macros.h" #include "base/macros.h"
#include "base/metrics/ukm_source_id.h"
#include "services/metrics/public/cpp/metrics_export.h" #include "services/metrics/public/cpp/metrics_export.h"
#include "services/metrics/public/cpp/ukm_recorder.h" #include "services/metrics/public/cpp/ukm_recorder.h"
#include "services/metrics/public/mojom/ukm_interface.mojom.h" #include "services/metrics/public/mojom/ukm_interface.mojom.h"
...@@ -27,6 +28,8 @@ class METRICS_EXPORT UkmEntryBuilderBase { ...@@ -27,6 +28,8 @@ class METRICS_EXPORT UkmEntryBuilderBase {
void Record(UkmRecorder* recorder); void Record(UkmRecorder* recorder);
protected: protected:
UkmEntryBuilderBase(base::UkmSourceId source_id, uint64_t event_hash);
// TODO(crbug/873866): Remove this version once callers are migrated.
UkmEntryBuilderBase(SourceId source_id, uint64_t event_hash); UkmEntryBuilderBase(SourceId source_id, uint64_t event_hash);
// Add metric to the entry. A metric contains a metric hash and value. // Add metric to the entry. A metric contains a metric hash and value.
......
...@@ -31,4 +31,12 @@ ukm::SourceId UkmRecorder::GetNewSourceID() { ...@@ -31,4 +31,12 @@ ukm::SourceId UkmRecorder::GetNewSourceID() {
return AssignNewSourceId(); return AssignNewSourceId();
} }
void UkmRecorder::RecordOtherURL(base::UkmSourceId source_id, const GURL& url) {
UpdateSourceURL(source_id.ToInt64(), url);
}
void UkmRecorder::RecordAppURL(base::UkmSourceId source_id, const GURL& url) {
UpdateAppURL(source_id.ToInt64(), url);
}
} // namespace ukm } // namespace ukm
...@@ -95,6 +95,11 @@ class METRICS_EXPORT UkmRecorder { ...@@ -95,6 +95,11 @@ class METRICS_EXPORT UkmRecorder {
// Disables sampling for testing purposes. // Disables sampling for testing purposes.
virtual void DisableSamplingForTesting(){}; virtual void DisableSamplingForTesting(){};
protected:
// Type-safe wrappers for Update<X> functions.
void RecordOtherURL(base::UkmSourceId source_id, const GURL& url);
void RecordAppURL(base::UkmSourceId source_id, const GURL& url);
private: private:
friend DelegatingUkmRecorder; friend DelegatingUkmRecorder;
friend IOSChromePasswordManagerClient; friend IOSChromePasswordManagerClient;
......
...@@ -10,39 +10,16 @@ ...@@ -10,39 +10,16 @@
namespace ukm { namespace ukm {
namespace {
const int64_t kLowBitsMask = (INT64_C(1) << 32) - 1;
const int64_t kNumTypeBits = 2;
const int64_t kTypeMask = (INT64_C(1) << kNumTypeBits) - 1;
} // namespace
SourceId AssignNewSourceId() { SourceId AssignNewSourceId() {
// Generate some bits which are unique to this process, so we can generate return base::UkmSourceId::New().ToInt64();
// IDs independently in different processes. IDs generated by this method may
// collide, but it should be sufficiently rare enough to not impact data
// quality.
const static int64_t process_id_bits =
static_cast<int64_t>(base::RandUint64()) & ~kLowBitsMask;
// Generate some bits which are unique within the process, using a counter.
static base::AtomicSequenceNumber seq;
SourceId local_id = ConvertToSourceId(seq.GetNext() + 1, SourceIdType::UKM);
// Combine the local and process bits to generate a unique ID.
return (local_id & kLowBitsMask) | process_id_bits;
} }
SourceId ConvertToSourceId(int64_t other_id, SourceIdType id_type) { SourceId ConvertToSourceId(int64_t other_id, SourceIdType id_type) {
const int64_t type_bits = static_cast<int64_t>(id_type); return base::UkmSourceId::FromOtherId(other_id, id_type).ToInt64();
DCHECK_EQ(type_bits, type_bits & kTypeMask);
// Stores the the type ID in the low bits of the source id, and shift the rest
// of the ID to make room. This could cause the original ID to overflow, but
// that should be rare enough that it won't matter for UKM's purposes.
return (other_id << kNumTypeBits) | type_bits;
} }
SourceIdType GetSourceIdType(SourceId source_id) { SourceIdType GetSourceIdType(SourceId source_id) {
return static_cast<SourceIdType>(source_id & kTypeMask); return base::UkmSourceId::FromInt64(source_id).GetType();
} }
} // namespace ukm } // namespace ukm
...@@ -7,17 +7,14 @@ ...@@ -7,17 +7,14 @@
#include <stdint.h> #include <stdint.h>
#include "base/metrics/ukm_source_id.h"
#include "services/metrics/public/cpp/metrics_export.h" #include "services/metrics/public/cpp/metrics_export.h"
namespace ukm { namespace ukm {
typedef int64_t SourceId; typedef int64_t SourceId;
enum class SourceIdType : int64_t { using SourceIdType = base::UkmSourceId::Type;
UKM = 0,
NAVIGATION_ID = 1,
APP_ID = 2,
};
const SourceId kInvalidSourceId = 0; const SourceId kInvalidSourceId = 0;
......
...@@ -32,7 +32,8 @@ namespace builders {{ ...@@ -32,7 +32,8 @@ namespace builders {{
event_template=""" event_template="""
class {event.name} final : public ::ukm::internal::UkmEntryBuilderBase {{ class {event.name} final : public ::ukm::internal::UkmEntryBuilderBase {{
public: public:
{event.name}(ukm::SourceId source_id); explicit {event.name}(ukm::SourceId source_id);
explicit {event.name}(base::UkmSourceId source_id);
~{event.name}() override; ~{event.name}() override;
static const char kEntryName[]; static const char kEntryName[];
...@@ -70,6 +71,10 @@ const char {event.name}::kEntryName[] = "{event.raw_name}"; ...@@ -70,6 +71,10 @@ const char {event.name}::kEntryName[] = "{event.raw_name}";
::ukm::internal::UkmEntryBuilderBase(source_id, kEntryNameHash) {{ ::ukm::internal::UkmEntryBuilderBase(source_id, kEntryNameHash) {{
}} }}
{event.name}::{event.name}(base::UkmSourceId source_id) :
::ukm::internal::UkmEntryBuilderBase(source_id, kEntryNameHash) {{
}}
{event.name}::~{event.name}() = default; {event.name}::~{event.name}() = default;
{metric_code} {metric_code}
......
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