// -*- mode: Rust -*- // AUTOGENERATED BY glean_parser. DO NOT EDIT. {# The rendered source is autogenerated, but this Jinja2 template is not. Please file bugs! #} /* 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/. */ /// This file contains factory implementation information for the /// JOG Runtime Registration module. /// It is responsible for being able to build metrics and pings described at runtime. /// It is generated to keep it in sync with how the runtime definitions are defined. use std::borrow::Cow; use std::sync::atomic::{AtomicU32, Ordering}; use crate::private::{ CommonMetricData, Lifetime, MemoryUnit, TimeUnit, Ping, LabeledMetric, {% for metric_type_name in metric_types.keys() if not metric_type_name.startswith('labeled_') %} {{ metric_type_name|Camelize }}Metric, {% endfor %}}; use crate::private::traits::HistogramType; pub(crate) static DYNAMIC_METRIC_BIT: u32 = {{runtime_metric_bit}}; // 2**DYNAMIC_METRIC_BIT + 1 (+1 because we reserve the 0 metric id) static NEXT_METRIC_ID: AtomicU32 = AtomicU32::new({{2**runtime_metric_bit + 1}}); #[cfg(feature = "with_gecko")] // only used in submit_ping_by_id, which is gecko-only. pub(crate) static DYNAMIC_PING_BIT: u32 = {{runtime_ping_bit}}; // 2**DYNAMIC_PING_BIT + 1 (+1 because we reserve the 0 ping id) static NEXT_PING_ID: AtomicU32 = AtomicU32::new({{2**runtime_ping_bit + 1}}); pub(crate) mod __jog_metric_maps { use crate::metrics::DynamicLabel; use crate::private::MetricId; use crate::private::{ Ping, LabeledMetric, NoExtraKeys, {% for metric_type_name in metric_types.keys() %} {{ metric_type_name|Camelize }}Metric, {% endfor %} }; use once_cell::sync::Lazy; use std::collections::HashMap; use std::sync::{Arc, RwLock}; {% for metric_type_name in metric_types.keys() if metric_type_name != "event" and not metric_type_name.startswith('labeled_') %} pub static {{ metric_type_name.upper() }}_MAP: Lazy>>> = Lazy::new(|| Arc::new(RwLock::new(HashMap::new()))); {% endfor %} {# Labeled metrics are special because they're LabeledMetric #} {% for metric_type_name in metric_types.keys() if metric_type_name.startswith('labeled_') %} pub static {{ metric_type_name.upper() }}_MAP: Lazy>>>> = Lazy::new(|| Arc::new(RwLock::new(HashMap::new()))); {% endfor %} pub static PING_MAP: Lazy>>> = Lazy::new(|| Arc::new(RwLock::new(HashMap::new()))); {# Event metrics are special because they're EventMetric #} pub static EVENT_MAP: Lazy>>>> = Lazy::new(|| Arc::new(RwLock::new(HashMap::new()))); } #[derive(Debug)] struct MetricTypeNotFoundError(String); impl std::error::Error for MetricTypeNotFoundError {} impl std::fmt::Display for MetricTypeNotFoundError { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { write!(f, "Metric type {} not found", self.0) } } /// Creates and registers a metric, returning its type+id. pub fn create_and_register_metric( metric_type: &str, {# The rest of these are handrolled because it proved easier than maintaining a map of argument name to argument type. I may regret this if I need it again. #} {# In order of util.common_metric_args and util.extra_metric_args, because why not. #} category: String, name: String, send_in_pings: Vec, lifetime: Lifetime, disabled: bool, time_unit: Option, memory_unit: Option, allowed_extra_keys: Option>, {# Skipping reason_codes since that's a ping thing. #} range_min: Option, range_max: Option, bucket_count: Option, histogram_type: Option, numerators: Option>, {# And, don't forget the list of acceptable labels for a labeled metric. #} labels: Option>>, ) -> Result<(u32, u32), Box> { let metric_id = NEXT_METRIC_ID.fetch_add(1, Ordering::SeqCst); let metric32 = match metric_type { {% for metric_type_name, metric_type in metric_types.items() %} "{{ metric_type_name }}" => { let metric = {{ metric_type_name|Camelize if not metric_type_name.startswith('labeled_') else "Labeled"}}Metric::{% if metric_type_name == 'event' %}with_runtime_extra_keys{% else %}new{% endif %}(metric_id.into(), CommonMetricData { {% for arg_name in common_metric_data_args if arg_name in metric_type.args %} {{ arg_name }}, {% endfor %} ..Default::default() } {%- for arg_name in metric_type.args if arg_name not in common_metric_data_args -%} , {{ arg_name }}.unwrap() {%- endfor -%} {%- if metric_type_name.startswith('labeled_') -%} , labels {%- endif -%} ); let metric32: u32 = ({{metric_type.id}} << {{ID_BITS}}) | metric_id; assert!( __jog_metric_maps::{{metric_type_name.upper()}}_MAP.write()?.insert(metric_id.into(), metric).is_none(), "We should never insert a runtime metric with an already-used id." ); metric32 } {% endfor %} _ => return Err(Box::new(MetricTypeNotFoundError(metric_type.to_string()))) }; Ok((metric32, metric_id)) } /// Creates and registers a ping, returning its id. pub fn create_and_register_ping( ping_name: String, include_client_id: bool, send_if_empty: bool, reason_codes: Vec, ) -> Result> { let ping_id = NEXT_PING_ID.fetch_add(1, Ordering::SeqCst); let ping = Ping::new(ping_name, include_client_id, send_if_empty, reason_codes); assert!( __jog_metric_maps::PING_MAP.write()?.insert(ping_id.into(), ping).is_none(), "We should never insert a runtime ping with an already-used id." ); Ok(ping_id) }