diff --git a/CHANGELOG.md b/CHANGELOG.md index e388b55d4..b0bdbc40a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ * General * Adds the capability to merge remote metric configurations, enabling multiple Nimbus Features or components to share this functionality ([Bug 1833381](https://bugzilla.mozilla.org/show_bug.cgi?id=1833381)) * StringList metric type limits have been increased. The length of strings allowed has been increased from 50 to 100 to match the String metric type, and the list length has been increased from 20 to 100 ([Bug 1833870](https://bugzilla.mozilla.org/show_bug.cgi?id=1833870)) + * Make ping rate limiting configurable on Glean init. ([bug 1647630](https://bugzilla.mozilla.org/show_bug.cgi?id=1647630)) * Rust * Timing distribution traits now expose `accumulate_samples` and `accumulate_raw_samples_nanos`. This is a breaking change for consumers that make use of the trait as they will need to implement the new functions ([Bug 1829745](https://bugzilla.mozilla.org/show_bug.cgi?id=1829745)) * iOS diff --git a/glean-core/android/src/main/java/mozilla/telemetry/glean/Glean.kt b/glean-core/android/src/main/java/mozilla/telemetry/glean/Glean.kt index 7198f3e5b..3a094bed7 100644 --- a/glean-core/android/src/main/java/mozilla/telemetry/glean/Glean.kt +++ b/glean-core/android/src/main/java/mozilla/telemetry/glean/Glean.kt @@ -245,7 +245,8 @@ open class GleanInternalAPI internal constructor() { appBuild = "none", useCoreMps = false, trimDataToRegisteredPings = false, - logLevel = configuration.logLevel + logLevel = configuration.logLevel, + rateLimit = null ) val clientInfo = getClientInfo(configuration, buildInfo) val callbacks = OnGleanEventsImpl(this@GleanInternalAPI) diff --git a/glean-core/ios/Glean/Glean.swift b/glean-core/ios/Glean/Glean.swift index 56a91d3b7..32545f96b 100644 --- a/glean-core/ios/Glean/Glean.swift +++ b/glean-core/ios/Glean/Glean.swift @@ -192,6 +192,7 @@ public class Glean { useCoreMps: false, trimDataToRegisteredPings: false, logLevel: configuration.logLevel + rateLimit: nil, ) let clientInfo = getClientInfo(configuration, buildInfo: buildInfo) let callbacks = OnGleanEventsImpl(glean: self) diff --git a/glean-core/python/glean/glean.py b/glean-core/python/glean/glean.py index 5a82495a2..52f253487 100644 --- a/glean-core/python/glean/glean.py +++ b/glean-core/python/glean/glean.py @@ -231,6 +231,7 @@ class Glean: app_build=cls._application_build_id, trim_data_to_registered_pings=False, log_level=None, + rate_limit=None, ) _uniffi.glean_initialize(cfg, client_info, callbacks) diff --git a/glean-core/python/glean/net/ping_upload_worker.py b/glean-core/python/glean/net/ping_upload_worker.py index b843c0044..c80e2bbbc 100644 --- a/glean-core/python/glean/net/ping_upload_worker.py +++ b/glean-core/python/glean/net/ping_upload_worker.py @@ -121,6 +121,7 @@ def _process(data_dir: Path, application_id: str, configuration) -> bool: app_build="", trim_data_to_registered_pings=False, log_level=None, + rate_limit=None, ) if not glean_initialize_for_subprocess(cfg): log.error("Couldn't initialize Glean in subprocess") diff --git a/glean-core/rlb/src/configuration.rs b/glean-core/rlb/src/configuration.rs index 145f1a573..66200ee1a 100644 --- a/glean-core/rlb/src/configuration.rs +++ b/glean-core/rlb/src/configuration.rs @@ -38,6 +38,8 @@ pub struct Configuration { pub trim_data_to_registered_pings: bool, /// The internal logging level. pub log_level: Option, + /// The rate pings may be uploaded before they are throttled. + pub rate_limit: Option, } /// Configuration builder. @@ -75,6 +77,9 @@ pub struct Builder { /// Optional: The internal logging level. /// Default: `None` pub log_level: Option, + /// Optional: The internal ping upload rate limit. + /// Default: `None` + pub rate_limit: Option, } impl Builder { @@ -95,6 +100,7 @@ impl Builder { use_core_mps: false, trim_data_to_registered_pings: false, log_level: None, + rate_limit: None, } } @@ -111,6 +117,7 @@ impl Builder { use_core_mps: self.use_core_mps, trim_data_to_registered_pings: self.trim_data_to_registered_pings, log_level: self.log_level, + rate_limit: self.rate_limit, } } diff --git a/glean-core/rlb/src/lib.rs b/glean-core/rlb/src/lib.rs index d6ad16bdc..06c7786e0 100644 --- a/glean-core/rlb/src/lib.rs +++ b/glean-core/rlb/src/lib.rs @@ -119,6 +119,7 @@ fn initialize_internal(cfg: Configuration, client_info: ClientInfoMetrics) -> Op use_core_mps: cfg.use_core_mps, trim_data_to_registered_pings: cfg.trim_data_to_registered_pings, log_level: cfg.log_level, + rate_limit: cfg.rate_limit, }; glean_core::glean_initialize(core_cfg, client_info.into(), callbacks); diff --git a/glean-core/src/core/mod.rs b/glean-core/src/core/mod.rs index e83d8f4f8..c1d1dc9c3 100644 --- a/glean-core/src/core/mod.rs +++ b/glean-core/src/core/mod.rs @@ -19,8 +19,8 @@ use crate::storage::{StorageManager, INTERNAL_STORAGE}; use crate::upload::{PingUploadManager, PingUploadTask, UploadResult, UploadTaskAction}; use crate::util::{local_now_with_offset, sanitize_application_id}; use crate::{ - scheduler, system, CommonMetricData, ErrorKind, InternalConfiguration, Lifetime, Result, - DEFAULT_MAX_EVENTS, GLEAN_SCHEMA_VERSION, GLEAN_VERSION, KNOWN_CLIENT_ID, + scheduler, system, CommonMetricData, ErrorKind, InternalConfiguration, Lifetime, PingRateLimit, + Result, DEFAULT_MAX_EVENTS, GLEAN_SCHEMA_VERSION, GLEAN_VERSION, KNOWN_CLIENT_ID, }; static GLEAN: OnceCell> = OnceCell::new(); @@ -113,6 +113,7 @@ where /// use_core_mps: false, /// trim_data_to_registered_pings: false, /// log_level: None, +/// rate_limit: None, /// }; /// let mut glean = Glean::new(cfg).unwrap(); /// let ping = PingType::new("sample", true, false, vec![]); @@ -175,8 +176,13 @@ impl Glean { // Create an upload manager with rate limiting of 15 pings every 60 seconds. let mut upload_manager = PingUploadManager::new(&cfg.data_path, &cfg.language_binding_name); + let rate_limit = cfg.rate_limit.as_ref().unwrap_or(&PingRateLimit { + seconds_per_interval: 60, + pings_per_interval: 15, + }); upload_manager.set_rate_limiter( - /* seconds per interval */ 60, /* max pings per interval */ 15, + rate_limit.seconds_per_interval, + rate_limit.pings_per_interval, ); // We only scan the pending ping directories when calling this from a subprocess, @@ -295,6 +301,7 @@ impl Glean { use_core_mps: false, trim_data_to_registered_pings: false, log_level: None, + rate_limit: None, }; let mut glean = Self::new(cfg).unwrap(); diff --git a/glean-core/src/glean.udl b/glean-core/src/glean.udl index 2b62a8f10..ad5ed5587 100644 --- a/glean-core/src/glean.udl +++ b/glean-core/src/glean.udl @@ -73,6 +73,13 @@ dictionary InternalConfiguration { boolean use_core_mps; boolean trim_data_to_registered_pings; LevelFilter? log_level; + PingRateLimit? rate_limit; +}; + +// How to specify the rate pings may be uploaded before they are throttled. +dictionary PingRateLimit { + u64 seconds_per_interval; + u32 pings_per_interval; }; // An enum representing the different logging levels for the `log` crate. diff --git a/glean-core/src/lib.rs b/glean-core/src/lib.rs index 71e100252..036e0402c 100644 --- a/glean-core/src/lib.rs +++ b/glean-core/src/lib.rs @@ -128,6 +128,17 @@ pub struct InternalConfiguration { pub trim_data_to_registered_pings: bool, /// The internal logging level. pub log_level: Option, + /// The rate at which pings may be uploaded before they are throttled. + pub rate_limit: Option, +} + +/// How to specify the rate at which pings may be uploaded before they are throttled. +#[derive(Debug, Clone)] +pub struct PingRateLimit { + /// Length of time in seconds of a ping uploading interval. + pub seconds_per_interval: u64, + /// Number of pings that may be uploaded in a ping uploading interval. + pub pings_per_interval: u32, } /// Launches a new task on the global dispatch queue with a reference to the Glean singleton. diff --git a/samples/rust/src/main.rs b/samples/rust/src/main.rs index 82412580b..57e33cf38 100644 --- a/samples/rust/src/main.rs +++ b/samples/rust/src/main.rs @@ -38,6 +38,7 @@ fn main() { use_core_mps: true, trim_data_to_registered_pings: false, log_level: None, + rate_limit: None, }; let client_info = ClientInfoMetrics {