Bug 1828528 - expose Text metric type in FOG r=chutten for causing merge conflict

Differential Revision: https://phabricator.services.mozilla.com/D176350
This commit is contained in:
Perry McManis 2023-05-03 11:58:20 +03:00
Родитель e6cb503ac2
Коммит 6ebb4fdd04
23 изменённых файлов: 585 добавлений и 93 удалений

Просмотреть файл

@ -21,6 +21,7 @@ mod quantity;
mod rate;
mod string;
mod string_list;
mod text;
mod timespan;
mod timing_distribution;
mod url;

Просмотреть файл

@ -0,0 +1,29 @@
// 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/.
#![cfg(feature = "with_gecko")]
use nsstring::nsACString;
#[no_mangle]
pub extern "C" fn fog_text_test_has_value(id: u32, ping_name: &nsACString) -> bool {
with_metric!(TEXT_MAP, id, metric, test_has!(metric, ping_name))
}
#[no_mangle]
pub extern "C" fn fog_text_test_get_value(id: u32, ping_name: &nsACString, value: &mut nsACString) {
let val = with_metric!(TEXT_MAP, id, metric, test_get!(metric, ping_name));
value.assign(&val);
}
#[no_mangle]
pub extern "C" fn fog_text_set(id: u32, value: &nsACString) {
with_metric!(TEXT_MAP, id, metric, metric.set(value.to_utf8()));
}
#[no_mangle]
pub extern "C" fn fog_text_test_get_error(id: u32, error_str: &mut nsACString) -> bool {
let err = with_metric!(TEXT_MAP, id, metric, test_get_errors!(metric));
err.map(|err_str| error_str.assign(&err_str)).is_some()
}

Просмотреть файл

@ -29,6 +29,7 @@ mod quantity;
mod rate;
pub(crate) mod string;
mod string_list;
mod text;
mod timespan;
mod timing_distribution;
mod url;
@ -51,6 +52,7 @@ pub use self::rate::RateMetric;
pub use self::string::StringMetric;
pub use self::string::StringMetric as LabeledStringMetric;
pub use self::string_list::StringListMetric;
pub use self::text::TextMetric;
pub use self::timespan::TimespanMetric;
pub use self::timing_distribution::TimingDistributionMetric;
pub use self::url::UrlMetric;

Просмотреть файл

@ -0,0 +1,176 @@
// 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/.
use inherent::inherent;
use std::sync::Arc;
use super::{CommonMetricData, MetricId};
use crate::ipc::need_ipc;
/// A text metric.
///
/// Record a string value with arbitrary content. Supports non-ASCII
/// characters.
///
/// # Example
///
/// The following piece of code will be generated by `glean_parser`:
///
/// ```rust,ignore
/// use glean::metrics::{TextMetric, CommonMetricData, Lifetime};
/// use once_cell::sync::Lazy;
///
/// mod browser {
/// pub static bread_recipe: Lazy<TextMetric> = Lazy::new(|| TextMetric::new(CommonMetricData {
/// name: "bread_recipe".into(),
/// category: "browser".into(),
/// lifetime: Lifetime::Ping,
/// disabled: false,
/// dynamic_label: None
/// }));
/// }
/// ```
///
/// It can then be used with:
///
/// ```rust,ignore
/// browser::bread_recipe.set("The 'baguette de tradition française' is made from wheat flour, water, yeast, and common salt. It may contain up to 2% broad bean flour, up to 0.5% soya flour, and up to 0.3% wheat malt flour.");
/// ```
#[derive(Clone)]
pub enum TextMetric {
Parent(Arc<glean::private::TextMetric>),
Child(TextMetricIpc),
}
#[derive(Clone, Debug)]
pub struct TextMetricIpc;
impl TextMetric {
/// Create a new text metric.
pub fn new(_id: MetricId, meta: CommonMetricData) -> Self {
if need_ipc() {
TextMetric::Child(TextMetricIpc)
} else {
TextMetric::Parent(Arc::new(glean::private::TextMetric::new(meta)))
}
}
#[cfg(test)]
pub(crate) fn child_metric(&self) -> Self {
match self {
TextMetric::Parent(_) => TextMetric::Child(TextMetricIpc),
TextMetric::Child(_) => panic!("Can't get a child metric from a child process"),
}
}
}
#[inherent]
impl glean::traits::Text for TextMetric {
/// Sets to the specified value.
///
/// # Arguments
///
/// * `value` - The text to set the metric to.
pub fn set<S: Into<std::string::String>>(&self, value: S) {
match self {
TextMetric::Parent(p) => {
p.set(value.into());
}
TextMetric::Child(_) => {
log::error!("Unable to set text metric in non-main process. Ignoring.")
}
}
}
/// **Exported for test purposes.**
///
/// Gets the currently stored value as a string.
///
/// This doesn't clear the stored value.
///
/// # Arguments
///
/// * `ping_name` - represents the optional name of the ping to retrieve the
/// metric for. Defaults to the first value in `send_in_pings`.
pub fn test_get_value<'a, S: Into<Option<&'a str>>>(
&self,
ping_name: S,
) -> Option<std::string::String> {
let ping_name = ping_name.into().map(|s| s.to_string());
match self {
TextMetric::Parent(p) => p.test_get_value(ping_name),
TextMetric::Child(_) => {
panic!("Cannot get test value for text metric in non-parent process!")
}
}
}
/// **Exported for test purposes.**
///
/// Gets the number of recorded errors for the given metric and error type.
///
/// # Arguments
///
/// * `error` - The type of error
/// * `ping_name` - represents the optional name of the ping to retrieve the
/// metric for. Defaults to the first value in `send_in_pings`.
///
/// # Returns
///
/// The number of errors reported.
pub fn test_get_num_recorded_errors(&self, error: glean::ErrorType) -> i32 {
match self {
TextMetric::Parent(p) => p.test_get_num_recorded_errors(error),
TextMetric::Child(_) => panic!(
"Cannot get the number of recorded errors for text metric in non-parent process!"
),
}
}
}
#[cfg(test)]
mod test {
use crate::{common_test::*, ipc, metrics};
#[test]
fn sets_text_value() {
let _lock = lock_test();
let metric = &metrics::test_only_ipc::a_text;
metric.set("test_text_value");
assert_eq!("test_text_value", metric.test_get_value("store1").unwrap());
}
#[test]
fn text_ipc() {
// TextMetric doesn't support IPC.
let _lock = lock_test();
let parent_metric = &metrics::test_only_ipc::a_text;
parent_metric.set("test_parent_value");
{
let child_metric = parent_metric.child_metric();
let _raii = ipc::test_set_need_ipc(true);
// Instrumentation calls do not panic.
child_metric.set("test_child_value");
// (They also shouldn't do anything,
// but that's not something we can inspect in this test)
}
assert!(ipc::replay_from_buf(&ipc::take_buf().unwrap()).is_ok());
assert!(
"test_parent_value" == parent_metric.test_get_value("store1").unwrap(),
"Text metrics should only work in the parent process"
);
}
}

