From d8bbc7858622b6d9c278469aab701ca0b609cddf Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 15 May 2024 05:35:49 +0200 Subject: Merging upstream version 126.0. Signed-off-by: Daniel Baumann --- toolkit/components/glean/Cargo.toml | 2 +- toolkit/components/glean/api/Cargo.toml | 2 +- toolkit/components/glean/api/src/common_test.rs | 1 + .../glean/api/src/ffi/custom_distribution.rs | 20 +++ toolkit/components/glean/api/src/ffi/event.rs | 5 +- .../glean/api/src/private/custom_distribution.rs | 17 +- .../glean/api/src/private/timing_distribution.rs | 12 +- .../components/glean/bindings/private/Boolean.cpp | 2 +- .../components/glean/bindings/private/Counter.cpp | 2 +- .../glean/bindings/private/CustomDistribution.cpp | 23 +++ .../glean/bindings/private/CustomDistribution.h | 17 ++ .../glean/bindings/private/DistributionData.h | 22 +++ .../components/glean/bindings/private/Labeled.cpp | 2 +- .../components/glean/bindings/private/Labeled.h | 2 +- toolkit/components/glean/bindings/private/Ping.cpp | 4 +- .../components/glean/bindings/private/Timespan.cpp | 6 +- .../glean/bindings/private/TimingDistribution.cpp | 20 ++- .../glean/build_scripts/mach_commands.py | 59 ++++++- .../glean/build_scripts/translate_events.py | 177 +++++++++++++++++++++ toolkit/components/glean/metrics_index.py | 3 + toolkit/components/glean/src/init/mod.rs | 15 +- toolkit/components/glean/tests/gtest/TestFog.cpp | 11 ++ toolkit/components/glean/xpcom/FOG.cpp | 15 +- toolkit/components/glean/xpcom/nsIFOG.idl | 4 +- 24 files changed, 401 insertions(+), 42 deletions(-) create mode 100644 toolkit/components/glean/build_scripts/translate_events.py (limited to 'toolkit/components/glean') 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 { 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 @@ -68,6 +68,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>>( 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& 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, 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& 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 @@ -34,6 +34,13 @@ class CustomDistributionMetric { */ void AccumulateSamples(const nsTArray& 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. * @@ -45,6 +52,14 @@ class CustomDistributionMetric { */ void AccumulateSamplesSigned(const nsTArray& 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** * @@ -80,6 +95,8 @@ class GleanCustomDistribution final : public GleanMetric { void AccumulateSamples(const dom::Sequence& aSamples); + void AccumulateSingleSample(const int64_t aSample); + void TestGetValue(const nsACString& aPingName, dom::Nullable& 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 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( 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( 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(); 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(std::numeric_limits::min()) || + roundedDurationNs > + static_cast(std::numeric_limits::max()))) { + // TODO(bug 1691073): Instrument this error. + return; + } fog_timing_distribution_accumulate_raw_nanos( - mId, uint64_t(aDuration.ToMicroseconds() * 1000.00)); + mId, static_cast(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>, + 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::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. -- cgit v1.2.3