mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-23 12:51:06 +00:00
Bug 1881021 - Implement the new object metric type (JS only) r=chutten,webidl,saschanaz,smaug
For now this only provides a JavaScript API, as it's easier to generate and to use (we just use JavaScript objects, validation is done by (de)serialization on the Rust side). No JOG support. Parent-process only right now. Differential Revision: https://phabricator.services.mozilla.com/D202224
This commit is contained in:
parent
a7f4e39ff2
commit
84afc3d817
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -1706,6 +1706,7 @@ dependencies = [
|
||||
"nsstring",
|
||||
"once_cell",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"tempfile",
|
||||
"thin-vec",
|
||||
"uuid",
|
||||
|
@ -1527,6 +1527,10 @@ DOMInterfaces = {
|
||||
'nativeType': 'mozilla::glean::GleanText',
|
||||
'headerFile': 'mozilla/glean/bindings/Text.h',
|
||||
},
|
||||
'GleanObject': {
|
||||
'nativeType': 'mozilla::glean::GleanObject',
|
||||
'headerFile': 'mozilla/glean/bindings/Object.h',
|
||||
},
|
||||
|
||||
'Window': {
|
||||
'nativeType': 'nsGlobalWindowInner',
|
||||
|
@ -643,3 +643,35 @@ interface GleanText : GleanMetric {
|
||||
[Throws, ChromeOnly]
|
||||
UTF8String? testGetValue(optional UTF8String aPingName = "");
|
||||
};
|
||||
|
||||
[Func="nsGlobalWindowInner::IsGleanNeeded", Exposed=Window]
|
||||
interface GleanObject : GleanMetric {
|
||||
/**
|
||||
* Set to the specified object.
|
||||
*
|
||||
* The structure of the metric is validated against the predefined structure.
|
||||
*
|
||||
* @param object The object to set the metric to.
|
||||
*/
|
||||
undefined set(object value);
|
||||
|
||||
/**
|
||||
* **Test-only API**
|
||||
*
|
||||
* Gets the currently stored value as an object.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
[Throws, ChromeOnly]
|
||||
object? testGetValue(optional UTF8String aPingName = "");
|
||||
};
|
||||
|
@ -19,6 +19,7 @@ uuid = { version = "1.0", features = ["v4"] }
|
||||
xpcom = { path = "../../../../xpcom/rust/xpcom", optional = true }
|
||||
thin-vec = { version = "0.2.1", features = ["gecko-ffi"] }
|
||||
mozbuild = "0.1"
|
||||
serde_json = "1"
|
||||
|
||||
[dev-dependencies]
|
||||
tempfile = "3.1.0"
|
||||
|
@ -16,6 +16,7 @@ mod event;
|
||||
mod labeled;
|
||||
mod memory_distribution;
|
||||
mod numerator;
|
||||
mod object;
|
||||
mod ping;
|
||||
mod quantity;
|
||||
mod rate;
|
||||
|
68
toolkit/components/glean/api/src/ffi/object.rs
Normal file
68
toolkit/components/glean/api/src/ffi/object.rs
Normal file
@ -0,0 +1,68 @@
|
||||
// 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;
|
||||
|
||||
use crate::metrics::__glean_metric_maps as metric_maps;
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn fog_object_set_string(id: u32, value: &nsACString) {
|
||||
if id & (1 << crate::factory::DYNAMIC_METRIC_BIT) > 0 {
|
||||
panic!("No dynamic metric for objects");
|
||||
}
|
||||
|
||||
let value = value.to_utf8().to_string();
|
||||
if metric_maps::set_object_by_id(id, value).is_err() {
|
||||
panic!("No object for id {}", id);
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn fog_object_test_has_value(id: u32, ping_name: &nsACString) -> bool {
|
||||
let storage = if ping_name.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(ping_name.to_utf8().into_owned())
|
||||
};
|
||||
if id & (1 << crate::factory::DYNAMIC_METRIC_BIT) > 0 {
|
||||
panic!("No dynamic metric for objects");
|
||||
} else {
|
||||
metric_maps::object_test_get_value(id, storage).is_some()
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn fog_object_test_get_value(
|
||||
id: u32,
|
||||
ping_name: &nsACString,
|
||||
value: &mut nsACString,
|
||||
) {
|
||||
let storage = if ping_name.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(ping_name.to_utf8().into_owned())
|
||||
};
|
||||
|
||||
let object = if id & (1 << crate::factory::DYNAMIC_METRIC_BIT) > 0 {
|
||||
panic!("No dynamic metric for objects");
|
||||
} else {
|
||||
match metric_maps::object_test_get_value(id, storage) {
|
||||
Some(object) => object,
|
||||
None => return,
|
||||
}
|
||||
};
|
||||
value.assign(&object);
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn fog_object_test_get_error(id: u32, error_str: &mut nsACString) -> bool {
|
||||
let err = if id & (1 << crate::factory::DYNAMIC_METRIC_BIT) > 0 {
|
||||
panic!("No dynamic metric for objects");
|
||||
} else {
|
||||
metric_maps::object_test_get_error(id)
|
||||
};
|
||||
err.map(|err_str| error_str.assign(&err_str)).is_some()
|
||||
}
|
@ -24,6 +24,7 @@ mod labeled;
|
||||
mod labeled_counter;
|
||||
mod memory_distribution;
|
||||
mod numerator;
|
||||
mod object;
|
||||
mod ping;
|
||||
mod quantity;
|
||||
mod rate;
|
||||
@ -46,6 +47,7 @@ pub use self::labeled::LabeledMetric;
|
||||
pub use self::labeled_counter::LabeledCounterMetric;
|
||||
pub use self::memory_distribution::MemoryDistributionMetric;
|
||||
pub use self::numerator::NumeratorMetric;
|
||||
pub use self::object::ObjectMetric;
|
||||
pub use self::ping::Ping;
|
||||
pub use self::quantity::QuantityMetric;
|
||||
pub use self::rate::RateMetric;
|
||||
|
83
toolkit/components/glean/api/src/private/object.rs
Normal file
83
toolkit/components/glean/api/src/private/object.rs
Normal file
@ -0,0 +1,83 @@
|
||||
// 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 super::{CommonMetricData, MetricId};
|
||||
|
||||
use crate::ipc::need_ipc;
|
||||
|
||||
use glean::traits::ObjectSerialize;
|
||||
|
||||
/// An object metric.
|
||||
pub enum ObjectMetric<K> {
|
||||
Parent {
|
||||
id: MetricId,
|
||||
inner: glean::private::ObjectMetric<K>,
|
||||
},
|
||||
Child,
|
||||
}
|
||||
|
||||
impl<K: ObjectSerialize> ObjectMetric<K> {
|
||||
/// Create a new object metric.
|
||||
pub fn new(id: MetricId, meta: CommonMetricData) -> Self {
|
||||
if need_ipc() {
|
||||
ObjectMetric::Child
|
||||
} else {
|
||||
let inner = glean::private::ObjectMetric::new(meta);
|
||||
ObjectMetric::Parent { id, inner }
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set(&self, value: K) {
|
||||
match self {
|
||||
ObjectMetric::Parent { inner, .. } => {
|
||||
inner.set(value);
|
||||
}
|
||||
ObjectMetric::Child => {
|
||||
log::error!("Unable to set object metric in non-main process. This operation will be ignored.");
|
||||
// TODO: Record an error.
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
pub fn set_string(&self, value: String) {
|
||||
match self {
|
||||
ObjectMetric::Parent { inner, .. } => {
|
||||
inner.set_string(value);
|
||||
}
|
||||
ObjectMetric::Child => {
|
||||
log::error!("Unable to set object metric in non-main process. This operation will be ignored.");
|
||||
// TODO: Record an error.
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
pub fn test_get_value<'a, S: Into<Option<&'a str>>>(
|
||||
&self,
|
||||
ping_name: S,
|
||||
) -> Option<serde_json::Value> {
|
||||
match self {
|
||||
ObjectMetric::Parent { inner, .. } => inner.test_get_value(ping_name),
|
||||
ObjectMetric::Child => {
|
||||
panic!("Cannot get test value for object metric in non-parent process!",)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn test_get_value_as_str<'a, S: Into<Option<&'a str>>>(
|
||||
&self,
|
||||
ping_name: S,
|
||||
) -> Option<String> {
|
||||
self.test_get_value(ping_name)
|
||||
.map(|val| serde_json::to_string(&val).unwrap())
|
||||
}
|
||||
|
||||
pub fn test_get_num_recorded_errors(&self, error: glean::ErrorType) -> i32 {
|
||||
match self {
|
||||
ObjectMetric::Parent { inner, .. } => inner.test_get_num_recorded_errors(error),
|
||||
ObjectMetric::Child => {
|
||||
panic!("Cannot get the number of recorded errors in non-parent process!")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -14,6 +14,7 @@
|
||||
#include "mozilla/glean/bindings/Labeled.h"
|
||||
#include "mozilla/glean/bindings/MemoryDistribution.h"
|
||||
#include "mozilla/glean/bindings/Numerator.h"
|
||||
#include "mozilla/glean/bindings/Object.h"
|
||||
#include "mozilla/glean/bindings/Quantity.h"
|
||||
#include "mozilla/glean/bindings/Rate.h"
|
||||
#include "mozilla/glean/bindings/String.h"
|
||||
|
80
toolkit/components/glean/bindings/private/Object.cpp
Normal file
80
toolkit/components/glean/bindings/private/Object.cpp
Normal file
@ -0,0 +1,80 @@
|
||||
/* -*- 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/Object.h"
|
||||
|
||||
#include "Common.h"
|
||||
#include "mozilla/dom/GleanMetricsBinding.h"
|
||||
#include "mozilla/dom/ToJSValue.h"
|
||||
#include "mozilla/Logging.h"
|
||||
#include "jsapi.h"
|
||||
#include "js/JSON.h"
|
||||
#include "nsContentUtils.h"
|
||||
|
||||
using namespace mozilla::dom;
|
||||
|
||||
namespace mozilla::glean {
|
||||
|
||||
/* virtual */
|
||||
JSObject* GleanObject::WrapObject(JSContext* aCx,
|
||||
JS::Handle<JSObject*> aGivenProto) {
|
||||
return dom::GleanObject_Binding::Wrap(aCx, this, aGivenProto);
|
||||
}
|
||||
|
||||
void GleanObject::Set(JSContext* aCx, JS::Handle<JSObject*> aObj) {
|
||||
// We take in an `object`. Cannot be `null`!
|
||||
// But at this point the type system doesn't know that.
|
||||
JS::Rooted<JS::Value> value(aCx);
|
||||
value.setObjectOrNull(aObj);
|
||||
|
||||
nsAutoString serializedValue;
|
||||
bool res = nsContentUtils::StringifyJSON(aCx, value, serializedValue,
|
||||
UndefinedIsNullStringLiteral);
|
||||
if (!res) {
|
||||
// JS_Stringify throws an exception, e.g. on cyclic objects.
|
||||
// We don't want this rethrown.
|
||||
JS_ClearPendingException(aCx);
|
||||
|
||||
LogToBrowserConsole(nsIScriptError::warningFlag,
|
||||
u"passed in object cannot be serialized"_ns);
|
||||
return;
|
||||
}
|
||||
|
||||
NS_ConvertUTF16toUTF8 payload(serializedValue);
|
||||
mObject.SetStr(payload);
|
||||
}
|
||||
|
||||
void GleanObject::TestGetValue(JSContext* aCx, const nsACString& aPingName,
|
||||
JS::MutableHandle<JSObject*> aResult,
|
||||
ErrorResult& aRv) {
|
||||
aResult.set(nullptr);
|
||||
|
||||
auto result = mObject.TestGetValue(aPingName);
|
||||
if (result.isErr()) {
|
||||
aRv.ThrowDataError(result.unwrapErr());
|
||||
return;
|
||||
}
|
||||
auto optresult = result.unwrap();
|
||||
if (optresult.isNothing()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const NS_ConvertUTF8toUTF16 str(optresult.ref());
|
||||
JS::Rooted<JS::Value> json(aCx);
|
||||
bool res = JS_ParseJSON(aCx, str.get(), str.Length(), &json);
|
||||
if (!res) {
|
||||
aRv.ThrowDataError("couldn't parse stored object");
|
||||
return;
|
||||
}
|
||||
if (!json.isObject()) {
|
||||
aRv.ThrowDataError("stored data does not represent a valid object");
|
||||
return;
|
||||
}
|
||||
|
||||
aResult.set(&json.toObject());
|
||||
}
|
||||
|
||||
} // namespace mozilla::glean
|
94
toolkit/components/glean/bindings/private/Object.h
Normal file
94
toolkit/components/glean/bindings/private/Object.h
Normal file
@ -0,0 +1,94 @@
|
||||
/* -*- 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_GleanObject_h
|
||||
#define mozilla_glean_GleanObject_h
|
||||
|
||||
#include "mozilla/dom/BindingDeclarations.h"
|
||||
#include "mozilla/glean/bindings/GleanMetric.h"
|
||||
#include "mozilla/glean/fog_ffi_generated.h"
|
||||
#include "mozilla/ResultVariant.h"
|
||||
#include "nsString.h"
|
||||
#include "nsTArray.h"
|
||||
|
||||
namespace mozilla::glean {
|
||||
|
||||
// forward declaration
|
||||
class GleanObject;
|
||||
|
||||
namespace impl {
|
||||
|
||||
template <class T>
|
||||
class ObjectMetric {
|
||||
friend class mozilla::glean::GleanObject;
|
||||
|
||||
public:
|
||||
constexpr explicit ObjectMetric(uint32_t id) : mId(id) {}
|
||||
|
||||
private:
|
||||
const uint32_t mId;
|
||||
|
||||
/* TODO(bug 1881023): Turn this into the public C++ API */
|
||||
/**
|
||||
* **Test-only API**
|
||||
*
|
||||
* Gets the currently stored object as a JSON-encoded 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 Nothing() if there is no value.
|
||||
*/
|
||||
Result<Maybe<nsCString>, nsCString> TestGetValue(
|
||||
const nsACString& aPingName) const {
|
||||
nsCString err;
|
||||
if (fog_object_test_get_error(mId, &err)) {
|
||||
return Err(err);
|
||||
}
|
||||
if (!fog_object_test_has_value(mId, &aPingName)) {
|
||||
return Maybe<nsCString>();
|
||||
}
|
||||
nsCString ret;
|
||||
fog_object_test_get_value(mId, &aPingName, &ret);
|
||||
return Some(ret);
|
||||
}
|
||||
|
||||
void SetStr(const nsACString& aValue) const {
|
||||
fog_object_set_string(mId, &aValue);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace impl
|
||||
|
||||
class GleanObject final : public GleanMetric {
|
||||
public:
|
||||
explicit GleanObject(uint32_t aId, nsISupports* aParent)
|
||||
: GleanMetric(aParent), mObject(aId) {}
|
||||
|
||||
virtual JSObject* WrapObject(
|
||||
JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override final;
|
||||
|
||||
void Set(JSContext* aCx, JS::Handle<JSObject*> aObj);
|
||||
|
||||
void TestGetValue(JSContext* aCx, const nsACString& aPingName,
|
||||
JS::MutableHandle<JSObject*> aResult, ErrorResult& aRv);
|
||||
|
||||
virtual ~GleanObject() = default;
|
||||
|
||||
private:
|
||||
const impl::ObjectMetric<void> mObject;
|
||||
};
|
||||
|
||||
} // namespace mozilla::glean
|
||||
|
||||
#endif /* mozilla_glean_GleanObject.h */
|
@ -68,9 +68,10 @@ def rust_datatypes_filter(value):
|
||||
# CowString is also a 'str' but is a special case.
|
||||
# Ensure its case is handled before str's (below).
|
||||
elif isinstance(value, CowString):
|
||||
yield f'::std::borrow::Cow::from("{value.inner}")'
|
||||
value = json.dumps(value)
|
||||
yield f"::std::borrow::Cow::from({value})"
|
||||
elif isinstance(value, str):
|
||||
yield '"' + value + '".into()'
|
||||
yield f"{json.dumps(value)}.into()"
|
||||
elif isinstance(value, Rate):
|
||||
yield "CommonMetricData {"
|
||||
for arg_name in common_metric_data_args:
|
||||
@ -118,6 +119,10 @@ def type_name(obj):
|
||||
return "{}<{}>".format(
|
||||
class_name(obj.type), util.Camelize(obj.name) + suffix
|
||||
)
|
||||
generate_structure = getattr(obj, "_generate_structure", [])
|
||||
if len(generate_structure):
|
||||
generic = util.Camelize(obj.name) + "Object"
|
||||
return "{}<{}>".format(class_name(obj.type), generic)
|
||||
return class_name(obj.type)
|
||||
|
||||
|
||||
@ -136,6 +141,21 @@ def extra_type_name(typ: str) -> str:
|
||||
return "UNSUPPORTED"
|
||||
|
||||
|
||||
def structure_type_name(typ: str) -> str:
|
||||
"""
|
||||
Returns the corresponding Rust type for structure items.
|
||||
"""
|
||||
|
||||
if typ == "boolean":
|
||||
return "bool"
|
||||
elif typ == "string":
|
||||
return "String"
|
||||
elif typ == "number":
|
||||
return "i64"
|
||||
else:
|
||||
return "UNSUPPORTED"
|
||||
|
||||
|
||||
def class_name(obj_type):
|
||||
"""
|
||||
Returns the Rust class name for a given metric or ping type.
|
||||
@ -208,6 +228,14 @@ def output_rust(objs, output_fd, ping_names_by_app_id, options={}):
|
||||
# 17 -> "test_only::an_event"
|
||||
events_by_id = {}
|
||||
|
||||
# Map from a metric ID to the fully qualified path of the object metric in Rust.
|
||||
# Required for the special handling of object lookups.
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# 18 -> "test_only::an_object"
|
||||
objects_by_id = {}
|
||||
|
||||
# Map from a labeled type (e.g. "counter") to a map from metric ID to the
|
||||
# fully qualified path of the labeled metric object in Rust paired with
|
||||
# whether the labeled metric has an enum.
|
||||
@ -238,6 +266,9 @@ def output_rust(objs, output_fd, ping_names_by_app_id, options={}):
|
||||
if metric.type == "event":
|
||||
events_by_id[get_metric_id(metric)] = full_path
|
||||
continue
|
||||
if metric.type == "object":
|
||||
objects_by_id[get_metric_id(metric)] = full_path
|
||||
continue
|
||||
|
||||
if getattr(metric, "labeled", False):
|
||||
labeled_type = metric.type[8:]
|
||||
@ -261,6 +292,7 @@ def output_rust(objs, output_fd, ping_names_by_app_id, options={}):
|
||||
("snake_case", util.snake_case),
|
||||
("type_name", type_name),
|
||||
("extra_type_name", extra_type_name),
|
||||
("structure_type_name", structure_type_name),
|
||||
("ctor", ctor),
|
||||
("extra_keys", extra_keys),
|
||||
("metric_id", get_metric_id),
|
||||
@ -275,6 +307,7 @@ def output_rust(objs, output_fd, ping_names_by_app_id, options={}):
|
||||
metric_by_type=objs_by_type,
|
||||
extra_args=util.extra_args,
|
||||
events_by_id=events_by_id,
|
||||
objects_by_id=objects_by_id,
|
||||
labeleds_by_id_by_type=labeleds_by_id_by_type,
|
||||
submetric_bit=ID_BITS - ID_SIGNAL_BITS,
|
||||
ping_names_by_app_id=ping_names_by_app_id,
|
||||
|
@ -78,6 +78,7 @@ enum class DynamicLabel: uint16_t { };
|
||||
{% for category_name, objs in all_objs.items() %}
|
||||
namespace {{ category_name|snake_case }} {
|
||||
{% for obj in objs.values() %}
|
||||
{% if obj.type != "object" %}{# TODO(bug 1881023): Add C++ support #}
|
||||
/**
|
||||
* generated from {{ category_name }}.{{ obj.name }}
|
||||
*/
|
||||
@ -91,6 +92,7 @@ namespace {{ category_name|snake_case }} {
|
||||
* {{ obj.description|wordwrap() | replace('\n', '\n * ') }}
|
||||
*/
|
||||
constexpr impl::{{ obj|type_name }} {{obj.name|snake_case }}({{obj|metric_id}});
|
||||
{% endif %}
|
||||
|
||||
{% endfor %}
|
||||
}
|
||||
|
@ -23,7 +23,9 @@ use crate::private::{
|
||||
Ping,
|
||||
LabeledMetric,
|
||||
{% for metric_type_name in metric_types.keys() if not metric_type_name.startswith('labeled_') %}
|
||||
{% if metric_type_name != "object" %}{# TODO(bug 1883857): Add JOG support #}
|
||||
{{ metric_type_name|Camelize }}Metric,
|
||||
{% endif %}
|
||||
{% endfor %}};
|
||||
use crate::private::traits::HistogramType;
|
||||
|
||||
@ -50,7 +52,7 @@ pub(crate) mod __jog_metric_maps {
|
||||
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_') %}
|
||||
{% for metric_type_name in metric_types.keys() if metric_type_name != "event" and not metric_type_name.startswith('labeled_') and metric_type_name != "object" %}
|
||||
pub static {{ metric_type_name.upper() }}_MAP: Lazy<Arc<RwLock<HashMap<MetricId, {{ metric_type_name|Camelize }}Metric>>>> =
|
||||
Lazy::new(|| Arc::new(RwLock::new(HashMap::new())));
|
||||
|
||||
@ -67,6 +69,10 @@ pub(crate) mod __jog_metric_maps {
|
||||
{# Event metrics are special because they're EventMetric<K> #}
|
||||
pub static EVENT_MAP: Lazy<Arc<RwLock<HashMap<MetricId, EventMetric<NoExtraKeys>>>>> =
|
||||
Lazy::new(|| Arc::new(RwLock::new(HashMap::new())));
|
||||
{# Object metrics are special because they're ObjectMetric<K> #}
|
||||
#[allow(dead_code)]
|
||||
pub static OBJECT_MAP: Lazy<Arc<RwLock<HashMap<MetricId, ObjectMetric<()>>>>> =
|
||||
Lazy::new(|| Arc::new(RwLock::new(HashMap::new())));
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
@ -105,6 +111,9 @@ map of argument name to argument type. I may regret this if I need it again. #}
|
||||
let metric32 = match metric_type {
|
||||
{% for metric_type_name, metric_type in metric_types.items() %}
|
||||
"{{ metric_type_name }}" => {
|
||||
{% if metric_type_name == "object" %}{# TODO(bug 1883857): Add JOG support #}
|
||||
return Err(Box::new(MetricTypeNotFoundError(metric_type.to_string())));
|
||||
{% else %}
|
||||
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 }},
|
||||
@ -124,6 +133,7 @@ map of argument name to argument type. I may regret this if I need it again. #}
|
||||
"We should never insert a runtime metric with an already-used id."
|
||||
);
|
||||
metric32
|
||||
{% endif %}
|
||||
}
|
||||
{% endfor %}
|
||||
_ => return Err(Box::new(MetricTypeNotFoundError(metric_type.to_string())))
|
||||
|
@ -8,6 +8,41 @@ Jinja2 template is not. Please file bugs! #}
|
||||
* 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 #}
|
||||
@ -81,6 +116,9 @@ pub mod {{ category_name|snake_case }} {
|
||||
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) }}
|
||||
@ -88,6 +126,9 @@ pub mod {{ category_name|snake_case }} {
|
||||
{% 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 }}
|
||||
///
|
||||
@ -148,6 +189,71 @@ pub(crate) mod __glean_metric_maps {
|
||||
|
||||
{% 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
|
||||
|
@ -42,6 +42,7 @@ EXPORTS.mozilla.glean.bindings += [
|
||||
"bindings/private/Labeled.h",
|
||||
"bindings/private/MemoryDistribution.h",
|
||||
"bindings/private/Numerator.h",
|
||||
"bindings/private/Object.h",
|
||||
"bindings/private/Ping.h",
|
||||
"bindings/private/Quantity.h",
|
||||
"bindings/private/Rate.h",
|
||||
@ -88,6 +89,7 @@ UNIFIED_SOURCES += [
|
||||
"bindings/private/Labeled.cpp",
|
||||
"bindings/private/MemoryDistribution.cpp",
|
||||
"bindings/private/Numerator.cpp",
|
||||
"bindings/private/Object.cpp",
|
||||
"bindings/private/Ping.cpp",
|
||||
"bindings/private/Quantity.cpp",
|
||||
"bindings/private/Rate.cpp",
|
||||
|
@ -26,10 +26,10 @@ using Telemetry::EventID;
|
||||
|
||||
static inline Maybe<EventID> EventIdForMetric(uint32_t aId) {
|
||||
switch(aId) {
|
||||
case 17: { // test.nested.event_metric
|
||||
case 18: { // test.nested.event_metric
|
||||
return Some(EventID::EventMetric_EnumNames_AreStrange);
|
||||
}
|
||||
case 18: { // test.nested.event_metric_with_extra
|
||||
case 19: { // test.nested.event_metric_with_extra
|
||||
return Some(EventID::EventMetric_EnumName_WithExtra);
|
||||
}
|
||||
default: {
|
||||
|
@ -58,13 +58,13 @@ static inline Maybe<ScalarID> ScalarIdForMetric(uint32_t aId) {
|
||||
case 14: { // test.timespan_metric
|
||||
return Some(ScalarID::SOME_OTHER_UINT_SCALAR);
|
||||
}
|
||||
case 16: { // test.nested.datetime_metric
|
||||
case 17: { // test.nested.datetime_metric
|
||||
return Some(ScalarID::SOME_STILL_OTHER_STRING_SCALAR);
|
||||
}
|
||||
case 21: { // test.nested.quantity_metric
|
||||
case 22: { // test.nested.quantity_metric
|
||||
return Some(ScalarID::TELEMETRY_TEST_MIRROR_FOR_QUANTITY);
|
||||
}
|
||||
case 24: { // test.nested.uuid_metric
|
||||
case 25: { // test.nested.uuid_metric
|
||||
return Some(ScalarID::SOME_OTHER_STRING_SCALAR);
|
||||
}
|
||||
default: {
|
||||
|
@ -188,6 +188,15 @@
|
||||
]
|
||||
],
|
||||
"test.nested": [
|
||||
[
|
||||
"object",
|
||||
"an_object",
|
||||
[
|
||||
"metrics"
|
||||
],
|
||||
"ping",
|
||||
false
|
||||
],
|
||||
[
|
||||
"datetime",
|
||||
"datetime_metric",
|
||||
|
@ -396,3 +396,23 @@ test.nested:
|
||||
- https://bugzilla.mozilla.org/1635260/
|
||||
data_reviews:
|
||||
- https://example.com
|
||||
|
||||
an_object:
|
||||
type: object
|
||||
description: An example object
|
||||
bugs:
|
||||
- https://bugzilla.mozilla.org/1839640
|
||||
data_reviews:
|
||||
- http://example.com/reviews
|
||||
notification_emails:
|
||||
- CHANGE-ME@example.com
|
||||
expires: never
|
||||
structure:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
properties:
|
||||
colour:
|
||||
type: string
|
||||
diameter:
|
||||
type: number
|
||||
|
@ -6,6 +6,7 @@
|
||||
* 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/. */
|
||||
|
||||
|
||||
pub enum DynamicLabel { }
|
||||
|
||||
pub mod test {
|
||||
@ -16,6 +17,9 @@ pub mod test {
|
||||
use glean::HistogramType;
|
||||
use once_cell::sync::Lazy;
|
||||
|
||||
#[allow(unused_imports)]
|
||||
use std::convert::TryFrom;
|
||||
|
||||
#[allow(non_upper_case_globals)]
|
||||
/// generated from test.boolean_metric
|
||||
///
|
||||
@ -361,13 +365,40 @@ pub mod test_nested {
|
||||
use glean::HistogramType;
|
||||
use once_cell::sync::Lazy;
|
||||
|
||||
#[allow(unused_imports)]
|
||||
use std::convert::TryFrom;
|
||||
|
||||
pub type AnObjectObject = Vec<AnObjectObjectItem>;
|
||||
|
||||
#[derive(Debug, Hash, Eq, PartialEq, ::glean::traits::__serde::Serialize, ::glean::traits::__serde::Deserialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct AnObjectObjectItem {
|
||||
pub colour: Option<String>,
|
||||
pub diameter: Option<i64>,
|
||||
}
|
||||
|
||||
#[allow(non_upper_case_globals)]
|
||||
/// generated from test.nested.an_object
|
||||
///
|
||||
/// An example object
|
||||
pub static an_object: Lazy<ObjectMetric<AnObjectObject>> = Lazy::new(|| {
|
||||
ObjectMetric::new(16.into(), CommonMetricData {
|
||||
name: "an_object".into(),
|
||||
category: "test.nested".into(),
|
||||
send_in_pings: vec!["metrics".into()],
|
||||
lifetime: Lifetime::Ping,
|
||||
disabled: false,
|
||||
..Default::default()
|
||||
})
|
||||
});
|
||||
|
||||
#[allow(non_upper_case_globals)]
|
||||
/// generated from test.nested.datetime_metric
|
||||
///
|
||||
/// A multi-line
|
||||
/// description
|
||||
pub static datetime_metric: Lazy<DatetimeMetric> = Lazy::new(|| {
|
||||
DatetimeMetric::new(16.into(), CommonMetricData {
|
||||
DatetimeMetric::new(17.into(), CommonMetricData {
|
||||
name: "datetime_metric".into(),
|
||||
category: "test.nested".into(),
|
||||
send_in_pings: vec!["metrics".into()],
|
||||
@ -383,7 +414,7 @@ pub mod test_nested {
|
||||
/// A multi-line
|
||||
/// description
|
||||
pub static event_metric: Lazy<EventMetric<NoExtraKeys>> = Lazy::new(|| {
|
||||
EventMetric::new(17.into(), CommonMetricData {
|
||||
EventMetric::new(18.into(), CommonMetricData {
|
||||
name: "event_metric".into(),
|
||||
category: "test.nested".into(),
|
||||
send_in_pings: vec!["events".into()],
|
||||
@ -415,7 +446,7 @@ pub mod test_nested {
|
||||
/// A multi-line
|
||||
/// description
|
||||
pub static event_metric_with_extra: Lazy<EventMetric<EventMetricWithExtraExtra>> = Lazy::new(|| {
|
||||
EventMetric::new(18.into(), CommonMetricData {
|
||||
EventMetric::new(19.into(), CommonMetricData {
|
||||
name: "event_metric_with_extra".into(),
|
||||
category: "test.nested".into(),
|
||||
send_in_pings: vec!["events".into()],
|
||||
@ -431,7 +462,7 @@ pub mod test_nested {
|
||||
/// A multi-line
|
||||
/// description
|
||||
pub static external_denominator: Lazy<DenominatorMetric> = Lazy::new(|| {
|
||||
DenominatorMetric::new(19.into(), CommonMetricData {
|
||||
DenominatorMetric::new(20.into(), CommonMetricData {
|
||||
name: "external_denominator".into(),
|
||||
category: "test.nested".into(),
|
||||
send_in_pings: vec!["metrics".into()],
|
||||
@ -448,7 +479,7 @@ pub mod test_nested {
|
||||
/// description
|
||||
pub static optimizable_counter_metric: Lazy<CounterMetric> = Lazy::new(|| {
|
||||
CounterMetric::codegen_new(
|
||||
20,
|
||||
21,
|
||||
"test.nested",
|
||||
"optimizable_counter_metric",
|
||||
"metrics"
|
||||
@ -461,7 +492,7 @@ pub mod test_nested {
|
||||
/// A multi-line
|
||||
/// description
|
||||
pub static quantity_metric: Lazy<QuantityMetric> = Lazy::new(|| {
|
||||
QuantityMetric::new(21.into(), CommonMetricData {
|
||||
QuantityMetric::new(22.into(), CommonMetricData {
|
||||
name: "quantity_metric".into(),
|
||||
category: "test.nested".into(),
|
||||
send_in_pings: vec!["metrics".into()],
|
||||
@ -477,7 +508,7 @@ pub mod test_nested {
|
||||
/// A multi-line
|
||||
/// description
|
||||
pub static rate_metric: Lazy<RateMetric> = Lazy::new(|| {
|
||||
RateMetric::new(22.into(), CommonMetricData {
|
||||
RateMetric::new(23.into(), CommonMetricData {
|
||||
name: "rate_metric".into(),
|
||||
category: "test.nested".into(),
|
||||
send_in_pings: vec!["metrics".into()],
|
||||
@ -493,7 +524,7 @@ pub mod test_nested {
|
||||
/// A multi-line
|
||||
/// description
|
||||
pub static rate_with_external_denominator: Lazy<NumeratorMetric> = Lazy::new(|| {
|
||||
NumeratorMetric::new(23.into(), CommonMetricData {
|
||||
NumeratorMetric::new(24.into(), CommonMetricData {
|
||||
name: "rate_with_external_denominator".into(),
|
||||
category: "test.nested".into(),
|
||||
send_in_pings: vec!["metrics".into()],
|
||||
@ -509,7 +540,7 @@ pub mod test_nested {
|
||||
/// A multi-line
|
||||
/// description
|
||||
pub static uuid_metric: Lazy<UuidMetric> = Lazy::new(|| {
|
||||
UuidMetric::new(24.into(), CommonMetricData {
|
||||
UuidMetric::new(25.into(), CommonMetricData {
|
||||
name: "uuid_metric".into(),
|
||||
category: "test.nested".into(),
|
||||
send_in_pings: vec!["metrics".into()],
|
||||
@ -538,7 +569,7 @@ pub(crate) mod __glean_metric_maps {
|
||||
pub static COUNTER_MAP: Lazy<HashMap<MetricId, &Lazy<CounterMetric>>> = Lazy::new(|| {
|
||||
let mut map = HashMap::with_capacity(2);
|
||||
map.insert(2.into(), &super::test::counter_metric);
|
||||
map.insert(20.into(), &super::test_nested::optimizable_counter_metric);
|
||||
map.insert(21.into(), &super::test_nested::optimizable_counter_metric);
|
||||
map
|
||||
});
|
||||
|
||||
@ -586,41 +617,100 @@ pub(crate) mod __glean_metric_maps {
|
||||
|
||||
pub static DATETIME_MAP: Lazy<HashMap<MetricId, &Lazy<DatetimeMetric>>> = Lazy::new(|| {
|
||||
let mut map = HashMap::with_capacity(1);
|
||||
map.insert(16.into(), &super::test_nested::datetime_metric);
|
||||
map.insert(17.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(19.into(), &super::test_nested::external_denominator);
|
||||
map.insert(20.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(21.into(), &super::test_nested::quantity_metric);
|
||||
map.insert(22.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(22.into(), &super::test_nested::rate_metric);
|
||||
map.insert(23.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(23.into(), &super::test_nested::rate_with_external_denominator);
|
||||
map.insert(24.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(24.into(), &super::test_nested::uuid_metric);
|
||||
map.insert(25.into(), &super::test_nested::uuid_metric);
|
||||
map
|
||||
});
|
||||
|
||||
|
||||
pub(crate) fn set_object_by_id(metric_id: u32, value: String) -> Result<(), ()> {
|
||||
match metric_id {
|
||||
16 => {
|
||||
super::test_nested::an_object.set_string(value);
|
||||
Ok(())
|
||||
}
|
||||
_ => 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 {
|
||||
16 => super::test_nested::an_object.test_get_value_as_str(ping_name.as_deref()),
|
||||
_ => 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 {
|
||||
16 => test_get_errors!(super::test_nested::an_object),
|
||||
_ => 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
|
||||
@ -635,7 +725,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 {
|
||||
17 => {
|
||||
18 => {
|
||||
assert!(
|
||||
extra_keys_len(&super::test_nested::event_metric) != 0 || extra.is_empty(),
|
||||
"No extra keys allowed, but some were passed"
|
||||
@ -644,7 +734,7 @@ pub(crate) mod __glean_metric_maps {
|
||||
super::test_nested::event_metric.record_raw(extra);
|
||||
Ok(())
|
||||
}
|
||||
18 => {
|
||||
19 => {
|
||||
assert!(
|
||||
extra_keys_len(&super::test_nested::event_metric_with_extra) != 0 || extra.is_empty(),
|
||||
"No extra keys allowed, but some were passed"
|
||||
@ -673,7 +763,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(17) => {
|
||||
MetricId(18) => {
|
||||
if extra_keys_len(&super::test_nested::event_metric) == 0 && !extra.is_empty() {
|
||||
return Err(EventRecordingError::InvalidExtraKey);
|
||||
}
|
||||
@ -681,7 +771,7 @@ pub(crate) mod __glean_metric_maps {
|
||||
super::test_nested::event_metric.record_with_time(timestamp, extra);
|
||||
Ok(())
|
||||
}
|
||||
MetricId(18) => {
|
||||
MetricId(19) => {
|
||||
if extra_keys_len(&super::test_nested::event_metric_with_extra) == 0 && !extra.is_empty() {
|
||||
return Err(EventRecordingError::InvalidExtraKey);
|
||||
}
|
||||
@ -710,8 +800,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 {
|
||||
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()),
|
||||
18 => super::test_nested::event_metric.test_get_value(ping_name.as_deref()),
|
||||
19 => super::test_nested::event_metric_with_extra.test_get_value(ping_name.as_deref()),
|
||||
_ => panic!("No event for metric id {}", metric_id),
|
||||
}
|
||||
}
|
||||
@ -735,8 +825,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 {
|
||||
17 => test_get_errors!(super::test_nested::event_metric),
|
||||
18 => test_get_errors!(super::test_nested::event_metric_with_extra),
|
||||
18 => test_get_errors!(super::test_nested::event_metric),
|
||||
19 => test_get_errors!(super::test_nested::event_metric_with_extra),
|
||||
_ => panic!("No event for metric id {}", metric_id),
|
||||
}
|
||||
|
||||
|
@ -181,6 +181,7 @@ namespace test {
|
||||
|
||||
}
|
||||
namespace test_nested {
|
||||
|
||||
/**
|
||||
* generated from test.nested.datetime_metric
|
||||
*/
|
||||
@ -188,7 +189,7 @@ namespace test_nested {
|
||||
* A multi-line
|
||||
* description
|
||||
*/
|
||||
constexpr impl::DatetimeMetric datetime_metric(16);
|
||||
constexpr impl::DatetimeMetric datetime_metric(17);
|
||||
|
||||
/**
|
||||
* generated from test.nested.event_metric
|
||||
@ -197,7 +198,7 @@ namespace test_nested {
|
||||
* A multi-line
|
||||
* description
|
||||
*/
|
||||
constexpr impl::EventMetric<NoExtraKeys> event_metric(17);
|
||||
constexpr impl::EventMetric<NoExtraKeys> event_metric(18);
|
||||
|
||||
/**
|
||||
* generated from test.nested.event_metric_with_extra
|
||||
@ -224,7 +225,7 @@ namespace test_nested {
|
||||
* A multi-line
|
||||
* description
|
||||
*/
|
||||
constexpr impl::EventMetric<EventMetricWithExtraExtra> event_metric_with_extra(18);
|
||||
constexpr impl::EventMetric<EventMetricWithExtraExtra> event_metric_with_extra(19);
|
||||
|
||||
/**
|
||||
* generated from test.nested.external_denominator
|
||||
@ -233,7 +234,7 @@ namespace test_nested {
|
||||
* A multi-line
|
||||
* description
|
||||
*/
|
||||
constexpr impl::DenominatorMetric external_denominator(19);
|
||||
constexpr impl::DenominatorMetric external_denominator(20);
|
||||
|
||||
/**
|
||||
* generated from test.nested.optimizable_counter_metric
|
||||
@ -242,7 +243,7 @@ namespace test_nested {
|
||||
* A multi-line
|
||||
* description
|
||||
*/
|
||||
constexpr impl::CounterMetric optimizable_counter_metric(20);
|
||||
constexpr impl::CounterMetric optimizable_counter_metric(21);
|
||||
|
||||
/**
|
||||
* generated from test.nested.quantity_metric
|
||||
@ -251,7 +252,7 @@ namespace test_nested {
|
||||
* A multi-line
|
||||
* description
|
||||
*/
|
||||
constexpr impl::QuantityMetric quantity_metric(21);
|
||||
constexpr impl::QuantityMetric quantity_metric(22);
|
||||
|
||||
/**
|
||||
* generated from test.nested.rate_metric
|
||||
@ -260,7 +261,7 @@ namespace test_nested {
|
||||
* A multi-line
|
||||
* description
|
||||
*/
|
||||
constexpr impl::RateMetric rate_metric(22);
|
||||
constexpr impl::RateMetric rate_metric(23);
|
||||
|
||||
/**
|
||||
* generated from test.nested.rate_with_external_denominator
|
||||
@ -269,7 +270,7 @@ namespace test_nested {
|
||||
* A multi-line
|
||||
* description
|
||||
*/
|
||||
constexpr impl::NumeratorMetric rate_with_external_denominator(23);
|
||||
constexpr impl::NumeratorMetric rate_with_external_denominator(24);
|
||||
|
||||
/**
|
||||
* generated from test.nested.uuid_metric
|
||||
@ -278,7 +279,7 @@ namespace test_nested {
|
||||
* A multi-line
|
||||
* description
|
||||
*/
|
||||
constexpr impl::UuidMetric uuid_metric(24);
|
||||
constexpr impl::UuidMetric uuid_metric(25);
|
||||
|
||||
}
|
||||
|
||||
|
@ -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(24 < 33554432, "Too many metrics generated. Need room for 2 signal bits.");
|
||||
static_assert(19 < 32, "Too many different metric types.");
|
||||
static_assert(25 < 33554432, "Too many metrics generated. Need room for 2 signal bits.");
|
||||
static_assert(20 < 32, "Too many different metric types.");
|
||||
|
||||
already_AddRefed<GleanMetric> NewMetricFromId(uint32_t id, nsISupports* aParent) {
|
||||
uint32_t typeId = GLEAN_TYPE_ID(id);
|
||||
@ -95,31 +95,35 @@ already_AddRefed<GleanMetric> NewMetricFromId(uint32_t id, nsISupports* aParent)
|
||||
{
|
||||
return MakeAndAddRef<GleanTimingDistribution>(metricId, aParent);
|
||||
}
|
||||
case 13: /* datetime */
|
||||
case 13: /* object */
|
||||
{
|
||||
return MakeAndAddRef<GleanObject>(metricId, aParent);
|
||||
}
|
||||
case 14: /* datetime */
|
||||
{
|
||||
return MakeAndAddRef<GleanDatetime>(metricId, aParent);
|
||||
}
|
||||
case 14: /* event */
|
||||
case 15: /* event */
|
||||
{
|
||||
return MakeAndAddRef<GleanEvent>(metricId, aParent);
|
||||
}
|
||||
case 15: /* denominator */
|
||||
case 16: /* denominator */
|
||||
{
|
||||
return MakeAndAddRef<GleanDenominator>(metricId, aParent);
|
||||
}
|
||||
case 16: /* quantity */
|
||||
case 17: /* quantity */
|
||||
{
|
||||
return MakeAndAddRef<GleanQuantity>(metricId, aParent);
|
||||
}
|
||||
case 17: /* rate */
|
||||
case 18: /* rate */
|
||||
{
|
||||
return MakeAndAddRef<GleanRate>(metricId, aParent);
|
||||
}
|
||||
case 18: /* numerator */
|
||||
case 19: /* numerator */
|
||||
{
|
||||
return MakeAndAddRef<GleanNumerator>(metricId, aParent);
|
||||
}
|
||||
case 19: /* uuid */
|
||||
case 20: /* uuid */
|
||||
{
|
||||
return MakeAndAddRef<GleanUuid>(metricId, aParent);
|
||||
}
|
||||
@ -289,45 +293,47 @@ constexpr char gMetricStringTable[] = {
|
||||
/* 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.optimizableCounterMetric" */ 't', 'e', 's', 't', 'N', 'e', 's', 't', 'e', 'd', '.', 'o', 'p', 't', 'i', 'm', 'i', 'z', 'a', 'b', 'l', 'e', 'C', 'o', 'u', 'n', 't', 'e', 'r', 'M', 'e', 't', 'r', 'i', 'c', '\0',
|
||||
/* 524 - "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',
|
||||
/* 550 - "testNested.rateMetric" */ 't', 'e', 's', 't', 'N', 'e', 's', 't', 'e', 'd', '.', 'r', 'a', 't', 'e', 'M', 'e', 't', 'r', 'i', 'c', '\0',
|
||||
/* 572 - "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',
|
||||
/* 611 - "testNested.uuidMetric" */ 't', 'e', 's', 't', 'N', 'e', 's', 't', 'e', 'd', '.', 'u', 'u', 'i', 'd', 'M', 'e', 't', 'r', 'i', 'c', '\0',
|
||||
/* 376 - "testNested.anObject" */ 't', 'e', 's', 't', 'N', 'e', 's', 't', 'e', 'd', '.', 'a', 'n', 'O', 'b', 'j', 'e', 'c', 't', '\0',
|
||||
/* 396 - "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',
|
||||
/* 422 - "testNested.eventMetric" */ 't', 'e', 's', 't', 'N', 'e', 's', 't', 'e', 'd', '.', 'e', 'v', 'e', 'n', 't', 'M', 'e', 't', 'r', 'i', 'c', '\0',
|
||||
/* 445 - "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',
|
||||
/* 477 - "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',
|
||||
/* 508 - "testNested.optimizableCounterMetric" */ 't', 'e', 's', 't', 'N', 'e', 's', 't', 'e', 'd', '.', 'o', 'p', 't', 'i', 'm', 'i', 'z', 'a', 'b', 'l', 'e', 'C', 'o', 'u', 'n', 't', 'e', 'r', 'M', 'e', 't', 'r', 'i', 'c', '\0',
|
||||
/* 544 - "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',
|
||||
/* 570 - "testNested.rateMetric" */ 't', 'e', 's', 't', 'N', 'e', 's', 't', 'e', 'd', '.', 'r', 'a', 't', 'e', 'M', 'e', 't', 'r', 'i', 'c', '\0',
|
||||
/* 592 - "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',
|
||||
/* 631 - "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[] = {
|
||||
6341068335467200838ull,
|
||||
3458764548180279480ull,
|
||||
1152921590506193384ull,
|
||||
576460756598390784ull,
|
||||
2882303787286921342ull,
|
||||
6917529092065591642ull,
|
||||
9799832883647480358ull,
|
||||
2305843026393563204ull,
|
||||
7493989848663982456ull,
|
||||
1152921513196781587ull,
|
||||
8070450609557340585ull,
|
||||
2305843030688530526ull,
|
||||
5188146822270419236ull,
|
||||
8646911366155731401ull,
|
||||
1729382269795172390ull,
|
||||
10952754396844261987ull,
|
||||
4035225309073637616ull,
|
||||
10376293640245871164ull,
|
||||
9223372127049089548ull,
|
||||
5764607578868810038ull,
|
||||
8070450605262373266ull,
|
||||
2882303791581888664ull,
|
||||
1152921513196781587ull,
|
||||
1729382269795172390ull,
|
||||
3458764552475246801ull,
|
||||
10952754396844261968ull,
|
||||
4611686065672028430ull,
|
||||
3458764552475246801ull
|
||||
2305843026393563204ull,
|
||||
1152921594801160700ull,
|
||||
5188146822270419236ull,
|
||||
3458764548180279480ull,
|
||||
8646911361860764070ull,
|
||||
8646911366155731389ull,
|
||||
8070450605262373260ull,
|
||||
9799832883647480352ull,
|
||||
11529215153442652791ull,
|
||||
2305843030688530526ull,
|
||||
6917529092065591642ull,
|
||||
9223372122754122205ull,
|
||||
10376293640245871162ull,
|
||||
4035225309073637616ull,
|
||||
2882303787286921342ull,
|
||||
576460756598390784ull,
|
||||
7493989848663982456ull,
|
||||
2882303791581888664ull,
|
||||
6341068335467200838ull
|
||||
};
|
||||
|
||||
|
||||
@ -365,39 +371,39 @@ MetricByNameLookup(const nsACString& aKey)
|
||||
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,
|
||||
1, 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, 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, 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, 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, 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, 3, 0, 0, 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, 1, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 3, 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, 2, 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, 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, 3, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 1, 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,
|
||||
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, 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, 6, 0, 12, 0, 0, 0, 0, 0, 0, 0,
|
||||
11, 0, 0, 0, 3, 0, 0, 3, 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, 2, 0, 2, 0, 0, 0, 0, 0, 0, 0,
|
||||
2, 0, 0, 0, 6, 0, 0, 51, 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,
|
||||
};
|
||||
|
@ -69,7 +69,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[24];
|
||||
extern const metric_entry_t sMetricByNameLookupEntries[25];
|
||||
|
||||
} // namespace mozilla::glean
|
||||
#endif // mozilla_GleanJSMetricsLookup_h
|
||||
|
@ -403,6 +403,25 @@ test_only:
|
||||
- test-ping
|
||||
telemetry_mirror: TELEMETRY_TEST_MIRROR_FOR_QUANTITY
|
||||
|
||||
balloons:
|
||||
type: object
|
||||
description: A collection of balloons
|
||||
bugs:
|
||||
- https://bugzilla.mozilla.org/1839640
|
||||
data_reviews:
|
||||
- http://example.com/reviews
|
||||
notification_emails:
|
||||
- CHANGE-ME@example.com
|
||||
expires: never
|
||||
structure:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
properties:
|
||||
colour:
|
||||
type: string
|
||||
diameter:
|
||||
type: number
|
||||
|
||||
test_only.ipc:
|
||||
a_counter:
|
||||
|
@ -459,3 +459,100 @@ add_task(async function test_fog_text_works_unusual_character() {
|
||||
|
||||
Assert.greater(rslt.length, 100);
|
||||
});
|
||||
|
||||
add_task(async function test_fog_object_works() {
|
||||
Assert.equal(
|
||||
undefined,
|
||||
Glean.testOnly.balloons.testGetValue(),
|
||||
"No object stored"
|
||||
);
|
||||
|
||||
// Can't store not-objects.
|
||||
let invalidValues = [1, "str", false, undefined, null, NaN, Infinity];
|
||||
for (let value of invalidValues) {
|
||||
Assert.throws(
|
||||
() => Glean.testOnly.balloons.set(value),
|
||||
/is not an object/,
|
||||
"Should throw a type error"
|
||||
);
|
||||
}
|
||||
|
||||
// No invalid value will be stored.
|
||||
Assert.equal(
|
||||
undefined,
|
||||
Glean.testOnly.balloons.testGetValue(),
|
||||
"No object stored"
|
||||
);
|
||||
|
||||
// `JS_Stringify` internally throws
|
||||
// an `TypeError: cyclic object value` exception.
|
||||
// That's cleared and `set` should not throw on it.
|
||||
// This eventually should log a proper error in Glean.
|
||||
let selfref = {};
|
||||
selfref.a = selfref;
|
||||
Glean.testOnly.balloons.set(selfref);
|
||||
Assert.equal(
|
||||
undefined,
|
||||
Glean.testOnly.balloons.testGetValue(),
|
||||
"No object stored"
|
||||
);
|
||||
|
||||
let balloons = [
|
||||
{ colour: "red", diameter: 5 },
|
||||
{ colour: "blue", diameter: 7 },
|
||||
{ colour: "orange" },
|
||||
];
|
||||
Glean.testOnly.balloons.set(balloons);
|
||||
|
||||
let result = Glean.testOnly.balloons.testGetValue();
|
||||
let expected = [
|
||||
{ colour: "red", diameter: 5 },
|
||||
{ colour: "blue", diameter: 7 },
|
||||
{ colour: "orange", diameter: null },
|
||||
];
|
||||
Assert.deepEqual(expected, result);
|
||||
|
||||
// These values are coerced to null or removed.
|
||||
balloons = [
|
||||
{ colour: "inf", diameter: Infinity },
|
||||
{ colour: "negative-inf", diameter: -1 / 0 },
|
||||
{ colour: "nan", diameter: NaN },
|
||||
{ colour: "undef", diameter: undefined },
|
||||
];
|
||||
Glean.testOnly.balloons.set(balloons);
|
||||
result = Glean.testOnly.balloons.testGetValue();
|
||||
expected = [
|
||||
{ colour: "inf", diameter: null },
|
||||
{ colour: "negative-inf", diameter: null },
|
||||
{ colour: "nan", diameter: null },
|
||||
{ colour: "undef", diameter: null },
|
||||
];
|
||||
Assert.deepEqual(expected, result);
|
||||
|
||||
// colour != color.
|
||||
let invalid = [{ color: "orange" }, { color: "red", diameter: "small" }];
|
||||
Glean.testOnly.balloons.set(invalid);
|
||||
Assert.throws(
|
||||
() => Glean.testOnly.balloons.testGetValue(),
|
||||
/invalid_value/,
|
||||
"Should throw because last object was invalid."
|
||||
);
|
||||
|
||||
Services.fog.testResetFOG();
|
||||
// set again to ensure it's stored
|
||||
balloons = [
|
||||
{ colour: "red", diameter: 5 },
|
||||
{ colour: "blue", diameter: 7 },
|
||||
];
|
||||
Glean.testOnly.balloons.set(balloons);
|
||||
result = Glean.testOnly.balloons.testGetValue();
|
||||
Assert.deepEqual(balloons, result);
|
||||
|
||||
invalid = [{ colour: "red", diameter: 5, extra: "field" }];
|
||||
Glean.testOnly.balloons.set(invalid);
|
||||
Assert.throws(
|
||||
() => Glean.testOnly.balloons.testGetValue(),
|
||||
/invalid_value/,
|
||||
"Should throw because last object was invalid."
|
||||
);
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user