Просмотреть файл

@ -18,6 +18,7 @@
#include "mozilla/glean/bindings/Rate.h"
#include "mozilla/glean/bindings/String.h"
#include "mozilla/glean/bindings/StringList.h"
#include "mozilla/glean/bindings/Text.h"
#include "mozilla/glean/bindings/Timespan.h"
#include "mozilla/glean/bindings/TimingDistribution.h"
#include "mozilla/glean/bindings/Url.h"

Просмотреть файл

@ -0,0 +1,72 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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/. */
#include "mozilla/glean/bindings/Text.h"
#include "Common.h"
#include "jsapi.h"
#include "js/String.h"
#include "nsString.h"
#include "mozilla/Components.h"
#include "mozilla/ResultVariant.h"
#include "mozilla/glean/bindings/ScalarGIFFTMap.h"
#include "mozilla/glean/fog_ffi_generated.h"
#include "nsIClassInfoImpl.h"
namespace mozilla::glean {
namespace impl {
void TextMetric::Set(const nsACString& aValue) const {
fog_text_set(mId, &aValue);
}
Result<Maybe<nsCString>, nsCString> TextMetric::TestGetValue(
const nsACString& aPingName) const {
nsCString err;
if (fog_text_test_get_error(mId, &err)) {
return Err(err);
}
if (!fog_text_test_has_value(mId, &aPingName)) {
return Maybe<nsCString>();
}
nsCString ret;
fog_text_test_get_value(mId, &aPingName, &ret);
return Some(ret);
}
} // namespace impl
NS_IMPL_CLASSINFO(GleanText, nullptr, 0, {0})
NS_IMPL_ISUPPORTS_CI(GleanText, nsIGleanText)
NS_IMETHODIMP
GleanText::Set(const nsACString& aValue) {
mText.Set(aValue);
return NS_OK;
}
NS_IMETHODIMP
GleanText::TestGetValue(const nsACString& aStorageName, JSContext* aCx,
JS::MutableHandle<JS::Value> aResult) {
auto result = mText.TestGetValue(aStorageName);
if (result.isErr()) {
aResult.set(JS::UndefinedValue());
LogToBrowserConsole(nsIScriptError::errorFlag,
NS_ConvertUTF8toUTF16(result.unwrapErr()));
return NS_ERROR_LOSS_OF_SIGNIFICANT_DATA;
}
auto optresult = result.unwrap();
if (optresult.isNothing()) {
aResult.set(JS::UndefinedValue());
} else {
const NS_ConvertUTF8toUTF16 str(optresult.ref());
aResult.set(
JS::StringValue(JS_NewUCStringCopyN(aCx, str.Data(), str.Length())));
}
return NS_OK;
}
} // namespace mozilla::glean

Просмотреть файл

@ -0,0 +1,47 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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/. */
#ifndef mozilla_glean_GleanText_h
#define mozilla_glean_GleanText_h
#include "mozilla/Maybe.h"
#include "mozilla/Result.h"
#include "nsIGleanMetrics.h"
#include "nsString.h"
namespace mozilla::glean {
namespace impl {
class TextMetric {
public:
constexpr explicit TextMetric(uint32_t aId) : mId(aId) {}
void Set(const nsACString& aValue) const;
Result<Maybe<nsCString>, nsCString> TestGetValue(
const nsACString& aPingName = nsCString()) const;
private:
const uint32_t mId;
};
} // namespace impl
class GleanText final : public nsIGleanText {
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIGLEANTEXT
explicit GleanText(uint32_t aId) : mText(aId){};
private:
virtual ~GleanText() = default;
const impl::TextMetric mText;
};
} // namespace mozilla::glean
#endif

Просмотреть файл

