Bug 1675114 - Add Dispatcher and IPC support to FOG Pings r=janerik
authorChris H-C <chutten@mozilla.com>
Mon, 09 Nov 2020 10:43:46 +0000
changeset 556410 897365592259b24599153d7311321bef038aa6f4
parent 556409 644272d24cfbe015aa867540353aff8ae9f9df93
child 556411 d1443dd277ee81771bd749115f9a39e04e53a9da
push id37935
push usernbeleuzu@mozilla.com
push dateMon, 09 Nov 2020 21:53:49 +0000
treeherdermozilla-central@6659b306f585 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjanerik
bugs1675114
milestone84.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1675114 - Add Dispatcher and IPC support to FOG Pings r=janerik Differential Revision: https://phabricator.services.mozilla.com/D95865
toolkit/components/glean/api/src/private/ping.rs
--- a/toolkit/components/glean/api/src/private/ping.rs
+++ b/toolkit/components/glean/api/src/private/ping.rs
@@ -1,17 +1,26 @@
 // 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 https://mozilla.org/MPL/2.0/.
 
+use std::sync::Arc;
+
+use crate::{dispatcher, ipc::need_ipc};
+
 /// A Glean ping.
 ///
 /// See [Glean Pings](https://mozilla.github.io/glean/book/user/pings/index.html).
 #[derive(Clone, Debug)]
-pub struct Ping(glean_core::metrics::PingType);
+pub enum Ping {
+    Parent(Arc<PingImpl>),
+    Child,
+}
+#[derive(Debug)]
+pub struct PingImpl(glean_core::metrics::PingType);
 
 impl Ping {
     /// Create a new ping type for the given name, whether to include the client ID and whether to
     /// send this ping empty.
     ///
     /// ## Arguments
     ///
     /// * `name` - The name of the ping.
@@ -19,75 +28,104 @@ impl Ping {
     /// * `send_if_empty` - Whether the ping should be sent empty or not.
     /// * `reason_codes` - The valid reason codes for this ping.
     pub fn new<S: Into<String>>(
         name: S,
         include_client_id: bool,
         send_if_empty: bool,
         reason_codes: Vec<String>,
     ) -> Self {
+        if need_ipc() {
+            Ping::Child
+        } else {
+            Ping::Parent(Arc::new(PingImpl::new(
+                name,
+                include_client_id,
+                send_if_empty,
+                reason_codes,
+            )))
+        }
+    }
+
+    /// Collect and submit the ping for eventual upload.
+    ///
+    /// This will collect all stored data to be included in the ping.
+    /// Data with lifetime `ping` will then be reset.
+    ///
+    /// If the ping is configured with `send_if_empty = false`
+    /// and the ping currently contains no content,
+    /// it will not be queued for upload.
+    /// If the ping is configured with `send_if_empty = true`
+    /// it will be queued for upload even if otherwise empty.
+    ///
+    /// Pings always contain the `ping_info` and `client_info` sections.
+    /// See [ping sections](https://mozilla.github.io/glean/book/user/pings/index.html#ping-sections)
+    /// for details.
+    ///
+    /// ## Parameters
+    /// * `reason` - The reason the ping is being submitted.
+    ///              Must be one of the configured `reason_codes`.
+    pub fn submit(&self, reason: Option<&str>) {
+        match self {
+            Ping::Parent(p) => {
+                let ping = Arc::clone(&p);
+                let reason = reason.map(|x| x.to_owned());
+                dispatcher::launch(move || ping.submit(reason.as_deref()));
+            }
+            Ping::Child => {
+                log::error!(
+                    "Unable to submit ping {:?} in non-main process. Ignoring.",
+                    self
+                );
+                // TODO: Record an error.
+            }
+        };
+    }
+}
+
+impl PingImpl {
+    pub fn new<S: Into<String>>(
+        name: S,
+        include_client_id: bool,
+        send_if_empty: bool,
+        reason_codes: Vec<String>,
+    ) -> Self {
         let ping = glean_core::metrics::PingType::new(
             name,
             include_client_id,
             send_if_empty,
             reason_codes,
         );
 
         crate::with_glean(|glean| {
             glean.register_ping_type(&ping);
         });
 
         Self(ping)
     }
 
-    /// Collect and submit the ping for eventual upload.
-    ///
-    /// This will collect all stored data to be included in the ping.
-    /// Data with lifetime `ping` will then be reset.
-    ///
-    /// If the ping is configured with `send_if_empty = false`
-    /// and the ping currently contains no content,
-    /// it will not be queued for upload.
-    /// If the ping is configured with `send_if_empty = true`
-    /// it will be queued for upload even if otherwise empty.
-    ///
-    /// Pings always contain the `ping_info` and `client_info` sections.
-    /// See [ping sections](https://mozilla.github.io/glean/book/user/pings/index.html#ping-sections)
-    /// for details.
-    ///
-    /// ## Parameters
-    /// * `reason` - The reason the ping is being submitted.
-    ///              Must be one of the configured `reason_codes`.
-    ///
-    /// ## Return value
-    ///
-    /// Returns true if a ping was assembled and queued, false otherwise.
-    pub fn submit(&self, reason: Option<&str>) -> bool {
+    pub fn submit(&self, reason: Option<&str>) {
         let res = crate::with_glean(|glean| self.0.submit(glean, reason).unwrap_or(false));
         if res {
             crate::ping_upload::check_for_uploads();
         }
-        res
     }
 }
 
 #[cfg(test)]
 mod test {
     use once_cell::sync::Lazy;
 
     use super::*;
     use crate::common_test::*;
 
     // Smoke test for what should be the generated code.
     static PROTOTYPE_PING: Lazy<Ping> = Lazy::new(|| Ping::new("prototype", false, true, vec![]));
 
     #[test]
     fn smoke_test_custom_ping() {
         let _lock = lock_test();
-        // TODO: Submit through the dispatcher.
-        // For now we wait for glean to initialize to not crash.
-        crate::dispatcher::block_on_queue();
 
         // We can only check that nothing explodes.
-        // `true` signals that the ping has been succesfully submitted (and written to disk).
-        assert_eq!(true, PROTOTYPE_PING.submit(None));
+        // More comprehensive tests are blocked on bug 1673660.
+        PROTOTYPE_PING.submit(None);
     }
 }