summaryrefslogtreecommitdiffstats
path: root/toolkit/components/glean
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-15 03:35:49 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-15 03:35:49 +0000
commitd8bbc7858622b6d9c278469aab701ca0b609cddf (patch)
treeeff41dc61d9f714852212739e6b3738b82a2af87 /toolkit/components/glean
parentReleasing progress-linux version 125.0.3-1~progress7.99u1. (diff)
downloadfirefox-d8bbc7858622b6d9c278469aab701ca0b609cddf.tar.xz
firefox-d8bbc7858622b6d9c278469aab701ca0b609cddf.zip
Merging upstream version 126.0.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'toolkit/components/glean')
-rw-r--r--toolkit/components/glean/Cargo.toml2
-rw-r--r--toolkit/components/glean/api/Cargo.toml2
-rw-r--r--toolkit/components/glean/api/src/common_test.rs1
-rw-r--r--toolkit/components/glean/api/src/ffi/custom_distribution.rs20
-rw-r--r--toolkit/components/glean/api/src/ffi/event.rs5
-rw-r--r--toolkit/components/glean/api/src/private/custom_distribution.rs17
-rw-r--r--toolkit/components/glean/api/src/private/timing_distribution.rs12
-rw-r--r--toolkit/components/glean/bindings/private/Boolean.cpp2
-rw-r--r--toolkit/components/glean/bindings/private/Counter.cpp2
-rw-r--r--toolkit/components/glean/bindings/private/CustomDistribution.cpp23
-rw-r--r--toolkit/components/glean/bindings/private/CustomDistribution.h17
-rw-r--r--toolkit/components/glean/bindings/private/DistributionData.h22
-rw-r--r--toolkit/components/glean/bindings/private/Labeled.cpp2
-rw-r--r--toolkit/components/glean/bindings/private/Labeled.h2
-rw-r--r--toolkit/components/glean/bindings/private/Ping.cpp4
-rw-r--r--toolkit/components/glean/bindings/private/Timespan.cpp6
-rw-r--r--toolkit/components/glean/bindings/private/TimingDistribution.cpp20
-rw-r--r--toolkit/components/glean/build_scripts/mach_commands.py59
-rw-r--r--toolkit/components/glean/build_scripts/translate_events.py177
-rw-r--r--toolkit/components/glean/metrics_index.py3
-rw-r--r--toolkit/components/glean/src/init/mod.rs15
-rw-r--r--toolkit/components/glean/tests/gtest/TestFog.cpp11
-rw-r--r--toolkit/components/glean/xpcom/FOG.cpp15
-rw-r--r--toolkit/components/glean/xpcom/nsIFOG.idl4
24 files changed, 401 insertions, 42 deletions
diff --git a/toolkit/components/glean/Cargo.toml b/toolkit/components/glean/Cargo.toml
index 98b8d8a95b..ba563f514a 100644
--- a/toolkit/components/glean/Cargo.toml
+++ b/toolkit/components/glean/Cargo.toml
@@ -6,7 +6,7 @@ edition = "2018"
license = "MPL-2.0"
[dependencies]
-glean = "58.1.0"
+glean = "59.0.0"
log = "0.4"
nserror = { path = "../../../xpcom/rust/nserror" }
nsstring = { path = "../../../xpcom/rust/nsstring" }
diff --git a/toolkit/components/glean/api/Cargo.toml b/toolkit/components/glean/api/Cargo.toml
index dc688dc41e..af507f499f 100644
--- a/toolkit/components/glean/api/Cargo.toml
+++ b/toolkit/components/glean/api/Cargo.toml
@@ -9,7 +9,7 @@ license = "MPL-2.0"
[dependencies]
bincode = "1.0"
chrono = "0.4.10"
-glean = "58.1.0"
+glean = "59.0.0"
inherent = "1.0.0"
log = "0.4"
nsstring = { path = "../../../../xpcom/rust/nsstring", optional = true }
diff --git a/toolkit/components/glean/api/src/common_test.rs b/toolkit/components/glean/api/src/common_test.rs
index 3c8c2c71e1..46062736f2 100644
--- a/toolkit/components/glean/api/src/common_test.rs
+++ b/toolkit/components/glean/api/src/common_test.rs
@@ -43,6 +43,7 @@ fn setup_glean(tempdir: Option<tempfile::TempDir>) -> tempfile::TempDir {
rate_limit: None,
enable_event_timestamps: false,
experimentation_id: None,
+ enable_internal_pings: true
};
let client_info = glean::ClientInfoMetrics {
diff --git a/toolkit/components/glean/api/src/ffi/custom_distribution.rs b/toolkit/components/glean/api/src/ffi/custom_distribution.rs
index 643ebfbff5..6f369fd268 100644
--- a/toolkit/components/glean/api/src/ffi/custom_distribution.rs
+++ b/toolkit/components/glean/api/src/ffi/custom_distribution.rs
@@ -69,6 +69,26 @@ pub extern "C" fn fog_custom_distribution_accumulate_samples_signed(
}
#[no_mangle]
+pub extern "C" fn fog_custom_distribution_accumulate_single_sample(id: u32, sample: u64) {
+ with_metric!(
+ CUSTOM_DISTRIBUTION_MAP,
+ id,
+ metric,
+ metric.accumulate_single_sample_signed(sample as i64)
+ );
+}
+
+#[no_mangle]
+pub extern "C" fn fog_custom_distribution_accumulate_single_sample_signed(id: u32, sample: i64) {
+ with_metric!(
+ CUSTOM_DISTRIBUTION_MAP,
+ id,
+ metric,
+ metric.accumulate_single_sample_signed(sample)
+ );
+}
+
+#[no_mangle]
pub extern "C" fn fog_custom_distribution_test_get_error(
id: u32,
diff --git a/toolkit/components/glean/api/src/ffi/event.rs b/toolkit/components/glean/api/src/ffi/event.rs
index bd167021d6..5d1e2dc0f1 100644
--- a/toolkit/components/glean/api/src/ffi/event.rs
+++ b/toolkit/components/glean/api/src/ffi/event.rs
@@ -4,8 +4,6 @@
#![cfg(feature = "with_gecko")]
-use std::collections::HashMap;
-
use nsstring::{nsACString, nsCString};
use thin_vec::ThinVec;
@@ -59,7 +57,6 @@ pub extern "C" fn fog_event_record(
Some(m) => m.record_raw(extra),
None => panic!("No (dynamic) metric for event with id {}", id),
}
- return;
} else {
match metric_maps::record_event_by_id(id, extra) {
Ok(()) => {}
@@ -148,7 +145,7 @@ pub extern "C" fn fog_event_test_get_value(
};
for event in events {
- let extra = event.extra.unwrap_or_else(HashMap::new);
+ let extra = event.extra.unwrap_or_default();
let extra_len = extra.len();
let mut extras = ThinVec::with_capacity(extra_len * 2);
for (k, v) in extra.into_iter() {
diff --git a/toolkit/components/glean/api/src/private/custom_distribution.rs b/toolkit/components/glean/api/src/private/custom_distribution.rs
index aeaf9b58c2..85121fca1e 100644
--- a/toolkit/components/glean/api/src/private/custom_distribution.rs
+++ b/toolkit/components/glean/api/src/private/custom_distribution.rs
@@ -92,8 +92,21 @@ impl CustomDistribution for CustomDistributionMetric {
}
}
- pub fn accumulate_single_sample_signed(&self, _sample: i64) {
- unimplemented!("bug 1884183: expose this to FOG")
+ pub fn accumulate_single_sample_signed(&self, sample: i64) {
+ match self {
+ CustomDistributionMetric::Parent { inner, .. } => {
+ inner.accumulate_single_sample(sample)
+ }
+ CustomDistributionMetric::Child(c) => {
+ with_ipc_payload(move |payload| {
+ if let Some(v) = payload.custom_samples.get_mut(&c.0) {
+ v.push(sample);
+ } else {
+ payload.custom_samples.insert(c.0, vec![sample]);
+ }
+ });
+ }
+ }
}
pub fn test_get_value<'a, S: Into<Option<&'a str>>>(
diff --git a/toolkit/components/glean/api/src/private/timing_distribution.rs b/toolkit/components/glean/api/src/private/timing_distribution.rs
index 6707560e41..2807b87c4f 100644
--- a/toolkit/components/glean/api/src/private/timing_distribution.rs
+++ b/toolkit/components/glean/api/src/private/timing_distribution.rs
@@ -374,8 +374,16 @@ impl TimingDistribution for TimingDistributionMetric {
}
}
- pub fn accumulate_single_sample(&self, _sample: i64) {
- unimplemented!("bug 1884183: expose this to FOG")
+ pub fn accumulate_single_sample(&self, sample: i64) {
+ match self {
+ TimingDistributionMetric::Parent { id: _id, inner } => {
+ inner.accumulate_single_sample(sample)
+ }
+ TimingDistributionMetric::Child(_c) => {
+ // TODO: Instrument this error
+ log::error!("Can't record samples for a timing distribution from a child metric");
+ }
+ }
}
/// **Exported for test purposes.**
diff --git a/toolkit/components/glean/bindings/private/Boolean.cpp b/toolkit/components/glean/bindings/private/Boolean.cpp
index 8300990b49..168179f569 100644
--- a/toolkit/components/glean/bindings/private/Boolean.cpp
+++ b/toolkit/components/glean/bindings/private/Boolean.cpp
@@ -21,7 +21,7 @@ void BooleanMetric::Set(bool aValue) const {
if (scalarId) {
Telemetry::ScalarSet(scalarId.extract(), aValue);
} else if (IsSubmetricId(mId)) {
- GetLabeledMirrorLock().apply([&](auto& lock) {
+ GetLabeledMirrorLock().apply([&](const auto& lock) {
auto tuple = lock.ref()->MaybeGet(mId);
if (tuple) {
Telemetry::ScalarSet(std::get<0>(tuple.ref()), std::get<1>(tuple.ref()),
diff --git a/toolkit/components/glean/bindings/private/Counter.cpp b/toolkit/components/glean/bindings/private/Counter.cpp
index f7f70f29eb..4eeeb3de7a 100644
--- a/toolkit/components/glean/bindings/private/Counter.cpp
+++ b/toolkit/components/glean/bindings/private/Counter.cpp
@@ -22,7 +22,7 @@ void CounterMetric::Add(int32_t aAmount) const {
if (scalarId) {
Telemetry::ScalarAdd(scalarId.extract(), aAmount);
} else if (IsSubmetricId(mId)) {
- GetLabeledMirrorLock().apply([&](auto& lock) {
+ GetLabeledMirrorLock().apply([&](const auto& lock) {
auto tuple = lock.ref()->MaybeGet(mId);
if (tuple && aAmount > 0) {
Telemetry::ScalarAdd(std::get<0>(tuple.ref()),
diff --git a/toolkit/components/glean/bindings/private/CustomDistribution.cpp b/toolkit/components/glean/bindings/private/CustomDistribution.cpp
index a5a821a558..88e96236db 100644
--- a/toolkit/components/glean/bindings/private/CustomDistribution.cpp
+++ b/toolkit/components/glean/bindings/private/CustomDistribution.cpp
@@ -33,6 +33,15 @@ void CustomDistributionMetric::AccumulateSamples(
fog_custom_distribution_accumulate_samples(mId, &aSamples);
}
+void CustomDistributionMetric::AccumulateSingleSample(uint64_t aSample) const {
+ auto hgramId = HistogramIdForMetric(mId);
+ if (hgramId) {
+ auto id = hgramId.extract();
+ Telemetry::Accumulate(id, aSample);
+ }
+ fog_custom_distribution_accumulate_single_sample(mId, aSample);
+}
+
void CustomDistributionMetric::AccumulateSamplesSigned(
const nsTArray<int64_t>& aSamples) const {
auto hgramId = HistogramIdForMetric(mId);
@@ -47,6 +56,16 @@ void CustomDistributionMetric::AccumulateSamplesSigned(
fog_custom_distribution_accumulate_samples_signed(mId, &aSamples);
}
+void CustomDistributionMetric::AccumulateSingleSampleSigned(
+ int64_t aSample) const {
+ auto hgramId = HistogramIdForMetric(mId);
+ if (hgramId) {
+ auto id = hgramId.extract();
+ Telemetry::Accumulate(id, aSample);
+ }
+ fog_custom_distribution_accumulate_single_sample_signed(mId, aSample);
+}
+
Result<Maybe<DistributionData>, nsCString>
CustomDistributionMetric::TestGetValue(const nsACString& aPingName) const {
nsCString err;
@@ -78,6 +97,10 @@ void GleanCustomDistribution::AccumulateSamples(
mCustomDist.AccumulateSamplesSigned(aSamples);
}
+void GleanCustomDistribution::AccumulateSingleSample(const int64_t aSample) {
+ mCustomDist.AccumulateSingleSampleSigned(aSample);
+}
+
void GleanCustomDistribution::TestGetValue(
const nsACString& aPingName,
dom::Nullable<dom::GleanDistributionData>& aRetval, ErrorResult& aRv) {
diff --git a/toolkit/components/glean/bindings/private/CustomDistribution.h b/toolkit/components/glean/bindings/private/CustomDistribution.h
index 8227b024ad..8074a0542e 100644
--- a/toolkit/components/glean/bindings/private/CustomDistribution.h
+++ b/toolkit/components/glean/bindings/private/CustomDistribution.h
@@ -35,6 +35,13 @@ class CustomDistributionMetric {
void AccumulateSamples(const nsTArray<uint64_t>& aSamples) const;
/**
+ * Accumulates the provided sample in the metric.
+ *
+ * @param aSamples The sample to be recorded by the metric.
+ */
+ void AccumulateSingleSample(uint64_t aSample) const;
+
+ /**
* Accumulates the provided samples in the metric.
*
* @param aSamples The vector holding the samples to be recorded by the
@@ -46,6 +53,14 @@ class CustomDistributionMetric {
void AccumulateSamplesSigned(const nsTArray<int64_t>& aSamples) const;
/**
+ * Accumulates the provided sample in the metric.
+ *
+ * @param aSamples The signed integer sample to be recorded by the
+ * metric.
+ */
+ void AccumulateSingleSampleSigned(int64_t aSample) const;
+
+ /**
* **Test-only API**
*
* Gets the currently stored value as a DistributionData.
@@ -80,6 +95,8 @@ class GleanCustomDistribution final : public GleanMetric {
void AccumulateSamples(const dom::Sequence<int64_t>& aSamples);
+ void AccumulateSingleSample(const int64_t aSample);
+
void TestGetValue(const nsACString& aPingName,
dom::Nullable<dom::GleanDistributionData>& aRetval,
ErrorResult& aRv);
diff --git a/toolkit/components/glean/bindings/private/DistributionData.h b/toolkit/components/glean/bindings/private/DistributionData.h
index fb9bba720e..782fe17c98 100644
--- a/toolkit/components/glean/bindings/private/DistributionData.h
+++ b/toolkit/components/glean/bindings/private/DistributionData.h
@@ -27,6 +27,28 @@ struct DistributionData final {
this->values.InsertOrUpdate(aBuckets[i], aCounts[i]);
}
}
+
+ friend std::ostream& operator<<(std::ostream& aStream,
+ const DistributionData& aDist) {
+ aStream << "DistributionData(";
+ aStream << "sum=" << aDist.sum << ", ";
+ aStream << "count=" << aDist.count << ", ";
+ aStream << "values={";
+ bool first = true;
+ for (const auto& entry : aDist.values) {
+ if (!first) {
+ aStream << ", ";
+ }
+ first = false;
+
+ const uint64_t bucket = entry.GetKey();
+ const uint64_t count = entry.GetData();
+ aStream << bucket << "=" << count;
+ }
+ aStream << "}";
+ aStream << ")";
+ return aStream;
+ }
};
} // namespace mozilla::glean
diff --git a/toolkit/components/glean/bindings/private/Labeled.cpp b/toolkit/components/glean/bindings/private/Labeled.cpp
index 23527708e0..1af9b870ae 100644
--- a/toolkit/components/glean/bindings/private/Labeled.cpp
+++ b/toolkit/components/glean/bindings/private/Labeled.cpp
@@ -31,7 +31,7 @@ already_AddRefed<GleanMetric> GleanLabeled::NamedGetter(const nsAString& aName,
auto mirrorId = ScalarIdForMetric(mId);
if (mirrorId) {
- GetLabeledMirrorLock().apply([&](auto& lock) {
+ GetLabeledMirrorLock().apply([&](const auto& lock) {
auto tuple = std::make_tuple<Telemetry::ScalarID, nsString>(
mirrorId.extract(), nsString(aName));
lock.ref()->InsertOrUpdate(submetricId, std::move(tuple));
diff --git a/toolkit/components/glean/bindings/private/Labeled.h b/toolkit/components/glean/bindings/private/Labeled.h
index 65e31bd2bd..0e3aafba05 100644
--- a/toolkit/components/glean/bindings/private/Labeled.h
+++ b/toolkit/components/glean/bindings/private/Labeled.h
@@ -60,7 +60,7 @@ class Labeled {
static inline void UpdateLabeledMirror(Telemetry::ScalarID aMirrorId,
uint32_t aSubmetricId,
const nsACString& aLabel) {
- GetLabeledMirrorLock().apply([&](auto& lock) {
+ GetLabeledMirrorLock().apply([&](const auto& lock) {
auto tuple = std::make_tuple<Telemetry::ScalarID, nsString>(
std::move(aMirrorId), NS_ConvertUTF8toUTF16(aLabel));
lock.ref()->InsertOrUpdate(aSubmetricId, std::move(tuple));
diff --git a/toolkit/components/glean/bindings/private/Ping.cpp b/toolkit/components/glean/bindings/private/Ping.cpp
index 19f4fb5f77..8dbb316128 100644
--- a/toolkit/components/glean/bindings/private/Ping.cpp
+++ b/toolkit/components/glean/bindings/private/Ping.cpp
@@ -42,7 +42,7 @@ void Ping::Submit(const nsACString& aReason) const {
{
auto callback = Maybe<PingTestCallback>();
GetCallbackMapLock().apply(
- [&](auto& lock) { callback = lock.ref()->Extract(mId); });
+ [&](const auto& lock) { callback = lock.ref()->Extract(mId); });
// Calling the callback outside of the lock allows it to register a new
// callback itself.
if (callback) {
@@ -55,7 +55,7 @@ void Ping::Submit(const nsACString& aReason) const {
void Ping::TestBeforeNextSubmit(PingTestCallback&& aCallback) const {
{
GetCallbackMapLock().apply(
- [&](auto& lock) { lock.ref()->InsertOrUpdate(mId, aCallback); });
+ [&](const auto& lock) { lock.ref()->InsertOrUpdate(mId, aCallback); });
}
}
diff --git a/toolkit/components/glean/bindings/private/Timespan.cpp b/toolkit/components/glean/bindings/private/Timespan.cpp
index 2ab1f0dbba..7f154152eb 100644
--- a/toolkit/components/glean/bindings/private/Timespan.cpp
+++ b/toolkit/components/glean/bindings/private/Timespan.cpp
@@ -93,7 +93,7 @@ void TimespanMetric::Start() const {
auto optScalarId = ScalarIdForMetric(mId);
if (optScalarId) {
auto scalarId = optScalarId.extract();
- GetTimesToStartsLock().apply([&](auto& lock) {
+ GetTimesToStartsLock().apply([&](const auto& lock) {
(void)NS_WARN_IF(lock.ref()->Remove(scalarId));
lock.ref()->InsertOrUpdate(scalarId, TimeStamp::Now());
});
@@ -105,7 +105,7 @@ void TimespanMetric::Stop() const {
auto optScalarId = ScalarIdForMetric(mId);
if (optScalarId) {
auto scalarId = optScalarId.extract();
- GetTimesToStartsLock().apply([&](auto& lock) {
+ GetTimesToStartsLock().apply([&](const auto& lock) {
auto optStart = lock.ref()->Extract(scalarId);
if (!NS_WARN_IF(!optStart)) {
double delta = (TimeStamp::Now() - optStart.extract()).ToMilliseconds();
@@ -127,7 +127,7 @@ void TimespanMetric::Cancel() const {
if (optScalarId) {
auto scalarId = optScalarId.extract();
GetTimesToStartsLock().apply(
- [&](auto& lock) { lock.ref()->Remove(scalarId); });
+ [&](const auto& lock) { lock.ref()->Remove(scalarId); });
}
fog_timespan_cancel(mId);
}
diff --git a/toolkit/components/glean/bindings/private/TimingDistribution.cpp b/toolkit/components/glean/bindings/private/TimingDistribution.cpp
index 036db5f9db..7273d3fd2f 100644
--- a/toolkit/components/glean/bindings/private/TimingDistribution.cpp
+++ b/toolkit/components/glean/bindings/private/TimingDistribution.cpp
@@ -106,7 +106,7 @@ extern "C" NS_EXPORT void GIFFT_TimingDistributionStart(
uint32_t aMetricId, mozilla::glean::TimerId aTimerId) {
auto mirrorId = mozilla::glean::HistogramIdForMetric(aMetricId);
if (mirrorId) {
- mozilla::glean::GetTimerIdToStartsLock().apply([&](auto& lock) {
+ mozilla::glean::GetTimerIdToStartsLock().apply([&](const auto& lock) {
auto tuple = mozilla::glean::MetricTimerTuple{aMetricId, aTimerId};
// It should be all but impossible for anyone to have already inserted
// this timer for this metric given the monotonicity of timer ids.
@@ -121,7 +121,7 @@ extern "C" NS_EXPORT void GIFFT_TimingDistributionStopAndAccumulate(
uint32_t aMetricId, mozilla::glean::TimerId aTimerId) {
auto mirrorId = mozilla::glean::HistogramIdForMetric(aMetricId);
if (mirrorId) {
- mozilla::glean::GetTimerIdToStartsLock().apply([&](auto& lock) {
+ mozilla::glean::GetTimerIdToStartsLock().apply([&](const auto& lock) {
auto tuple = mozilla::glean::MetricTimerTuple{aMetricId, aTimerId};
auto optStart = lock.ref()->Extract(tuple);
// The timer might not be in the map to be removed if it's already been
@@ -147,7 +147,7 @@ extern "C" NS_EXPORT void GIFFT_TimingDistributionCancel(
uint32_t aMetricId, mozilla::glean::TimerId aTimerId) {
auto mirrorId = mozilla::glean::HistogramIdForMetric(aMetricId);
if (mirrorId) {
- mozilla::glean::GetTimerIdToStartsLock().apply([&](auto& lock) {
+ mozilla::glean::GetTimerIdToStartsLock().apply([&](const auto& lock) {
// The timer might not be in the map to be removed if it's already been
// cancelled or stop_and_accumulate'd.
auto tuple = mozilla::glean::MetricTimerTuple{aMetricId, aTimerId};
@@ -172,8 +172,20 @@ void TimingDistributionMetric::StopAndAccumulate(const TimerId&& aId) const {
// type.
void TimingDistributionMetric::AccumulateRawDuration(
const TimeDuration& aDuration) const {
+ // `* 1000.0` is an acceptable overflow risk as durations are unlikely to be
+ // on the order of (-)10^282 years.
+ double durationNs = aDuration.ToMicroseconds() * 1000.0;
+ double roundedDurationNs = std::round(durationNs);
+ if (MOZ_UNLIKELY(
+ roundedDurationNs <
+ static_cast<double>(std::numeric_limits<uint64_t>::min()) ||
+ roundedDurationNs >
+ static_cast<double>(std::numeric_limits<uint64_t>::max()))) {
+ // TODO(bug 1691073): Instrument this error.
+ return;
+ }
fog_timing_distribution_accumulate_raw_nanos(
- mId, uint64_t(aDuration.ToMicroseconds() * 1000.00));
+ mId, static_cast<uint64_t>(roundedDurationNs));
}
void TimingDistributionMetric::Cancel(const TimerId&& aId) const {
diff --git a/toolkit/components/glean/build_scripts/mach_commands.py b/toolkit/components/glean/build_scripts/mach_commands.py
index 4a0f6dbc68..b8d270c088 100644
--- a/toolkit/components/glean/build_scripts/mach_commands.py
+++ b/toolkit/components/glean/build_scripts/mach_commands.py
@@ -167,9 +167,18 @@ def update_glean(command_context, version):
topsrcdir = Path(command_context.topsrcdir)
replace_in_file_or_die(
- topsrcdir / "build.gradle",
- r'gleanVersion = "[0-9.]+"',
- f'gleanVersion = "{version}"',
+ topsrcdir
+ / "mobile"
+ / "android"
+ / "android-components"
+ / "plugins"
+ / "dependencies"
+ / "src"
+ / "main"
+ / "java"
+ / "DependenciesPlugin.kt",
+ r'mozilla_glean = "[0-9.]+"',
+ f'mozilla_glean = "{version}"',
)
replace_in_file_or_die(
topsrcdir / "toolkit" / "components" / "glean" / "Cargo.toml",
@@ -226,3 +235,47 @@ def update_glean(command_context, version):
"""
print(textwrap.dedent(instructions))
+
+
+@Command(
+ "event-into-legacy",
+ category="misc",
+ description="Create a Legacy Telemetry compatible event definition from an existing Glean Event metric.",
+)
+@CommandArgument(
+ "--append",
+ "-a",
+ action="store_true",
+ help="Append to toolkit/components/telemetry/Events.yaml (note: verify and make any necessary modifications before landing).",
+)
+@CommandArgument("event", default=None, nargs="?", type=str, help="Event name.")
+def event_into_legacy(command_context, event=None, append=False):
+ # Get the metrics_index's list of metrics indices
+ # by loading the index as a module.
+ import sys
+ from os import path
+
+ sys.path.append(path.join(path.dirname(__file__), path.pardir))
+
+ from metrics_index import metrics_yamls
+
+ sys.path.append(path.dirname(__file__))
+
+ from pathlib import Path
+
+ from translate_events import translate_event
+
+ legacy_yaml_path = path.join(
+ Path(command_context.topsrcdir),
+ "toolkit",
+ "components",
+ "telemetry",
+ "Events.yaml",
+ )
+
+ return translate_event(
+ event,
+ append,
+ [Path(command_context.topsrcdir) / x for x in metrics_yamls],
+ legacy_yaml_path,
+ )
diff --git a/toolkit/components/glean/build_scripts/translate_events.py b/toolkit/components/glean/build_scripts/translate_events.py
new file mode 100644
index 0000000000..5936a67132
--- /dev/null
+++ b/toolkit/components/glean/build_scripts/translate_events.py
@@ -0,0 +1,177 @@
+# -*- coding: utf-8 -*-
+
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+"""
+Create a Legacy Telemetry event definition for the provided, named Glean event metric.
+"""
+
+import re
+import sys
+from os import path
+from pathlib import Path
+from typing import Sequence
+
+import yaml
+from glean_parser import parser, util
+
+TC_ROOT_PATH = path.abspath(path.join(path.dirname(__file__), path.pardir, path.pardir))
+sys.path.append(TC_ROOT_PATH)
+# The parsers live in a subdirectory of "build_scripts", account for that.
+# NOTE: if the parsers are moved, this logic will need to be updated.
+sys.path.append(path.join(TC_ROOT_PATH, "telemetry", "build_scripts"))
+
+from mozparsers.parse_events import convert_to_cpp_identifier # noqa: E402
+
+bug_number_pattern = re.compile(r"\d+")
+
+
+class IndentingDumper(yaml.Dumper):
+ def increase_indent(self, flow=False, indentless=False):
+ return super(IndentingDumper, self).increase_indent(flow, False)
+
+
+def get_bug_number_from_url(url: str) -> int:
+ bug = bug_number_pattern.search(url)
+ # Python lacks a safe cast, so we will return 1 if we fail to bubble up.
+ if bug is not None:
+ try:
+ bug = int(bug[0])
+ except TypeError:
+ print(f"Failed to parse {bug[0]} to an integer")
+ return 1
+ return bug
+ print(f"Failed to find a valid bug in the url {url}")
+ return 1
+
+
+def create_legacy_mirror_def(category_name: str, metric_name: str, event_objects: list):
+ event_cpp_enum = convert_to_cpp_identifier(category_name, "_") + "_"
+ event_cpp_enum += convert_to_cpp_identifier(metric_name, ".") + "_"
+ event_cpp_enum += convert_to_cpp_identifier(event_objects[0], ".")
+
+ print(
+ f"""The Glean event {category_name}.{metric_name} has generated the {event_cpp_enum} Legacy Telemetry event. To link Glean to Legacy, please include in {category_name}.{metric_name}'s definition the following property:
+telemetry_mirror: {event_cpp_enum}
+See https://firefox-source-docs.mozilla.org/toolkit/components/glean/user/gifft.html#the-telemetry-mirror-property-in-metrics-yaml
+for more information.
+"""
+ )
+
+
+def translate_event(
+ event_category_and_name: str,
+ append: bool,
+ metrics_files: Sequence[Path],
+ legacy_yaml_file: Path,
+) -> int:
+ """
+ Commandline helper for translating Glean events to Legacy.
+
+ :param event_name: the event to look for
+ :param metrics_files: List of Path objects to load metrics from.
+ :return: Non-zero if there were any errors.
+ """
+
+ # Event objects are a Legacy Telemetry event field that is rarely used. We
+ # always broadcast into a single pre-defined object.
+ event_objects = ["events"]
+
+ if event_category_and_name is not None:
+ *event_category, event_name = event_category_and_name.rsplit(".", maxsplit=1)
+ else:
+ print("Please provide an event (in category.metricName format) to translate.")
+ return 1
+
+ if len(event_category) > 0:
+ event_category = util.snake_case(event_category[0])
+ event_name = util.snake_case(event_name)
+ else:
+ print(
+ f"Your event '{event_category_and_name}' did not conform to the a.category.a_metric_name format."
+ )
+ return 1
+
+ metrics_files = util.ensure_list(metrics_files)
+
+ # Accept any value of expires.
+ parser_options = {
+ "allow_reserved": True,
+ "custom_is_expired": lambda expires: False,
+ "custom_validate_expires": lambda expires: True,
+ }
+ all_objects = parser.parse_objects(metrics_files, parser_options)
+
+ if util.report_validation_errors(all_objects):
+ return 1
+
+ for category_name, metrics in all_objects.value.items():
+ for metric in metrics.values():
+ metric_name = util.snake_case(metric.name)
+ category_name = util.snake_case(category_name)
+
+ if metric_name != event_name or category_name != event_category:
+ continue
+
+ if metric.type != "event":
+ print(
+ f"Metric {event_category_and_name} was found, but was a {metric.type} metric, not an event metric."
+ )
+ return 1
+
+ bugs_list = [get_bug_number_from_url(m) for m in metric.bugs]
+ # Bail out if there was a parse error (error printed in get_bug_number_from_url)
+ if 1 in bugs_list:
+ return 1
+
+ metric_dict = {
+ "objects": event_objects,
+ "description": str(metric.description).strip(),
+ "bug_numbers": bugs_list,
+ "notification_emails": metric.notification_emails,
+ "expiry_version": str(metric.expires),
+ "products": ["firefox"],
+ "record_in_processes": ["all"],
+ }
+
+ if len(metric.extra_keys.items()) > 0:
+ # Convert extra keys into a nested dictionary that YAML can understand
+ extra_keys = {}
+ for extra_key_pair in metric.extra_keys.items():
+ description = (
+ extra_key_pair[1]["description"].replace("\n", " ").strip()
+ )
+ extra_keys[extra_key_pair[0]] = description
+
+ metric_dict["extra_keys"] = extra_keys
+
+ metric_dict = {metric_name: metric_dict}
+ metric_dict = {category_name: metric_dict}
+
+ metric_yaml = yaml.dump(
+ metric_dict,
+ default_flow_style=False,
+ width=78,
+ indent=2,
+ Dumper=IndentingDumper,
+ )
+
+ if append:
+ with open(legacy_yaml_file, "a") as file:
+ print("", file=file)
+ print(metric_yaml, file=file)
+ print(
+ f"Apended {event_category_and_name} to the Legacy Events.yaml file. Please confirm the details by opening"
+ )
+ print(legacy_yaml_file)
+ print("and checking that all fields are correct.")
+
+ create_legacy_mirror_def(event_name, category_name, event_objects)
+ return 0
+
+ print(metric_yaml)
+ create_legacy_mirror_def(event_name, category_name, event_objects)
+
+ return 0
diff --git a/toolkit/components/glean/metrics_index.py b/toolkit/components/glean/metrics_index.py
index 8e20658810..28759a15fa 100644
--- a/toolkit/components/glean/metrics_index.py
+++ b/toolkit/components/glean/metrics_index.py
@@ -18,6 +18,8 @@ gecko_metrics = [
"browser/base/content/metrics.yaml",
"docshell/base/metrics.yaml",
"dom/base/use_counter_metrics.yaml",
+ "dom/media/eme/metrics.yaml",
+ "dom/media/hls/metrics.yaml",
"dom/media/metrics.yaml",
"dom/media/webrtc/metrics.yaml",
"dom/metrics.yaml",
@@ -31,6 +33,7 @@ gecko_metrics = [
"mobile/android/modules/geckoview/metrics.yaml",
"netwerk/metrics.yaml",
"netwerk/protocol/http/metrics.yaml",
+ "security/certverifier/metrics.yaml",
"security/manager/ssl/metrics.yaml",
"toolkit/components/cookiebanners/metrics.yaml",
"toolkit/components/extensions/metrics.yaml",
diff --git a/toolkit/components/glean/src/init/mod.rs b/toolkit/components/glean/src/init/mod.rs
index f430cd7384..2c938899c0 100644
--- a/toolkit/components/glean/src/init/mod.rs
+++ b/toolkit/components/glean/src/init/mod.rs
@@ -38,6 +38,7 @@ use viaduct_uploader::ViaductUploader;
pub extern "C" fn fog_init(
data_path_override: &nsACString,
app_id_override: &nsACString,
+ disable_internal_pings: bool,
) -> nsresult {
let upload_enabled = static_prefs::pref!("datareporting.healthreport.uploadEnabled");
let recording_enabled = static_prefs::pref!("telemetry.fog.test.localhost_port") < 0;
@@ -48,6 +49,9 @@ pub extern "C" fn fog_init(
app_id_override,
upload_enabled || recording_enabled,
uploader,
+ // Flipping it around, because no value = defaults to false,
+ // so we take in `disable` but pass on `enable`.
+ !disable_internal_pings,
)
.into()
}
@@ -64,6 +68,7 @@ pub extern "C" fn fog_init(
pub extern "C" fn fog_init(
data_path_override: &nsACString,
app_id_override: &nsACString,
+ disable_internal_pings: bool,
) -> nsresult {
// On Android always enable Glean upload.
let upload_enabled = true;
@@ -75,6 +80,7 @@ pub extern "C" fn fog_init(
app_id_override,
upload_enabled,
uploader,
+ !disable_internal_pings,
)
.into()
}
@@ -84,6 +90,7 @@ fn fog_init_internal(
app_id_override: &nsACString,
upload_enabled: bool,
uploader: Option<Box<dyn glean::net::PingUploader>>,
+ enable_internal_pings: bool,
) -> Result<(), nsresult> {
metrics::fog::initialization.start();
@@ -95,6 +102,7 @@ fn fog_init_internal(
conf.upload_enabled = upload_enabled;
conf.uploader = uploader;
+ conf.enable_internal_pings = enable_internal_pings;
// If we're operating in automation without any specific source tags to set,
// set the tag "automation" so any pings that escape don't clutter the tables.
@@ -155,16 +163,12 @@ fn build_configuration(
extern "C" {
fn FOG_MaxPingLimit() -> u32;
- fn FOG_EventTimestampsEnabled() -> bool;
}
// SAFETY NOTE: Safe because it returns a primitive by value.
let pings_per_interval = unsafe { FOG_MaxPingLimit() };
metrics::fog::max_pings_per_minute.set(pings_per_interval.into());
- // SAFETY NOTE: Safe because it returns a primitive by value.
- let enable_event_timestamps = unsafe { FOG_EventTimestampsEnabled() };
-
let rate_limit = Some(glean::PingRateLimit {
seconds_per_interval: 60,
pings_per_interval,
@@ -182,8 +186,9 @@ fn build_configuration(
trim_data_to_registered_pings: true,
log_level: None,
rate_limit,
- enable_event_timestamps,
+ enable_event_timestamps: true,
experimentation_id: None,
+ enable_internal_pings: true,
};
Ok((configuration, client_info))
diff --git a/toolkit/components/glean/tests/gtest/TestFog.cpp b/toolkit/components/glean/tests/gtest/TestFog.cpp
index 0c1621911e..e6f4f7a2c2 100644
--- a/toolkit/components/glean/tests/gtest/TestFog.cpp
+++ b/toolkit/components/glean/tests/gtest/TestFog.cpp
@@ -11,6 +11,7 @@
#include "mozilla/Maybe.h"
#include "mozilla/Result.h"
#include "mozilla/ResultVariant.h"
+#include "mozilla/TimeStamp.h"
#include "nsTArray.h"
@@ -20,6 +21,7 @@
#include "prtime.h"
using mozilla::Preferences;
+using mozilla::TimeDuration;
using namespace mozilla::glean;
using namespace mozilla::glean::impl;
@@ -277,6 +279,15 @@ TEST_F(FOGFixture, TestCppTimingDistWorks) {
ASSERT_EQ(sampleCount, (uint64_t)2);
}
+TEST_F(FOGFixture, TestCppTimingDistNegativeDuration) {
+ // Intentionally a negative duration to test the error case.
+ auto negDuration = TimeDuration::FromSeconds(-1);
+ test_only::what_time_is_it.AccumulateRawDuration(negDuration);
+
+ ASSERT_EQ(mozilla::Nothing(),
+ test_only::what_time_is_it.TestGetValue().unwrap());
+}
+
TEST_F(FOGFixture, TestLabeledBooleanWorks) {
ASSERT_EQ(mozilla::Nothing(),
test_only::mabels_like_balloons.Get("hot_air"_ns)
diff --git a/toolkit/components/glean/xpcom/FOG.cpp b/toolkit/components/glean/xpcom/FOG.cpp
index d4c03a5b9e..955f2511b6 100644
--- a/toolkit/components/glean/xpcom/FOG.cpp
+++ b/toolkit/components/glean/xpcom/FOG.cpp
@@ -95,7 +95,7 @@ already_AddRefed<FOG> FOG::GetSingleton() {
glean::fog::inits_during_shutdown.Add(1);
// It's enough to call init before shutting down.
// We don't need to (and can't) wait for it to complete.
- glean::impl::fog_init(&VoidCString(), &VoidCString());
+ glean::impl::fog_init(&VoidCString(), &VoidCString(), false);
}
gFOG->Shutdown();
gFOG = nullptr;
@@ -123,19 +123,13 @@ extern "C" uint32_t FOG_MaxPingLimit(void) {
"gleanMaxPingsPerMinute"_ns, 15);
}
-// This allows us to pass whether to enable precise event timestamps to Rust.
-// Default is false.
-extern "C" bool FOG_EventTimestampsEnabled(void) {
- return NimbusFeatures::GetBool("gleanInternalSdk"_ns,
- "enableEventTimestamps"_ns, false);
-}
-
// Called when knowing if we're in automation is necessary.
extern "C" bool FOG_IPCIsInAutomation(void) { return xpc::IsInAutomation(); }
NS_IMETHODIMP
FOG::InitializeFOG(const nsACString& aDataPathOverride,
- const nsACString& aAppIdOverride) {
+ const nsACString& aAppIdOverride,
+ const bool aDisableInternalPings) {
MOZ_ASSERT(XRE_IsParentProcess());
gInitializeCalled = true;
RunOnShutdown(
@@ -147,7 +141,8 @@ FOG::InitializeFOG(const nsACString& aDataPathOverride,
},
ShutdownPhase::AppShutdownConfirmed);
- return glean::impl::fog_init(&aDataPathOverride, &aAppIdOverride);
+ return glean::impl::fog_init(&aDataPathOverride, &aAppIdOverride,
+ aDisableInternalPings);
}
NS_IMETHODIMP
diff --git a/toolkit/components/glean/xpcom/nsIFOG.idl b/toolkit/components/glean/xpcom/nsIFOG.idl
index dd5d0ec21a..67041d6228 100644
--- a/toolkit/components/glean/xpcom/nsIFOG.idl
+++ b/toolkit/components/glean/xpcom/nsIFOG.idl
@@ -17,8 +17,10 @@ interface nsIFOG : nsISupports
* instead of the profile dir.
* @param aAppIdOverride - The application_id to use instead of
* "firefox.desktop".
+ * @param aDisableInternalPings - Whether to disable internal pings (baseline, events, metrics).
+ * Default: false.
*/
- void initializeFOG([optional] in AUTF8String aDataPathOverride, [optional] in AUTF8String aAppIdOverride);
+ void initializeFOG([optional] in AUTF8String aDataPathOverride, [optional] in AUTF8String aAppIdOverride, [optional] in boolean aDisableInternalPings);
/**
* Register custom pings.