mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-18 15:55:36 +00:00
Bug 1623300 - Implement the remaining parts of the control API. r=chutten
Controlling is two things: * initializing Glean * toggling upload enabled. Initializing also means setting the internal metrics (client info), some of which we detect at build time. `upload_enabled` will eventually be tied to the Firefox Telemetry upload preference. Differential Revision: https://phabricator.services.mozilla.com/D68543 --HG-- extra : moz-landing-system : lando
This commit is contained in:
parent
d8523c3a61
commit
1eba67a2fb
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -1368,6 +1368,7 @@ dependencies = [
|
||||
"log",
|
||||
"nserror",
|
||||
"nsstring",
|
||||
"once_cell",
|
||||
"static_prefs",
|
||||
"xpcom",
|
||||
]
|
||||
|
@ -12,3 +12,4 @@ nserror = { path = "../../../xpcom/rust/nserror" }
|
||||
nsstring = { path = "../../../xpcom/rust/nsstring" }
|
||||
static_prefs = { path = "../../../modules/libpref/init/static_prefs" }
|
||||
xpcom = { path = "../../../xpcom/rust/xpcom" }
|
||||
once_cell = "1.2.0"
|
||||
|
125
toolkit/components/glean/src/api.rs
Normal file
125
toolkit/components/glean/src/api.rs
Normal file
@ -0,0 +1,125 @@
|
||||
// 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/.
|
||||
|
||||
//! The general API to initialize and control Glean.
|
||||
//!
|
||||
//! ## Example
|
||||
//!
|
||||
//! ```ignore
|
||||
//! let configuration = Configuration { /* ... */ };
|
||||
//! let client_info = ClientInfo { /* ... */ };
|
||||
//!
|
||||
//! // Initialize Glean once and passing in client information.
|
||||
//! initialize(configuration, client_info)?;
|
||||
//!
|
||||
//! // Toggle the upload enabled preference.
|
||||
//! set_upload_enabled(false);
|
||||
//! ```
|
||||
|
||||
use glean_core::{global_glean, setup_glean, Configuration, Glean, Result};
|
||||
use once_cell::sync::OnceCell;
|
||||
|
||||
use crate::client_info::ClientInfo;
|
||||
use crate::core_metrics::InternalMetrics;
|
||||
|
||||
/// Application state to keep track of.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct AppState {
|
||||
/// Client info metrics set by the application.
|
||||
client_info: ClientInfo,
|
||||
}
|
||||
|
||||
/// A global singleton storing additional state for Glean.
|
||||
static STATE: OnceCell<AppState> = OnceCell::new();
|
||||
|
||||
/// Get a reference to the global state object.
|
||||
///
|
||||
/// Panics if no global state object was set.
|
||||
fn global_state() -> &'static AppState {
|
||||
STATE.get().unwrap()
|
||||
}
|
||||
|
||||
/// Run a closure with a mutable reference to the locked global Glean object.
|
||||
fn with_glean_mut<F, R>(f: F) -> R
|
||||
where
|
||||
F: Fn(&mut Glean) -> R,
|
||||
{
|
||||
let mut glean = global_glean().lock().unwrap();
|
||||
f(&mut glean)
|
||||
}
|
||||
|
||||
/// Create and initialize a new Glean object.
|
||||
///
|
||||
/// See `glean_core::Glean::new`.
|
||||
///
|
||||
/// ## Thread safety
|
||||
///
|
||||
/// Many threads may call `initialize` concurrently with different configuration and client info,
|
||||
/// but it is guaranteed that only one function will be executed.
|
||||
///
|
||||
/// Glean will only be initialized exactly once with the configuration and client info obtained
|
||||
/// from the first call.
|
||||
/// Subsequent calls have no effect.
|
||||
pub fn initialize(cfg: Configuration, client_info: ClientInfo) -> Result<()> {
|
||||
STATE
|
||||
.get_or_try_init(|| {
|
||||
let glean = Glean::new(cfg)?;
|
||||
|
||||
// First initialize core metrics
|
||||
initialize_core_metrics(&glean, &client_info);
|
||||
|
||||
// Now make this the global object available to others.
|
||||
setup_glean(glean)?;
|
||||
|
||||
Ok(AppState { client_info })
|
||||
})
|
||||
.map(|_| ())
|
||||
}
|
||||
|
||||
/// Set the application's core metrics based on the passed client info.
|
||||
fn initialize_core_metrics(glean: &Glean, client_info: &ClientInfo) {
|
||||
let core_metrics = InternalMetrics::new();
|
||||
|
||||
core_metrics
|
||||
.app_build
|
||||
.set(glean, &client_info.app_build[..]);
|
||||
core_metrics
|
||||
.app_display_version
|
||||
.set(glean, &client_info.app_display_version[..]);
|
||||
if let Some(app_channel) = &client_info.channel {
|
||||
core_metrics.app_channel.set(glean, app_channel);
|
||||
}
|
||||
// FIXME(bug 1625916): OS should be handled inside glean-core.
|
||||
core_metrics.os.set(glean, "unknown".to_string());
|
||||
core_metrics
|
||||
.os_version
|
||||
.set(glean, &client_info.os_version[..]);
|
||||
// FIXME(bug 1624823): Architecture should be determined at runtime
|
||||
core_metrics.architecture.set(glean, "unknown");
|
||||
// FIXME(bug 1625207): Device manufacturer should be made optional.
|
||||
core_metrics
|
||||
.device_manufacturer
|
||||
.set(glean, "unknown".to_string());
|
||||
// FIXME(bug 1624823): Device model should be made optional.
|
||||
core_metrics.device_model.set(glean, "unknown".to_string());
|
||||
}
|
||||
|
||||
/// Set whether upload is enabled or not.
|
||||
///
|
||||
/// See `glean_core::Glean.set_upload_enabled`.
|
||||
pub fn set_upload_enabled(enabled: bool) -> bool {
|
||||
with_glean_mut(|glean| {
|
||||
let state = global_state();
|
||||
let old_enabled = glean.is_upload_enabled();
|
||||
glean.set_upload_enabled(enabled);
|
||||
|
||||
if !old_enabled && enabled {
|
||||
// If uploading is being re-enabled, we have to restore the
|
||||
// application-lifetime metrics.
|
||||
initialize_core_metrics(&glean, &state.client_info);
|
||||
}
|
||||
|
||||
enabled
|
||||
})
|
||||
}
|
@ -3,7 +3,7 @@
|
||||
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
|
||||
/// Metrics included in every ping as `client_info`.
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ClientInfo {
|
||||
/// The build identifier generated by the CI system (e.g. "1234/A").
|
||||
pub app_build: String,
|
||||
|
92
toolkit/components/glean/src/core_metrics.rs
Normal file
92
toolkit/components/glean/src/core_metrics.rs
Normal file
@ -0,0 +1,92 @@
|
||||
// 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/.
|
||||
|
||||
//! Internal metrics used to fill in the [client info section][client_info] included in every ping.
|
||||
//!
|
||||
//! [client_info]: https://mozilla.github.io/glean/book/user/pings/index.html#the-client_info-section
|
||||
|
||||
use glean_core::{metrics::StringMetric, CommonMetricData, Lifetime};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct InternalMetrics {
|
||||
pub app_build: StringMetric,
|
||||
pub app_display_version: StringMetric,
|
||||
pub app_channel: StringMetric,
|
||||
pub os: StringMetric,
|
||||
pub os_version: StringMetric,
|
||||
pub architecture: StringMetric,
|
||||
pub device_manufacturer: StringMetric,
|
||||
pub device_model: StringMetric,
|
||||
}
|
||||
|
||||
impl InternalMetrics {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
app_build: StringMetric::new(CommonMetricData {
|
||||
name: "app_build".into(),
|
||||
category: "".into(),
|
||||
send_in_pings: vec!["glean_client_info".into()],
|
||||
lifetime: Lifetime::Application,
|
||||
disabled: false,
|
||||
dynamic_label: None,
|
||||
}),
|
||||
app_display_version: StringMetric::new(CommonMetricData {
|
||||
name: "app_display_version".into(),
|
||||
category: "".into(),
|
||||
send_in_pings: vec!["glean_client_info".into()],
|
||||
lifetime: Lifetime::Application,
|
||||
disabled: false,
|
||||
dynamic_label: None,
|
||||
}),
|
||||
app_channel: StringMetric::new(CommonMetricData {
|
||||
name: "app_channel".into(),
|
||||
category: "".into(),
|
||||
send_in_pings: vec!["glean_client_info".into()],
|
||||
lifetime: Lifetime::Application,
|
||||
disabled: false,
|
||||
dynamic_label: None,
|
||||
}),
|
||||
os: StringMetric::new(CommonMetricData {
|
||||
name: "os".into(),
|
||||
category: "".into(),
|
||||
send_in_pings: vec!["glean_client_info".into()],
|
||||
lifetime: Lifetime::Application,
|
||||
disabled: false,
|
||||
dynamic_label: None,
|
||||
}),
|
||||
os_version: StringMetric::new(CommonMetricData {
|
||||
name: "os_version".into(),
|
||||
category: "".into(),
|
||||
send_in_pings: vec!["glean_client_info".into()],
|
||||
lifetime: Lifetime::Application,
|
||||
disabled: false,
|
||||
dynamic_label: None,
|
||||
}),
|
||||
architecture: StringMetric::new(CommonMetricData {
|
||||
name: "architecture".into(),
|
||||
category: "".into(),
|
||||
send_in_pings: vec!["glean_client_info".into()],
|
||||
lifetime: Lifetime::Application,
|
||||
disabled: false,
|
||||
dynamic_label: None,
|
||||
}),
|
||||
device_manufacturer: StringMetric::new(CommonMetricData {
|
||||
name: "device_manufacturer".into(),
|
||||
category: "".into(),
|
||||
send_in_pings: vec!["glean_client_info".into()],
|
||||
lifetime: Lifetime::Application,
|
||||
disabled: false,
|
||||
dynamic_label: None,
|
||||
}),
|
||||
device_model: StringMetric::new(CommonMetricData {
|
||||
name: "device_model".into(),
|
||||
category: "".into(),
|
||||
send_in_pings: vec!["glean_client_info".into()],
|
||||
lifetime: Lifetime::Application,
|
||||
disabled: false,
|
||||
dynamic_label: None,
|
||||
}),
|
||||
}
|
||||
}
|
||||
}
|
@ -2,6 +2,21 @@
|
||||
// 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/.
|
||||
|
||||
//! Firefox on Glean (FOG) is the name of the layer that integrates the [Glean SDK][glean-sdk] into Firefox Desktop.
|
||||
//! It is currently being designed and implemented.
|
||||
//!
|
||||
//! The [Glean SDK][glean-sdk] is a data collection library built by Mozilla for use in its products.
|
||||
//! Like [Telemetry][telemetry], it can be used to
|
||||
//! (in accordance with our [Privacy Policy][privacy-policy])
|
||||
//! send anonymous usage statistics to Mozilla in order to make better decisions.
|
||||
//!
|
||||
//! Documentation can be found online in the [Firefox Source Docs][docs].
|
||||
//!
|
||||
//! [glean-sdk]: https://github.com/mozilla/glean/
|
||||
//! [book-of-glean]: https://mozilla.github.io/glean/book/index.html
|
||||
//! [privacy-policy]: https://www.mozilla.org/privacy/
|
||||
//! [docs]: https://firefox-source-docs.mozilla.org/toolkit/components/glean/
|
||||
|
||||
use std::ffi::CStr;
|
||||
use std::os::raw::c_char;
|
||||
|
||||
@ -10,8 +25,14 @@ use nserror::{nsresult, NS_OK};
|
||||
use client_info::ClientInfo;
|
||||
use glean_core::Configuration;
|
||||
|
||||
mod api;
|
||||
mod client_info;
|
||||
mod core_metrics;
|
||||
|
||||
/// Project FOG's entry point.
|
||||
///
|
||||
/// This assembles client information and the Glean configuration and then initializes the global
|
||||
/// Glean instance.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn fog_init(
|
||||
app_build: *const c_char,
|
||||
|
Loading…
Reference in New Issue
Block a user