Source code
Revision control
Copy as Markdown
Other Tools
// 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
use std::{collections::HashMap, marker::PhantomData};
/// Types defined in `glean.udl` and used in the public API.
///
/// For now these are a copy of the same types in `glean-core`.
/// We can probably generate (most of) them from the UDL definition as well
/// (or share the glean-core implementation otherwise),
/// but for the experimentation phase of `glean-sym` we stick with a manual copy to get it going.
#[derive(uniffi::Enum, Default)]
pub enum Lifetime {
#[default]
Ping,
Application,
User,
}
#[derive(uniffi::Enum)]
pub enum MetricLabel {
Static(String),
Label(String),
KeyOnly(String, String),
CategoryOnly(String, String),
KeyAndCategory(String, String),
}
#[derive(uniffi::Record, Default)]
pub struct CommonMetricData {
pub category: String,
pub name: String,
pub send_in_pings: Vec<String>,
pub lifetime: Lifetime,
pub disabled: bool,
pub label: Option<MetricLabel>,
pub in_session: bool,
}
#[derive(uniffi::Record)]
pub struct Rate {
numerator: i32,
denominator: i32,
}
pub type JsonValue = String;
#[derive(uniffi::Record, Debug)]
pub struct RecordedEvent {
timestamp: u64,
category: String,
name: String,
extra: Option<::std::collections::HashMap<String, String>>,
session_metadata: Option<SessionMetadata>,
}
#[derive(uniffi::Record, Debug)]
pub struct SessionMetadata {
pub session_id: String,
pub session_seq: u64,
pub event_seq: u64,
pub session_sample_rate: f64,
pub session_start_time: Option<String>,
}
#[derive(uniffi::Record)]
pub struct Datetime {
year: i32,
month: u32,
day: u32,
hour: u32,
minute: u32,
second: u32,
nanosecond: u32,
offset_seconds: i32,
}
#[derive(uniffi::Record)]
pub struct DistributionData {
values: ::std::collections::HashMap<i64, i64>,
sum: i64,
count: i64,
}
#[derive(uniffi::Record)]
#[cfg_attr(not(feature = "active"), derive(Default))]
pub struct TimerId {
id: u64,
}
#[derive(uniffi::Enum)]
pub enum ErrorType {
InvalidValue,
InvalidLabel,
InvalidState,
InvalidOverflow,
}
#[derive(uniffi::Enum)]
#[repr(i32)]
pub enum TimeUnit {
/// Truncate to nanosecond precision.
Nanosecond,
/// Truncate to microsecond precision.
Microsecond,
/// Truncate to millisecond precision.
Millisecond,
/// Truncate to second precision.
Second,
/// Truncate to minute precision.
Minute,
/// Truncate to hour precision.
Hour,
/// Truncate to day precision.
Day,
}
#[derive(uniffi::Enum)]
#[repr(i32)] // use i32 to be compatible with our JNA definition
pub enum MemoryUnit {
/// 1 byte
Byte,
/// 2^10 bytes
Kilobyte,
/// 2^20 bytes
Megabyte,
/// 2^30 bytes
Gigabyte,
}
#[derive(uniffi::Enum)]
pub enum HistogramType {
/// A histogram with linear distributed buckets.
Linear,
/// A histogram with exponential distributed buckets.
Exponential,
}
pub type CowString = std::borrow::Cow<'static, str>;
pub trait ExtraKeys {
/// List of allowed extra keys as strings.
const ALLOWED_KEYS: &'static [&'static str];
/// Convert the event extras into a hashmap of extra key to extra value.
fn into_ffi_extra(self) -> HashMap<String, String>;
}
pub enum NoExtraKeys {}
impl ExtraKeys for NoExtraKeys {
const ALLOWED_KEYS: &'static [&'static str] = &[];
fn into_ffi_extra(self) -> HashMap<String, String> {
unimplemented!("non-existing extra keys can't be turned into a list")
}
}
/// Developer-facing API for recording event metrics.
///
/// Instances of this class type are automatically generated by the parsers
/// at build time, allowing developers to record values that were previously
/// registered in the metrics.yaml file.
pub struct EventMetric<K> {
pub(crate) inner: crate::metrics::EventMetric,
extra_keys: PhantomData<K>,
}
impl<K: ExtraKeys> EventMetric<K> {
/// The public constructor used by automatically generated metrics.
pub fn new(meta: CommonMetricData) -> Self {
let allowed_extra_keys = K::ALLOWED_KEYS.iter().map(|s| s.to_string()).collect();
let inner = crate::metrics::EventMetric::new(meta, allowed_extra_keys);
Self {
inner,
extra_keys: PhantomData,
}
}
/// Records an event.
///
/// # Arguments
///
/// * `extra` - (optional) An object for the extra keys.
pub fn record<M: Into<Option<K>>>(&self, extra: M) {
let extra = extra
.into()
.map(|e| e.into_ffi_extra())
.unwrap_or_else(HashMap::new);
self.inner.record(extra);
}
/// **Exported for test purposes.**
///
/// Gets the number of recorded errors for the given metric and error type.
///
/// # Arguments
///
/// * `error` - The type of error
///
/// # Returns
///
/// The number of errors reported.
pub fn test_get_num_recorded_errors(&self, error: ErrorType) -> i32 {
self.inner.test_get_num_recorded_errors(error)
}
}
#[cfg(not(feature = "active"))]
pub struct PingType;
#[cfg(feature = "active")]
pub struct PingType {
inner: crate::metrics::PingType,
}
#[cfg(feature = "active")]
impl PingType {
/// Creates a new ping type.
///
/// # Arguments
///
/// * `name` - The name of the ping.
/// * `include_client_id` - Whether to include the client ID in the assembled ping when.
/// * `send_if_empty` - Whether the ping should be sent empty or not.
/// * `precise_timestamps` - Whether the ping should use precise timestamps for the start and end time.
/// * `include_info_sections` - Whether the ping should include the client/ping_info sections.
/// * `enabled` - Whether or not this ping is enabled. Note: Data that would be sent on a disabled
/// ping will still be collected and is discarded instead of being submitted.
/// * `schedules_pings` - A list of pings which are triggered for submission when this ping is
/// submitted.
/// * `reason_codes` - The valid reason codes for this ping.
/// * `uploader_capabilities` - The capabilities required during this ping's upload.
#[allow(clippy::too_many_arguments)]
pub fn new<A: Into<String>>(
name: A,
include_client_id: bool,
send_if_empty: bool,
precise_timestamps: bool,
include_info_sections: bool,
enabled: bool,
schedules_pings: Vec<String>,
reason_codes: Vec<String>,
follows_collection_enabled: bool,
uploader_capabilities: Vec<String>,
) -> Self {
let inner = crate::metrics::PingType::new(
name.into(),
include_client_id,
send_if_empty,
precise_timestamps,
include_info_sections,
enabled,
schedules_pings,
reason_codes,
follows_collection_enabled,
uploader_capabilities,
);
Self { inner }
}
pub fn submit(&self, reason: Option<&str>) {
self.inner.submit(reason.map(|s| s.to_string()))
}
pub fn set_enabled(&self, enabled: bool) {
self.inner.set_enabled(enabled)
}
}
#[cfg(not(feature = "active"))]
impl PingType {
/// Creates a new ping type.
///
/// # Arguments
///
/// * `name` - The name of the ping.
/// * `include_client_id` - Whether to include the client ID in the assembled ping when.
/// * `send_if_empty` - Whether the ping should be sent empty or not.
/// * `precise_timestamps` - Whether the ping should use precise timestamps for the start and end time.
/// * `include_info_sections` - Whether the ping should include the client/ping_info sections.
/// * `enabled` - Whether or not this ping is enabled. Note: Data that would be sent on a disabled
/// ping will still be collected and is discarded instead of being submitted.
/// * `schedules_pings` - A list of pings which are triggered for submission when this ping is
/// submitted.
/// * `reason_codes` - The valid reason codes for this ping.
/// * `uploader_capabilities` - The capabilities required during this ping's upload.
#[allow(clippy::too_many_arguments)]
pub fn new<A: Into<String>>(
_name: A,
_include_client_id: bool,
_send_if_empty: bool,
_precise_timestamps: bool,
_include_info_sections: bool,
_enabled: bool,
_schedules_pings: Vec<String>,
_reason_codes: Vec<String>,
_follows_collection_enabled: bool,
_uploader_capabilities: Vec<String>,
) -> Self {
Self
}
pub fn submit(&self, _reason: Option<&str>) {}
pub fn set_enabled(&self, _enabled: bool) {}
}