@ -48,6 +48,7 @@ This compatibility table explains which Telemetry probe types can be mirrors for
| [events](https://mozilla.github.io/glean/book/user/metrics/event.html) | [Events](/toolkit/components/telemetry/collection/events.rst). The `value` field will be left empty. |
| [quantity](https://mozilla.github.io/glean/book/user/metrics/quantity.html) | [Scalar of kind: uint](/toolkit/components/telemetry/collection/scalars.rst) |
| [rate](https://mozilla.github.io/glean/book/user/metrics/rate.html) | [Keyed Scalar of kind: uint](/toolkit/components/telemetry/collection/scalars.rst). The keys are "numerator" and "denominator". Does not work for `rate` metrics with external denominators. |
| [text](https://mozilla.github.io/glean/book/reference/metrics/text.html) | *No Supported Telemetry Type* |
### The `telemetry_mirror` property in `metrics.yaml`

Просмотреть файл

@ -46,6 +46,7 @@ EXPORTS.mozilla.glean.bindings += [
"bindings/private/Rate.h",
"bindings/private/String.h",
"bindings/private/StringList.h",
"bindings/private/Text.h",
"bindings/private/Timespan.h",
"bindings/private/TimingDistribution.h",
"bindings/private/Url.h",
@ -90,6 +91,7 @@ UNIFIED_SOURCES += [
"bindings/private/Rate.cpp",
"bindings/private/String.cpp",
"bindings/private/StringList.cpp",
"bindings/private/Text.cpp",
"bindings/private/Timespan.cpp",
"bindings/private/TimingDistribution.cpp",
"bindings/private/Url.cpp",

Просмотреть файл

@ -370,6 +370,17 @@ TEST_F(FOGFixture, TestCppUrlWorks) {
.get());
}
TEST_F(FOGFixture, TestCppTextWorks) {
auto kValue =
"République is a French-inspired bakery, café, bar and formal dining room located in the Mid-city neighborhood of Los Angeles, set in a historic 1928 space ..."_ns;
mozilla::glean::test_only_ipc::a_text.Set(kValue);
ASSERT_STREQ(kValue.get(),
mozilla::glean::test_only_ipc::a_text.TestGetValue()
.unwrap()
.value()
.get());
}
extern "C" void Rust_TestRustInGTest();
TEST_F(FOGFixture, TestRustInGTest) { Rust_TestRustInGTest(); }

Просмотреть файл

@ -28,10 +28,10 @@ using Telemetry::EventID;
static inline Maybe<EventID> EventIdForMetric(uint32_t aId) {
switch(aId) {
case 16: { // test.nested.event_metric
case 17: { // test.nested.event_metric
return Some(EventID::EventMetric_EnumNames_AreStrange);
}
case 17: { // test.nested.event_metric_with_extra
case 18: { // test.nested.event_metric_with_extra
return Some(EventID::EventMetric_EnumName_WithExtra);
}
default: {

Просмотреть файл

@ -106,7 +106,7 @@ static Maybe<HistogramID> HistogramIdForMetric(uint32_t aId) {
case 10: { // test.memory_distribution_metric
return Some(HistogramID::SOME_MEM_HISTOGRAM_KB);
}
case 14: { // test.timing_distribution_metric
case 15: { // test.timing_distribution_metric
return Some(HistogramID::SOME_TIME_HISTOGRAM_MS);
}
default: {

Просмотреть файл

@ -171,16 +171,16 @@ static Maybe<ScalarID> ScalarIdForMetric(uint32_t aId) {
case 12: { // test.string_metric
return Some(ScalarID::SOME_STRING_SCALAR);
}
case 13: { // test.timespan_metric
case 14: { // test.timespan_metric
return Some(ScalarID::SOME_OTHER_UINT_SCALAR);
}
case 15: { // test.nested.datetime_metric
case 16: { // test.nested.datetime_metric
return Some(ScalarID::SOME_STILL_OTHER_STRING_SCALAR);
}
case 19: { // test.nested.quantity_metric
case 20: { // test.nested.quantity_metric
return Some(ScalarID::TELEMETRY_TEST_MIRROR_FOR_QUANTITY);
}
case 22: { // test.nested.uuid_metric
case 23: { // test.nested.uuid_metric
return Some(ScalarID::SOME_OTHER_STRING_SCALAR);
}
default: {

Просмотреть файл

@ -118,6 +118,15 @@
"application",
false
],
[
"text",
"text_metric",
[
"metrics"
],
"application",
false
],
[
"timespan",
"timespan_metric",

Просмотреть файл

@ -180,6 +180,21 @@ test:
- https://example.com
telemetry_mirror: YET_ANOTHER_KEYED_BOOL_SCALAR
text_metric:
type: text
expires: never
description: |
A multi-line
description
lifetime: application
notification_emails:
- glean-team@mozilla.com
bugs:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1828528
data_reviews:
- https://example.com
timespan_metric:
type: timespan
expires: never

Просмотреть файл

@ -205,13 +205,29 @@ pub mod test {
})
});
#[allow(non_upper_case_globals)]
/// generated from test.text_metric
///
/// A multi-line
/// description
pub static text_metric: Lazy<TextMetric> = Lazy::new(|| {
TextMetric::new(13.into(), CommonMetricData {
name: "text_metric".into(),
category: "test".into(),
send_in_pings: vec!["metrics".into()],
lifetime: Lifetime::Application,
disabled: false,
..Default::default()
})
});
#[allow(non_upper_case_globals)]
/// generated from test.timespan_metric
///
/// A multi-line
/// description
pub static timespan_metric: Lazy<TimespanMetric> = Lazy::new(|| {
TimespanMetric::new(13.into(), CommonMetricData {
TimespanMetric::new(14.into(), CommonMetricData {
name: "timespan_metric".into(),
category: "test".into(),
send_in_pings: vec!["metrics".into()],
@ -227,7 +243,7 @@ pub mod test {
/// A multi-line
/// description
pub static timing_distribution_metric: Lazy<TimingDistributionMetric> = Lazy::new(|| {
TimingDistributionMetric::new(14.into(), CommonMetricData {
TimingDistributionMetric::new(15.into(), CommonMetricData {
name: "timing_distribution_metric".into(),
category: "test".into(),
send_in_pings: vec!["metrics".into()],
@ -251,7 +267,7 @@ pub mod test_nested {
/// A multi-line
/// description
pub static datetime_metric: Lazy<DatetimeMetric> = Lazy::new(|| {
DatetimeMetric::new(15.into(), CommonMetricData {
DatetimeMetric::new(16.into(), CommonMetricData {
name: "datetime_metric".into(),
category: "test.nested".into(),
send_in_pings: vec!["metrics".into()],
@ -267,7 +283,7 @@ pub mod test_nested {
/// A multi-line
/// description
pub static event_metric: Lazy<EventMetric<NoExtraKeys>> = Lazy::new(|| {
EventMetric::new(16.into(), CommonMetricData {
EventMetric::new(17.into(), CommonMetricData {
name: "event_metric".into(),
category: "test.nested".into(),
send_in_pings: vec!["events".into()],
@ -299,7 +315,7 @@ pub mod test_nested {
/// A multi-line
/// description
pub static event_metric_with_extra: Lazy<EventMetric<EventMetricWithExtraExtra>> = Lazy::new(|| {
EventMetric::new(17.into(), CommonMetricData {
EventMetric::new(18.into(), CommonMetricData {
name: "event_metric_with_extra".into(),
category: "test.nested".into(),
send_in_pings: vec!["events".into()],
@ -315,7 +331,7 @@ pub mod test_nested {
/// A multi-line
/// description
pub static external_denominator: Lazy<DenominatorMetric> = Lazy::new(|| {
DenominatorMetric::new(18.into(), CommonMetricData {
DenominatorMetric::new(19.into(), CommonMetricData {
name: "external_denominator".into(),
category: "test.nested".into(),
send_in_pings: vec!["metrics".into()],
@ -331,7 +347,7 @@ pub mod test_nested {
/// A multi-line
/// description
pub static quantity_metric: Lazy<QuantityMetric> = Lazy::new(|| {
QuantityMetric::new(19.into(), CommonMetricData {
QuantityMetric::new(20.into(), CommonMetricData {
name: "quantity_metric".into(),
category: "test.nested".into(),
send_in_pings: vec!["metrics".into()],
@ -347,7 +363,7 @@ pub mod test_nested {
/// A multi-line
/// description
pub static rate_metric: Lazy<RateMetric> = Lazy::new(|| {
RateMetric::new(20.into(), CommonMetricData {
RateMetric::new(21.into(), CommonMetricData {
name: "rate_metric".into(),
category: "test.nested".into(),
send_in_pings: vec!["metrics".into()],
@ -363,7 +379,7 @@ pub mod test_nested {
/// A multi-line
/// description
pub static rate_with_external_denominator: Lazy<NumeratorMetric> = Lazy::new(|| {
NumeratorMetric::new(21.into(), CommonMetricData {
NumeratorMetric::new(22.into(), CommonMetricData {
name: "rate_with_external_denominator".into(),
category: "test.nested".into(),
send_in_pings: vec!["metrics".into()],
@ -379,7 +395,7 @@ pub mod test_nested {
/// A multi-line
/// description
pub static uuid_metric: Lazy<UuidMetric> = Lazy::new(|| {
UuidMetric::new(22.into(), CommonMetricData {
UuidMetric::new(23.into(), CommonMetricData {
name: "uuid_metric".into(),
category: "test.nested".into(),
send_in_pings: vec!["metrics".into()],
@ -456,51 +472,57 @@ pub(crate) mod __glean_metric_maps {
map
});
pub static TEXT_MAP: Lazy<HashMap<MetricId, &Lazy<TextMetric>>> = Lazy::new(|| {
let mut map = HashMap::with_capacity(1);
map.insert(13.into(), &super::test::text_metric);
map
});
pub static TIMESPAN_MAP: Lazy<HashMap<MetricId, &Lazy<TimespanMetric>>> = Lazy::new(|| {
let mut map = HashMap::with_capacity(1);
map.insert(13.into(), &super::test::timespan_metric);
map.insert(14.into(), &super::test::timespan_metric);
map
});
pub static TIMING_DISTRIBUTION_MAP: Lazy<HashMap<MetricId, &Lazy<TimingDistributionMetric>>> = Lazy::new(|| {
let mut map = HashMap::with_capacity(1);
map.insert(14.into(), &super::test::timing_distribution_metric);
map.insert(15.into(), &super::test::timing_distribution_metric);
map
});
pub static DATETIME_MAP: Lazy<HashMap<MetricId, &Lazy<DatetimeMetric>>> = Lazy::new(|| {
let mut map = HashMap::with_capacity(1);
map.insert(15.into(), &super::test_nested::datetime_metric);
map.insert(16.into(), &super::test_nested::datetime_metric);
map
});
pub static DENOMINATOR_MAP: Lazy<HashMap<MetricId, &Lazy<DenominatorMetric>>> = Lazy::new(|| {
let mut map = HashMap::with_capacity(1);
map.insert(18.into(), &super::test_nested::external_denominator);
map.insert(19.into(), &super::test_nested::external_denominator);
map
});
pub static QUANTITY_MAP: Lazy<HashMap<MetricId, &Lazy<QuantityMetric>>> = Lazy::new(|| {
let mut map = HashMap::with_capacity(1);
map.insert(19.into(), &super::test_nested::quantity_metric);
map.insert(20.into(), &super::test_nested::quantity_metric);
map
});
pub static RATE_MAP: Lazy<HashMap<MetricId, &Lazy<RateMetric>>> = Lazy::new(|| {
let mut map = HashMap::with_capacity(1);
map.insert(20.into(), &super::test_nested::rate_metric);
map.insert(21.into(), &super::test_nested::rate_metric);
map
});
pub static NUMERATOR_MAP: Lazy<HashMap<MetricId, &Lazy<NumeratorMetric>>> = Lazy::new(|| {
let mut map = HashMap::with_capacity(1);
map.insert(21.into(), &super::test_nested::rate_with_external_denominator);
map.insert(22.into(), &super::test_nested::rate_with_external_denominator);
map
});
pub static UUID_MAP: Lazy<HashMap<MetricId, &Lazy<UuidMetric>>> = Lazy::new(|| {
let mut map = HashMap::with_capacity(1);
map.insert(22.into(), &super::test_nested::uuid_metric);
map.insert(23.into(), &super::test_nested::uuid_metric);
map
});
@ -519,7 +541,7 @@ pub(crate) mod __glean_metric_maps {
/// 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 {
16 => {
17 => {
assert!(
extra_keys_len(&super::test_nested::event_metric) != 0 || extra.is_empty(),
"No extra keys allowed, but some were passed"
@ -528,7 +550,7 @@ pub(crate) mod __glean_metric_maps {
super::test_nested::event_metric.record_raw(extra);
Ok(())
}
17 => {
18 => {
assert!(
extra_keys_len(&super::test_nested::event_metric_with_extra) != 0 || extra.is_empty(),
"No extra keys allowed, but some were passed"
@ -557,7 +579,7 @@ pub(crate) mod __glean_metric_maps {
/// 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 {
MetricId(16) => {
MetricId(17) => {
if extra_keys_len(&super::test_nested::event_metric) == 0 && !extra.is_empty() {
return Err(EventRecordingError::InvalidExtraKey);
}
@ -565,7 +587,7 @@ pub(crate) mod __glean_metric_maps {
super::test_nested::event_metric.record_with_time(timestamp, extra);
Ok(())
}
MetricId(17) => {
MetricId(18) => {
if extra_keys_len(&super::test_nested::event_metric_with_extra) == 0 && !extra.is_empty() {
return Err(EventRecordingError::InvalidExtraKey);
}
@ -594,8 +616,8 @@ pub(crate) mod __glean_metric_maps {
/// 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 {
16 => super::test_nested::event_metric.test_get_value(ping_name.as_deref()),
17 => super::test_nested::event_metric_with_extra.test_get_value(ping_name.as_deref()),
17 => super::test_nested::event_metric.test_get_value(ping_name.as_deref()),
18 => super::test_nested::event_metric_with_extra.test_get_value(ping_name.as_deref()),
_ => panic!("No event for metric id {}", metric_id),
}
}
@ -619,8 +641,8 @@ pub(crate) mod __glean_metric_maps {
pub(crate) fn event_test_get_error(metric_id: u32) -> Option<String> {
#[cfg(feature = "with_gecko")]
match metric_id {
16 => test_get_errors!(super::test_nested::event_metric),
17 => test_get_errors!(super::test_nested::event_metric_with_extra),
17 => test_get_errors!(super::test_nested::event_metric),
18 => test_get_errors!(super::test_nested::event_metric_with_extra),
_ => panic!("No event for metric id {}", metric_id),
}

Просмотреть файл

@ -128,6 +128,15 @@ namespace test {
*/
constexpr impl::StringMetric string_metric(12);
/**
* generated from test.text_metric
*/
/**
* A multi-line
* description
*/
constexpr impl::TextMetric text_metric(13);
/**
* generated from test.timespan_metric
*/
@ -135,7 +144,7 @@ namespace test {
* A multi-line
* description
*/
constexpr impl::TimespanMetric timespan_metric(13);
constexpr impl::TimespanMetric timespan_metric(14);
/**
* generated from test.timing_distribution_metric
@ -144,7 +153,7 @@ namespace test {
* A multi-line
* description
*/
constexpr impl::TimingDistributionMetric timing_distribution_metric(14);
constexpr impl::TimingDistributionMetric timing_distribution_metric(15);
}
namespace test_nested {
@ -155,7 +164,7 @@ namespace test_nested {
* A multi-line
* description
*/
constexpr impl::DatetimeMetric datetime_metric(15);
constexpr impl::DatetimeMetric datetime_metric(16);
/**
* generated from test.nested.event_metric
@ -164,7 +173,7 @@ namespace test_nested {
* A multi-line
* description
*/
constexpr impl::EventMetric<NoExtraKeys> event_metric(16);
constexpr impl::EventMetric<NoExtraKeys> event_metric(17);
/**
* generated from test.nested.event_metric_with_extra
@ -191,7 +200,7 @@ namespace test_nested {
* A multi-line
* description
*/
constexpr impl::EventMetric<EventMetricWithExtraExtra> event_metric_with_extra(17);
constexpr impl::EventMetric<EventMetricWithExtraExtra> event_metric_with_extra(18);
/**
* generated from test.nested.external_denominator
@ -200,7 +209,7 @@ namespace test_nested {
* A multi-line
* description
*/
constexpr impl::DenominatorMetric external_denominator(18);
constexpr impl::DenominatorMetric external_denominator(19);
/**
* generated from test.nested.quantity_metric
@ -209,7 +218,7 @@ namespace test_nested {
* A multi-line
* description
*/
constexpr impl::QuantityMetric quantity_metric(19);
constexpr impl::QuantityMetric quantity_metric(20);
/**
* generated from test.nested.rate_metric
@ -218,7 +227,7 @@ namespace test_nested {
* A multi-line
* description
*/
constexpr impl::RateMetric rate_metric(20);
constexpr impl::RateMetric rate_metric(21);
/**
* generated from test.nested.rate_with_external_denominator
@ -227,7 +236,7 @@ namespace test_nested {
* A multi-line
* description
*/
constexpr impl::NumeratorMetric rate_with_external_denominator(21);
constexpr impl::NumeratorMetric rate_with_external_denominator(22);
/**
* generated from test.nested.uuid_metric
@ -236,7 +245,7 @@ namespace test_nested {
* A multi-line
* description
*/
constexpr impl::UuidMetric uuid_metric(22);
constexpr impl::UuidMetric uuid_metric(23);
}

Просмотреть файл

@ -39,8 +39,8 @@ using metric_entry_t = uint64_t;
static_assert(GLEAN_INDEX_BITS + GLEAN_TYPE_BITS + GLEAN_ID_BITS == sizeof(metric_entry_t) * 8, "Index, Type, and ID bits need to fit into a metric_entry_t");
static_assert(GLEAN_TYPE_BITS + GLEAN_ID_BITS <= sizeof(uint32_t) * 8, "Metric Types and IDs need to fit into at most 32 bits");
static_assert(2 < UINT32_MAX, "Too many metric categories generated.");
static_assert(22 < 33554432, "Too many metrics generated. Need room for 2 signal bits.");
static_assert(18 < 32, "Too many different metric types.");
static_assert(23 < 33554432, "Too many metrics generated. Need room for 2 signal bits.");
static_assert(19 < 32, "Too many different metric types.");
already_AddRefed<nsISupports> NewMetricFromId(uint32_t id) {
uint32_t typeId = GLEAN_TYPE_ID(id);
@ -83,39 +83,43 @@ already_AddRefed<nsISupports> NewMetricFromId(uint32_t id) {
{
return MakeAndAddRef<GleanString>(metricId);
}
case 10: /* timespan */
case 10: /* text */
{
return MakeAndAddRef<GleanText>(metricId);
}
case 11: /* timespan */
{
return MakeAndAddRef<GleanTimespan>(metricId);
}
case 11: /* timing_distribution */
case 12: /* timing_distribution */
{
return MakeAndAddRef<GleanTimingDistribution>(metricId);
}
case 12: /* datetime */
case 13: /* datetime */
{
return MakeAndAddRef<GleanDatetime>(metricId);
}
case 13: /* event */
case 14: /* event */
{
return MakeAndAddRef<GleanEvent>(metricId);
}
case 14: /* denominator */
case 15: /* denominator */
{
return MakeAndAddRef<GleanDenominator>(metricId);
}
case 15: /* quantity */
case 16: /* quantity */
{
return MakeAndAddRef<GleanQuantity>(metricId);
}
case 16: /* rate */
case 17: /* rate */
{
return MakeAndAddRef<GleanRate>(metricId);
}
case 17: /* numerator */
case 18: /* numerator */
{
return MakeAndAddRef<GleanNumerator>(metricId);
}
case 18: /* uuid */
case 19: /* uuid */
{
return MakeAndAddRef<GleanUuid>(metricId);
}
@ -246,44 +250,46 @@ constexpr char gMetricStringTable[] = {
/* 240 - "test.memoryDistributionMetric" */ 't', 'e', 's', 't', '.', 'm', 'e', 'm', 'o', 'r', 'y', 'D', 'i', 's', 't', 'r', 'i', 'b', 'u', 't', 'i', 'o', 'n', 'M', 'e', 't', 'r', 'i', 'c', '\0',
/* 270 - "test.stringListMetric" */ 't', 'e', 's', 't', '.', 's', 't', 'r', 'i', 'n', 'g', 'L', 'i', 's', 't', 'M', 'e', 't', 'r', 'i', 'c', '\0',
/* 292 - "test.stringMetric" */ 't', 'e', 's', 't', '.', 's', 't', 'r', 'i', 'n', 'g', 'M', 'e', 't', 'r', 'i', 'c', '\0',
/* 310 - "test.timespanMetric" */ 't', 'e', 's', 't', '.', 't', 'i', 'm', 'e', 's', 'p', 'a', 'n', 'M', 'e', 't', 'r', 'i', 'c', '\0',
/* 330 - "test.timingDistributionMetric" */ 't', 'e', 's', 't', '.', 't', 'i', 'm', 'i', 'n', 'g', 'D', 'i', 's', 't', 'r', 'i', 'b', 'u', 't', 'i', 'o', 'n', 'M', 'e', 't', 'r', 'i', 'c', '\0',
/* 360 - "testNested.datetimeMetric" */ 't', 'e', 's', 't', 'N', 'e', 's', 't', 'e', 'd', '.', 'd', 'a', 't', 'e', 't', 'i', 'm', 'e', 'M', 'e', 't', 'r', 'i', 'c', '\0',
/* 386 - "testNested.eventMetric" */ 't', 'e', 's', 't', 'N', 'e', 's', 't', 'e', 'd', '.', 'e', 'v', 'e', 'n', 't', 'M', 'e', 't', 'r', 'i', 'c', '\0',
/* 409 - "testNested.eventMetricWithExtra" */ 't', 'e', 's', 't', 'N', 'e', 's', 't', 'e', 'd', '.', 'e', 'v', 'e', 'n', 't', 'M', 'e', 't', 'r', 'i', 'c', 'W', 'i', 't', 'h', 'E', 'x', 't', 'r', 'a', '\0',
/* 441 - "testNested.externalDenominator" */ 't', 'e', 's', 't', 'N', 'e', 's', 't', 'e', 'd', '.', 'e', 'x', 't', 'e', 'r', 'n', 'a', 'l', 'D', 'e', 'n', 'o', 'm', 'i', 'n', 'a', 't', 'o', 'r', '\0',
/* 472 - "testNested.quantityMetric" */ 't', 'e', 's', 't', 'N', 'e', 's', 't', 'e', 'd', '.', 'q', 'u', 'a', 'n', 't', 'i', 't', 'y', 'M', 'e', 't', 'r', 'i', 'c', '\0',
/* 498 - "testNested.rateMetric" */ 't', 'e', 's', 't', 'N', 'e', 's', 't', 'e', 'd', '.', 'r', 'a', 't', 'e', 'M', 'e', 't', 'r', 'i', 'c', '\0',
/* 520 - "testNested.rateWithExternalDenominator" */ 't', 'e', 's', 't', 'N', 'e', 's', 't', 'e', 'd', '.', 'r', 'a', 't', 'e', 'W', 'i', 't', 'h', 'E', 'x', 't', 'e', 'r', 'n', 'a', 'l', 'D', 'e', 'n', 'o', 'm', 'i', 'n', 'a', 't', 'o', 'r', '\0',
/* 559 - "testNested.uuidMetric" */ 't', 'e', 's', 't', 'N', 'e', 's', 't', 'e', 'd', '.', 'u', 'u', 'i', 'd', 'M', 'e', 't', 'r', 'i', 'c', '\0',
/* 310 - "test.textMetric" */ 't', 'e', 's', 't', '.', 't', 'e', 'x', 't', 'M', 'e', 't', 'r', 'i', 'c', '\0',
/* 326 - "test.timespanMetric" */ 't', 'e', 's', 't', '.', 't', 'i', 'm', 'e', 's', 'p', 'a', 'n', 'M', 'e', 't', 'r', 'i', 'c', '\0',
/* 346 - "test.timingDistributionMetric" */ 't', 'e', 's', 't', '.', 't', 'i', 'm', 'i', 'n', 'g', 'D', 'i', 's', 't', 'r', 'i', 'b', 'u', 't', 'i', 'o', 'n', 'M', 'e', 't', 'r', 'i', 'c', '\0',
/* 376 - "testNested.datetimeMetric" */ 't', 'e', 's', 't', 'N', 'e', 's', 't', 'e', 'd', '.', 'd', 'a', 't', 'e', 't', 'i', 'm', 'e', 'M', 'e', 't', 'r', 'i', 'c', '\0',
/* 402 - "testNested.eventMetric" */ 't', 'e', 's', 't', 'N', 'e', 's', 't', 'e', 'd', '.', 'e', 'v', 'e', 'n', 't', 'M', 'e', 't', 'r', 'i', 'c', '\0',
/* 425 - "testNested.eventMetricWithExtra" */ 't', 'e', 's', 't', 'N', 'e', 's', 't', 'e', 'd', '.', 'e', 'v', 'e', 'n', 't', 'M', 'e', 't', 'r', 'i', 'c', 'W', 'i', 't', 'h', 'E', 'x', 't', 'r', 'a', '\0',
/* 457 - "testNested.externalDenominator" */ 't', 'e', 's', 't', 'N', 'e', 's', 't', 'e', 'd', '.', 'e', 'x', 't', 'e', 'r', 'n', 'a', 'l', 'D', 'e', 'n', 'o', 'm', 'i', 'n', 'a', 't', 'o', 'r', '\0',
/* 488 - "testNested.quantityMetric" */ 't', 'e', 's', 't', 'N', 'e', 's', 't', 'e', 'd', '.', 'q', 'u', 'a', 'n', 't', 'i', 't', 'y', 'M', 'e', 't', 'r', 'i', 'c', '\0',
/* 514 - "testNested.rateMetric" */ 't', 'e', 's', 't', 'N', 'e', 's', 't', 'e', 'd', '.', 'r', 'a', 't', 'e', 'M', 'e', 't', 'r', 'i', 'c', '\0',
/* 536 - "testNested.rateWithExternalDenominator" */ 't', 'e', 's', 't', 'N', 'e', 's', 't', 'e', 'd', '.', 'r', 'a', 't', 'e', 'W', 'i', 't', 'h', 'E', 'x', 't', 'e', 'r', 'n', 'a', 'l', 'D', 'e', 'n', 'o', 'm', 'i', 'n', 'a', 't', 'o', 'r', '\0',
/* 575 - "testNested.uuidMetric" */ 't', 'e', 's', 't', 'N', 'e', 's', 't', 'e', 'd', '.', 'u', 'u', 'i', 'd', 'M', 'e', 't', 'r', 'i', 'c', '\0',
};
static_assert(sizeof(gMetricStringTable) < 4294967296, "Metric string table is too large.");
const metric_entry_t sMetricByNameLookupEntries[] = {
3458764552475246801ull,
576460756598390784ull,
6341068335467200842ull,
2882303791581888664ull,
4035225309073637616ull,
4611686065672028430ull,
5764607578868810038ull,
8070450609557340601ull,
7493989848663982466ull,
8646911366155731416ull,
5188146822270419236ull,
1729382269795172390ull,
1152921513196781587ull,
10376293635950903855ull,
9223372122754122226ull,
6917529092065591656ull,
7493989852958949785ull,
9799832879352513032ull,
9223372122754122216ull,
3458764548180279480ull,
9799832879352513026ull,
6341068335467200838ull,
2305843026393563204ull,
4035225309073637616ull,
2305843030688530526ull,
4611686065672028430ull,
576460756598390784ull,
7493989848663982456ull,
8070450605262373266ull,
8646911366155731401ull,
3458764552475246801ull,
5188146822270419236ull,
1152921513196781587ull,
10952754392549294655ull,
1729382269795172390ull,
2882303787286921342ull,
2305843026393563204ull
10376293635950903832ull,
2882303791581888664ull,
6917529092065591642ull,
5764607578868810038ull,
8070450609557340585ull
};
@ -299,29 +305,29 @@ MetricByNameLookup(const nsACString& aKey)
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 1, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0,
0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0,
10, 0, 0, 0, 2, 0, 0, 9, 0, 0, 0, 0, 25, 0, 0, 0,
0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 3, 0, 3, 0, 0, 0, 0, 0, 0, 0,
2, 0, 0, 0, 2, 0, 0, 21, 0, 0, 0, 0, 34, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
};

Просмотреть файл

@ -68,7 +68,7 @@ Maybe<uint32_t> MetricByNameLookup(const nsACString&);
Maybe<uint32_t> CategoryByNameLookup(const nsACString&);
extern const category_entry_t sCategoryByNameLookupEntries[2];
extern const metric_entry_t sMetricByNameLookupEntries[22];
extern const metric_entry_t sMetricByNameLookupEntries[23];
} // namespace mozilla::glean
#endif // mozilla_GleanJSMetricsLookup_h

Просмотреть файл

@ -425,6 +425,24 @@ test_only.ipc:
no_lint:
- COMMON_PREFIX
telemetry_mirror: TELEMETRY_TEST_MULTIPLE_STORES_STRING
a_text:
type: text
description: |
This is a test-only metric.
For holding Text data.
bugs:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1828528
data_reviews:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1688281#c1
data_sensitivity:
- web_activity
notification_emails:
- glean-team@mozilla.com
expires: never
send_in_pings:
- store1
no_lint:
- COMMON_PREFIX
a_memory_dist:
type: memory_distribution
memory_unit: kilobyte

Просмотреть файл

@ -400,3 +400,27 @@ add_task(async function test_fog_url_works() {
Assert.equal(value, Glean.testOnlyIpc.aUrl.testGetValue("store1"));
});
add_task(async function test_fog_text_works() {
const value =
"Before the risin' sun, we fly, So many roads to choose, We'll start out walkin' and learn to run, (We've only just begun)";
Glean.testOnlyIpc.aText.set(value);
let rslt = Glean.testOnlyIpc.aText.testGetValue();
Assert.equal(value, rslt);
Assert.equal(121, rslt.length);
});
add_task(async function test_fog_text_works_unusual_character() {
const value =
"The secret to Dominique Ansel's viennoiserie is the use of Isigny Sainte-Mère butter and Les Grands Moulins de Paris flour";
Glean.testOnlyIpc.aText.set(value);
let rslt = Glean.testOnlyIpc.aText.testGetValue();
Assert.equal(value, rslt);
Assert.greater(rslt.length, 100);
});

Просмотреть файл

@ -721,3 +721,19 @@ add_task(function test_enumerable_names() {
Assert.ok(Object.keys(Glean.testOnlyJog).includes("aCounter"));
Assert.ok(Object.keys(GleanPings).includes("testPing"));
});
add_task(async function test_jog_text_works() {
const kValue =
"In the heart of the Opéra district in Paris, the Cédric Grolet Opéra bakery-pastry shop is a veritable temple of gourmet delights.";
Services.fog.testRegisterRuntimeMetric(
"text",
"test_only.jog",
"a_text",
["test-only"],
`"ping"`,
false
);
Glean.testOnlyJog.aText.set(kValue);
Assert.equal(kValue, Glean.testOnlyJog.aText.testGetValue());
});

Просмотреть файл

@ -663,3 +663,34 @@ interface nsIGleanUrl : nsISupports
[implicit_jscontext]
jsval testGetValue([optional] in AUTF8String aPingName);
};
[scriptable, uuid(fafceafb-c3a0-4424-b3b9-b7bd487f6bb4)]
interface nsIGleanText : nsISupports
{
/*
* Set to the specified value.
*
* @param value The text to set the metric to.
*/
void set(in AUTF8String value);
/**
* **Test-only API**
*
* Gets the currently stored value as a string.
*
* This function will attempt to await the last parent-process task (if any)
* writing to the the metric's storage engine before returning a value.
* This function will not wait for data from child processes.
*
* This doesn't clear the stored value.
* Parent process only. Panics in child processes.
*
* @param aPingName The (optional) name of the ping to retrieve the metric
* for. Defaults to the first value in `send_in_pings`.
*
* @return value of the stored metric, or undefined if there is no value.
*/
[implicit_jscontext]
jsval testGetValue([optional] in AUTF8String aPingName);
};