Skip to content

Commit

Permalink
Bug 1934880 - Provide a public interface so that consumers of glean's…
Browse files Browse the repository at this point in the history
… RLB can access metric identifiers
  • Loading branch information
AdamBrouwersHarries authored and badboy committed Jan 30, 2025
1 parent 26cebd6 commit 5e7064f
Show file tree
Hide file tree
Showing 5 changed files with 141 additions and 3 deletions.
5 changes: 4 additions & 1 deletion glean-core/rlb/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,10 @@ use configuration::DEFAULT_GLEAN_ENDPOINT;
pub use configuration::{Builder as ConfigurationBuilder, Configuration};
pub use core_metrics::ClientInfoMetrics;
pub use glean_core::{
metrics::{Datetime, DistributionData, MemoryUnit, Rate, RecordedEvent, TimeUnit, TimerId},
metrics::{
Datetime, DistributionData, MemoryUnit, MetricIdentifier, Rate, RecordedEvent, TimeUnit,
TimerId,
},
traits, CommonMetricData, Error, ErrorType, Glean, HistogramType, LabeledMetricData, Lifetime,
PingRateLimit, RecordedExperiment, Result,
};
Expand Down
8 changes: 7 additions & 1 deletion glean-core/rlb/src/private/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
use inherent::inherent;
use std::{collections::HashMap, marker::PhantomData};

use glean_core::traits;
use glean_core::{metrics::MetricIdentifier, traits};

use crate::{ErrorType, RecordedEvent};

Expand All @@ -25,6 +25,12 @@ pub struct EventMetric<K> {
extra_keys: PhantomData<K>,
}

impl<'a, K> MetricIdentifier<'a> for EventMetric<K> {
fn get_identifiers(&'a self) -> (&'a str, &'a str, Option<&'a str>) {
self.inner.get_identifiers()
}
}

impl<K: traits::ExtraKeys> EventMetric<K> {
/// The public constructor used by automatically generated metrics.
pub fn new(meta: glean_core::CommonMetricData) -> Self {
Expand Down
8 changes: 7 additions & 1 deletion glean-core/rlb/src/private/object.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

use std::marker::PhantomData;

use glean_core::metrics::JsonValue;
use glean_core::metrics::{JsonValue, MetricIdentifier};
use glean_core::traits;

use crate::ErrorType;
Expand All @@ -25,6 +25,12 @@ pub struct ObjectMetric<K> {
object_type: PhantomData<K>,
}

impl<'a, K> MetricIdentifier<'a> for ObjectMetric<K> {
fn get_identifiers(&'a self) -> (&'a str, &'a str, Option<&'a str>) {
self.inner.get_identifiers()
}
}

impl<K: traits::ObjectSerialize> ObjectMetric<K> {
/// The public constructor used by automatically generated metrics.
pub fn new(meta: glean_core::CommonMetricData) -> Self {
Expand Down
104 changes: 104 additions & 0 deletions glean-core/rlb/tests/metric_metadata.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
// 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/.

//! This integration test should model how the RLB is used when embedded in another Rust application
//! (e.g. FOG/Firefox Desktop).
//!
//! We write a single test scenario per file to avoid any state keeping across runs
//! (different files run as different processes).
mod common;

/// Some user metrics.
mod metrics {
use glean::private::*;
use glean::traits;
use glean::CommonMetricData;
use once_cell::sync::Lazy;
use std::collections::HashMap;

pub struct SomeExtras {
extra1: Option<String>,
extra2: Option<bool>,
}

impl traits::ExtraKeys for SomeExtras {
const ALLOWED_KEYS: &'static [&'static str] = &["extra1", "extra2"];

fn into_ffi_extra(self) -> HashMap<String, String> {
let mut map = HashMap::new();

self.extra1
.and_then(|val| map.insert("extra1".to_string(), val));
self.extra2
.and_then(|val| map.insert("extra2".to_string(), val.to_string()));

map
}
}

#[allow(non_upper_case_globals)]
pub static countit: Lazy<CounterMetric> = Lazy::new(|| {
CounterMetric::new(CommonMetricData {
name: "count_von_count".into(),
category: "sesame".into(),
send_in_pings: vec!["validation".into()],
dynamic_label: Some("ah_ah_ah".into()),
..Default::default()
})
});

#[allow(non_upper_case_globals)]
pub static event: Lazy<EventMetric<SomeExtras>> = Lazy::new(|| {
EventMetric::new(CommonMetricData {
name: "birthday".into(),
category: "shire".into(),
send_in_pings: vec!["validation".into()],
dynamic_label: Some("111th".into()),
..Default::default()
})
});

#[allow(non_upper_case_globals)]
pub static object: Lazy<ObjectMetric<i32>> = Lazy::new(|| {
ObjectMetric::new(CommonMetricData {
name: "objection".into(),
category: "court".into(),
send_in_pings: vec!["validation".into()],
..Default::default()
})
});
}

/// Test scenario: We have an unknown metric, and wish to get metadata about the metric.
///
/// The app is initialized, in turn Glean gets initialized without problems.
/// We retrieve information about the metric.
/// And later the whole process is shutdown.
#[test]
fn check_metadata() {
use glean::MetricIdentifier;
common::enable_test_logging();

// Pick the counter metric to test the blanket implementation of
// MetricIdentifier for types that implement MetricType
let (category, name, label) = metrics::countit.get_identifiers();
assert_eq!(category, "sesame");
assert_eq!(name, "count_von_count");
assert_eq!(label, Some("ah_ah_ah"));

// Events and Objects have MetricIdentifier implemented explicitly, as
// they wrap the glean-core Event and Object types
let (category, name, label) = metrics::event.get_identifiers();
assert_eq!(category, "shire");
assert_eq!(name, "birthday");
assert_eq!(label, Some("111th"));

let (category, name, label) = metrics::object.get_identifiers();
assert_eq!(category, "court");
assert_eq!(name, "objection");
assert_eq!(label, None);

glean::shutdown();
}
19 changes: 19 additions & 0 deletions glean-core/src/metrics/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,25 @@ pub trait MetricType {
}
}

/// A [`MetricIdentifier`] describes an interface for retrieving an
/// identifier (category, name, label) for a metric
pub trait MetricIdentifier<'a> {
/// Retrieve the category, name and (maybe) label of the metric
fn get_identifiers(&'a self) -> (&'a str, &'a str, Option<&'a str>);
}

// Provide a blanket implementation for MetricIdentifier for all the types
// that implement MetricType.
impl<'a, T> MetricIdentifier<'a> for T
where
T: MetricType,
{
fn get_identifiers(&'a self) -> (&'a str, &'a str, Option<&'a str>) {
let meta = &self.meta().inner;
(&meta.category, &meta.name, meta.dynamic_label.as_deref())
}
}

impl Metric {
/// Gets the ping section the metric fits into.
///
Expand Down

0 comments on commit 5e7064f

Please sign in to comment.