Source code

Revision control

Copy as Markdown

Other Tools

// -*- 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/. */
{% macro generate_structure(name, struct) %}
{% if struct.type == "array" %}
pub type {{ name }} = Vec<{{ name }}Item>;
{{ generate_structure(name ~ "Item", struct["items"]) -}}
{% elif struct.type == "object" %}
#[derive(Debug, Hash, Eq, PartialEq, ::glean::traits::__serde::Serialize, ::glean::traits::__serde::Deserialize)]
#[serde(deny_unknown_fields)]
pub struct {{ name }} {
{% for itemname, val in struct.properties.items() %}
{% if val.type == "object" %}
pub {{itemname|snake_case}}: {{ name ~ "Item" ~ itemname|Camelize ~ "Object" }},
{% elif val.type == "array" %}
pub {{itemname|snake_case}}: {{ name ~ "Item" ~ itemname|Camelize }},
{% else %}
pub {{itemname|snake_case}}: Option<{{val.type|structure_type_name}}>,
{% endif %}
{% endfor %}
}
{% for itemname, val in struct.properties.items() %}
{% if val.type == "array" %}
{% set nested_name = name ~ "Item" ~ itemname|Camelize %}
{{ generate_structure(nested_name, val) -}}
{% elif val.type == "object" %}
{% set nested_name = name ~ "Item" ~ itemname|Camelize ~ "Object" %}
{{ generate_structure(nested_name, val) -}}
{% endif %}
{% endfor %}
{% else %}
pub type {{ name }} = {{ struct.type|structure_type_name }};
{% endif %}
{% endmacro %}
{% macro generate_extra_keys(obj) -%}
{% for name, _ in obj["_generate_enums"] %}
{# we always use the `extra` suffix, because we only expose the new event API #}
{% set suffix = "Extra" %}
{% if obj|attr(name)|length %}
{{ extra_keys_with_types(obj, name, suffix)|indent }}
{% endif %}
{% endfor %}
{%- endmacro -%}
{%- macro extra_keys_with_types(obj, name, suffix) -%}
#[derive(Default, Debug, Clone, Hash, Eq, PartialEq)]
pub struct {{ obj.name|Camelize }}{{ suffix }} {
{% for item, type in obj|attr(name) %}
pub {{ item|snake_case }}: Option<{{type|extra_type_name}}>,
{% endfor %}
}
impl ExtraKeys for {{ obj.name|Camelize }}{{ suffix }} {
const ALLOWED_KEYS: &'static [&'static str] = {{ obj.allowed_extra_keys|extra_keys }};
fn into_ffi_extra(self) -> ::std::collections::HashMap<String, String> {
let mut map = ::std::collections::HashMap::new();
{% for key, _ in obj|attr(name) %}
self.{{key|snake_case}}.and_then(|val| map.insert("{{key|snake_case}}".into(), val.to_string()));
{% endfor %}
map
}
}
{%- endmacro -%}
{% macro generate_label_enum(obj) %}
#[repr(u16)]
pub enum {{ obj.name|Camelize }}Label {
{% for label in obj.ordered_labels %}
{# Specifically _not_ using r# as C++ doesn't have it #}
{{ label|Camelize }} = {{loop.index0}},
{% endfor %}
__Other__,
}
impl From<u16> for {{ obj.name|Camelize }}Label {
fn from(v: u16) -> Self {
match v {
{% for label in obj.ordered_labels %}
{{ loop.index0 }} => Self::{{ label|Camelize }},
{% endfor %}
_ => Self::__Other__,
}
}
}
impl Into<&'static str> for {{ obj.name|Camelize }}Label {
fn into(self) -> &'static str {
match self {
{% for label in obj.ordered_labels %}
Self::{{ label| Camelize }} => "{{label}}",
{% endfor %}
Self::__Other__ => "__other__",
}
}
}
{%- endmacro -%}
pub enum DynamicLabel { }
{% for category_name, objs in all_objs.items() %}
pub mod {{ category_name|snake_case }} {
use crate::private::*;
#[allow(unused_imports)] // CommonMetricData might be unused, let's avoid warnings
use glean::CommonMetricData;
#[allow(unused_imports)] // HistogramType might be unusued, let's avoid warnings
use glean::HistogramType;
use once_cell::sync::Lazy;
#[allow(unused_imports)]
use std::convert::TryFrom;
{% for obj in objs.values() %}
{% if obj|attr("_generate_enums") %}
{{ generate_extra_keys(obj) }}
{%- endif %}
{% if obj.labeled and obj.labels and obj.labels|length %}
{{ generate_label_enum(obj)|indent }}
{% endif %}
{% if obj|attr("_generate_structure") %}
{{ generate_structure(obj.name|Camelize ~ "Object", obj._generate_structure) -}}
{% endif %}
#[allow(non_upper_case_globals)]
/// generated from {{ category_name }}.{{ obj.name }}
///
/// {{ obj.description|wordwrap() | replace('\n', '\n /// ') }}
{% if obj.type == "counter" and obj.send_in_pings|length == 1 and not obj.disabled and obj.lifetime|rust == "Lifetime::Ping" %}
{# Use optimized CounterMetric ctor in a common case (esp. for Use Counters) #}
pub static {{ obj.name|snake_case }}: Lazy<{{ obj|type_name }}> = Lazy::new(|| {
CounterMetric::codegen_new(
{{obj|metric_id}},
"{{obj.category}}",
"{{obj.name}}",
"{{obj.send_in_pings[0]}}"
)
});
{% else %}
pub static {{ obj.name|snake_case }}: Lazy<{{ obj|type_name }}> = Lazy::new(|| {
{{ obj|ctor }}({{obj|metric_id}}.into(), CommonMetricData {
{% for arg_name in common_metric_data_args if obj[arg_name] is defined %}
{{ arg_name }}: {{ obj[arg_name]|rust }},
{% endfor %}
..Default::default()
}
{%- for arg_name in extra_args if obj[arg_name] is defined and arg_name not in common_metric_data_args and arg_name != 'allowed_extra_keys' -%}
, {{ obj[arg_name]|rust }}
{%- endfor -%}
{{ ", " if obj.labeled else ")\n" }}
{%- if obj.labeled -%}
{%- if obj.labels -%}
Some({{ obj.labels|rust }})
{%- else -%}
None
{%- endif -%})
{% endif %}
});
{% endif %}
{% endfor %}
}
{% endfor %}
{% if metric_by_type|length > 0 %}
#[allow(dead_code)]
pub(crate) mod __glean_metric_maps {
use std::collections::HashMap;
use crate::metrics::extra_keys_len;
use crate::private::*;
use once_cell::sync::Lazy;
{% for typ, metrics in metric_by_type.items() %}
pub static {{typ.0}}: Lazy<HashMap<MetricId, &Lazy<{{typ.1}}>>> = Lazy::new(|| {
let mut map = HashMap::with_capacity({{metrics|length}});
{% for metric in metrics %}
map.insert({{metric.0}}.into(), &super::{{metric.1}});
{% endfor %}
map
});
{% endfor %}
pub(crate) fn set_object_by_id(metric_id: u32, value: String) -> Result<(), ()> {
match metric_id {
{% for metric_id, object in objects_by_id.items() %}
{{metric_id}} => {
super::{{object}}.set_string(value);
Ok(())
}
{% endfor %}
_ => Err(()),
}
}
/// Wrapper to get the currently stored object for object metric as a string.
///
/// # Arguments
///
/// * `metric_id` - The metric's ID to look up
/// * `ping_name` - (Optional) The ping name to look into.
/// Defaults to the first value in `send_in_pings`.
///
/// # Returns
///
/// Returns the recorded object serialized as a JSON string or `None` if nothing stored.
///
/// # Panics
///
/// Panics if no object by the given metric ID could be found.
pub(crate) fn object_test_get_value(metric_id: u32, ping_name: Option<String>) -> Option<String> {
match metric_id {
{% for metric_id, object in objects_by_id.items() %}
{{metric_id}} => super::{{object}}.test_get_value_as_str(ping_name.as_deref()),
{% endfor %}
_ => panic!("No object for metric id {}", metric_id),
}
}
/// Check the provided object for errors.
///
/// # Arguments
///
/// * `metric_id` - The metric's ID to look up
///
/// # Returns
///
/// Returns a string for the recorded error or `None`.
///
/// # Panics
///
/// Panics if no object by the given metric ID could be found.
#[allow(unused_variables)]
pub(crate) fn object_test_get_error(metric_id: u32) -> Option<String> {
#[cfg(feature = "with_gecko")]
match metric_id {
{% for metric_id, object in objects_by_id.items() %}
{{metric_id}} => test_get_errors!(super::{{object}}),
{% endfor %}
_ => panic!("No object for metric id {}", metric_id),
}
#[cfg(not(feature = "with_gecko"))]
{
return None;
}
}
/// Wrapper to record an event based on its metric ID.
///
/// # Arguments
///
/// * `metric_id` - The metric's ID to look up
/// * `extra` - An map of (extra key id, string) pairs.
/// The map will be decoded into the appropriate `ExtraKeys` type.
/// # Returns
///
/// Returns `Ok(())` if the event was found and `record` was called with the given `extra`,
/// or an `EventRecordingError::InvalidId` if no event by that ID exists
/// or an `EventRecordingError::InvalidExtraKey` if the `extra` map could not be deserialized.
pub(crate) fn record_event_by_id(metric_id: u32, extra: HashMap<String, String>) -> Result<(), EventRecordingError> {
match metric_id {
{% for metric_id, event in events_by_id.items() %}
{{metric_id}} => {
assert!(
extra_keys_len(&super::{{event}}) != 0 || extra.is_empty(),
"No extra keys allowed, but some were passed"
);
super::{{event}}.record_raw(extra);
Ok(())
}
{% endfor %}
_ => Err(EventRecordingError::InvalidId),
}
}
/// Wrapper to record an event based on its metric ID, with a provided timestamp.
///
/// # Arguments
///
/// * `metric_id` - The metric's ID to look up
/// * `timestamp` - The time at which this event was recorded.
/// * `extra` - An map of (extra key id, string) pairs.
/// The map will be decoded into the appropriate `ExtraKeys` type.
/// # Returns
///
/// Returns `Ok(())` if the event was found and `record` was called with the given `extra`,
/// or an `EventRecordingError::InvalidId` if no event by that ID exists
/// or an `EventRecordingError::InvalidExtraKey` if the event doesn't take extra pairs,
/// but some are passed in.
pub(crate) fn record_event_by_id_with_time(metric_id: MetricId, timestamp: u64, extra: HashMap<String, String>) -> Result<(), EventRecordingError> {
match metric_id {
{% for metric_id, event in events_by_id.items() %}
MetricId({{metric_id}}) => {
if extra_keys_len(&super::{{event}}) == 0 && !extra.is_empty() {
return Err(EventRecordingError::InvalidExtraKey);
}
super::{{event}}.record_with_time(timestamp, extra);
Ok(())
}
{% endfor %}
_ => Err(EventRecordingError::InvalidId),
}
}
/// Wrapper to get the currently stored events for event metric.
///
/// # Arguments
///
/// * `metric_id` - The metric's ID to look up
/// * `ping_name` - (Optional) The ping name to look into.
/// Defaults to the first value in `send_in_pings`.
///
/// # Returns
///
/// Returns the recorded events or `None` if nothing stored.
///
/// # Panics
///
/// Panics if no event by the given metric ID could be found.
pub(crate) fn event_test_get_value_wrapper(metric_id: u32, ping_name: Option<String>) -> Option<Vec<RecordedEvent>> {
match metric_id {
{% for metric_id, event in events_by_id.items() %}
{{metric_id}} => super::{{event}}.test_get_value(ping_name.as_deref()),
{% endfor %}
_ => panic!("No event for metric id {}", metric_id),
}
}
/// Check the provided event for errors.
///
/// # Arguments
///
/// * `metric_id` - The metric's ID to look up
/// * `ping_name` - (Optional) The ping name to look into.
/// Defaults to the first value in `send_in_pings`.
///
/// # Returns
///
/// Returns a string for the recorded error or `None`.
///
/// # Panics
///
/// Panics if no event by the given metric ID could be found.
#[allow(unused_variables)]
pub(crate) fn event_test_get_error(metric_id: u32) -> Option<String> {
#[cfg(feature = "with_gecko")]
match metric_id {
{% for metric_id, event in events_by_id.items() %}
{{metric_id}} => test_get_errors!(super::{{event}}),
{% endfor %}
_ => panic!("No event for metric id {}", metric_id),
}
#[cfg(not(feature = "with_gecko"))]
{
return None;
}
}
{% for labeled_type, labeleds_by_id in labeleds_by_id_by_type.items() %}
/// Gets the submetric from the specified labeled_{{labeled_type}} metric.
///
/// # Arguments
///
/// * `metric_id` - The metric's ID to look up
/// * `label` - The label identifying the {{labeled_type}} submetric.
///
/// # Returns
///
/// Returns the {{labeled_type}} submetric.
///
/// # Panics
///
/// Panics if no labeled_{{labeled_type}} by the given metric ID could be found.
#[allow(unused_variables)]
pub(crate) fn labeled_{{labeled_type}}_get(metric_id: u32, label: &str) -> Labeled{{labeled_type|Camelize}}Metric {
match metric_id {
{% for metric_id, (labeled, _) in labeleds_by_id.items() %}
{{metric_id}} => super::{{labeled}}.get(label),
{% endfor %}
_ => panic!("No labeled_{{labeled_type}} for metric id {}", metric_id),
}
}
/// Gets the submetric from the specified labeled_{{labeled_type}} metric, by enum.
///
/// # Arguments
///
/// * `metric_id` - The metric's ID to look up
/// * `label_enum` - The label enum identifying the {{labeled_type}} submetric.
///
/// # Returns
///
/// Returns the {{labeled_type}} submetric.
///
/// # Panics
///
/// Panics if no labeled_{{labeled_type}} by the given metric ID could be found.
#[allow(unused_variables)]
pub(crate) fn labeled_{{labeled_type}}_enum_get(metric_id: u32, label_enum: u16) -> Labeled{{labeled_type|Camelize}}Metric {
match metric_id {
{% for metric_id, (labeled, has_enum) in labeleds_by_id.items() %}
{% if has_enum %}
{{metric_id}} => super::{{labeled}}.get(labeled_enum_to_str(metric_id, label_enum)),
{% endif %}
{% endfor %}
_ => panic!("No labeled_{{labeled_type}} for metric id {}", metric_id),
}
}
{% endfor %}
pub(crate) fn labeled_enum_to_str(metric_id: u32, label: u16) -> &'static str {
match metric_id {
{% for category_name, objs in all_objs.items() %}
{% for obj in objs.values() %}
{% if obj.labeled and obj.labels and obj.labels|length %}
{{obj|metric_id}} => super::{{category_name|snake_case}}::{{obj.name|Camelize}}Label::from(label).into(),
{% endif %}
{% endfor %}
{% endfor %}
_ => panic!("Can't turn label enum to string for metric {} which isn't a labeled metric with static labels", metric_id),
}
}
pub(crate) mod submetric_maps {
use std::sync::{
atomic::AtomicU32,
RwLock,
};
use super::*;
pub(crate) const SUBMETRIC_BIT: u32 = {{submetric_bit}};
pub(crate) static NEXT_LABELED_SUBMETRIC_ID: AtomicU32 = AtomicU32::new((1 << SUBMETRIC_BIT) + 1);
pub(crate) static LABELED_METRICS_TO_IDS: Lazy<RwLock<HashMap<(u32, String), u32>>> = Lazy::new(||
RwLock::new(HashMap::new())
);
pub(crate) static LABELED_ENUMS_TO_IDS: Lazy<RwLock<HashMap<(u32, u16), u32>>> = Lazy::new(||
RwLock::new(HashMap::new())
);
{% for typ, metrics in metric_by_type.items() %}
{% if typ.0 in ('BOOLEAN_MAP', 'COUNTER_MAP', 'STRING_MAP') %}
pub static {{typ.0}}: Lazy<RwLock<HashMap<MetricId, Labeled{{typ.1}}>>> = Lazy::new(||
RwLock::new(HashMap::new())
);
{% endif %}
{% endfor%}
}
}
{% endif %}