1#![deny(missing_docs)]
6
7use once_cell::sync::OnceCell;
42use std::sync::Mutex;
43
44pub use configuration::Configuration;
45pub use core_metrics::ClientInfoMetrics;
46pub use glean_core::{CommonMetricData, Error, Glean, Lifetime, Result};
47
48mod configuration;
49mod core_metrics;
50pub mod metrics;
51mod system;
52
53#[derive(Debug)]
54struct GleanWrapper {
55 instance: Glean,
56 channel: Option<String>,
57 client_info: ClientInfoMetrics,
58}
59
60static GLEAN: OnceCell<Mutex<GleanWrapper>> = OnceCell::new();
61
62fn global_glean() -> &'static Mutex<GleanWrapper> {
66 GLEAN.get().unwrap()
67}
68
69fn setup_glean(glean: GleanWrapper) -> Result<()> {
71 if GLEAN.get().is_none() {
72 GLEAN.set(Mutex::new(glean)).unwrap();
73 } else {
74 let mut lock = GLEAN.get().unwrap().lock().unwrap();
75 *lock = glean;
76 }
77 Ok(())
78}
79
80fn with_glean<F, R>(f: F) -> R
81where
82 F: Fn(&Glean) -> R,
83{
84 let lock = global_glean().lock().unwrap();
85 f(&lock.instance)
86}
87
88fn with_glean_wrapper_mut<F, R>(f: F) -> R
89where
90 F: Fn(&mut GleanWrapper) -> R,
91{
92 let mut lock = global_glean().lock().unwrap();
93 f(&mut lock)
94}
95
96fn with_glean_mut<F, R>(f: F) -> R
97where
98 F: Fn(&mut Glean) -> R,
99{
100 let mut lock = global_glean().lock().unwrap();
101 f(&mut lock.instance)
102}
103
104pub fn initialize(cfg: Configuration, client_info: ClientInfoMetrics) -> Result<()> {
108 let core_cfg = glean_core::Configuration {
109 upload_enabled: cfg.upload_enabled,
110 data_path: cfg.data_path.clone(),
111 application_id: cfg.application_id.clone(),
112 max_events: cfg.max_events,
113 delay_ping_lifetime_io: cfg.delay_ping_lifetime_io,
114 };
115 let glean = Glean::new(core_cfg)?;
116
117 initialize_core_metrics(&glean, &client_info, cfg.channel.clone());
119
120 let wrapper = GleanWrapper {
122 instance: glean,
123 channel: cfg.channel,
124 client_info,
125 };
126 setup_glean(wrapper)?;
127
128 Ok(())
129}
130
131fn initialize_core_metrics(
132 glean: &Glean,
133 client_info: &ClientInfoMetrics,
134 channel: Option<String>,
135) {
136 let core_metrics = core_metrics::InternalMetrics::new();
137
138 core_metrics
139 .app_build
140 .set(glean, &client_info.app_build[..]);
141 core_metrics
142 .app_display_version
143 .set(glean, &client_info.app_display_version[..]);
144 if let Some(app_channel) = channel {
145 core_metrics.app_channel.set(glean, app_channel);
146 }
147 core_metrics.os.set(glean, system::OS.to_string());
148 core_metrics.os_version.set(glean, "unknown".to_string());
149 core_metrics
150 .architecture
151 .set(glean, system::ARCH.to_string());
152 core_metrics
153 .device_manufacturer
154 .set(glean, "unknown".to_string());
155 core_metrics.device_model.set(glean, "unknown".to_string());
156}
157
158pub fn set_upload_enabled(enabled: bool) -> bool {
162 with_glean_wrapper_mut(|glean| {
163 let old_enabled = glean.instance.is_upload_enabled();
164 glean.instance.set_upload_enabled(enabled);
165
166 if !old_enabled && enabled {
167 initialize_core_metrics(&glean.instance, &glean.client_info, glean.channel.clone());
170 }
171
172 enabled
173 })
174}
175
176pub fn is_upload_enabled() -> bool {
180 with_glean(|glean| glean.is_upload_enabled())
181}
182
183pub fn register_ping_type(ping: &metrics::PingType) {
185 with_glean_mut(|glean| {
186 glean.register_ping_type(&ping.ping_type);
187 })
188}
189
190pub fn submit_ping(ping: &metrics::PingType) -> bool {
198 submit_ping_by_name(&ping.name)
199}
200
201pub fn submit_ping_by_name(ping: &str) -> bool {
209 submit_pings_by_name(&[ping.to_string()])
210}
211
212pub fn submit_pings_by_name(pings: &[String]) -> bool {
218 with_glean(|glean| glean.submit_pings_by_name(pings))
219}
220
221#[cfg(test)]
222mod test;