зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1673664 - Implement C++ and JS FOG APIs for UUID r=janerik,brizental
Differential Revision: https://phabricator.services.mozilla.com/D95590
This commit is contained in:
Родитель
02ff8b6e97
Коммит
a79272a14e
|
@ -1543,8 +1543,10 @@ dependencies = [
|
|||
"bincode",
|
||||
"chrono",
|
||||
"crossbeam-channel",
|
||||
"ffi-support",
|
||||
"glean-core",
|
||||
"log",
|
||||
"nsstring",
|
||||
"once_cell",
|
||||
"serde",
|
||||
"tempfile",
|
||||
|
|
|
@ -8,8 +8,10 @@ publish = false
|
|||
[dependencies]
|
||||
bincode = "1.0"
|
||||
chrono = "0.4.10"
|
||||
ffi-support = "0.4"
|
||||
glean-core = "31.4.0"
|
||||
log = "0.4"
|
||||
nsstring = { path = "../../../../xpcom/rust/nsstring", optional = true }
|
||||
once_cell = "1.2.0"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
uuid = { version = "0.8.1", features = ["v4"] }
|
||||
|
@ -21,4 +23,4 @@ crossbeam-channel = "0.4.3"
|
|||
tempfile = "3.1.0"
|
||||
|
||||
[features]
|
||||
with_gecko = ["xpcom"]
|
||||
with_gecko = ["xpcom", "nsstring"]
|
||||
|
|
|
@ -5,6 +5,10 @@
|
|||
#[macro_use]
|
||||
mod macros;
|
||||
|
||||
use ffi_support::FfiStr;
|
||||
#[cfg(feature = "with_gecko")]
|
||||
use {nsstring::nsACString, uuid::Uuid};
|
||||
|
||||
define_metric_ffi!(COUNTER_MAP {
|
||||
test_has -> fog_counter_test_has_value,
|
||||
test_get -> fog_counter_test_get_value: i32,
|
||||
|
@ -17,3 +21,50 @@ define_metric_ffi!(TIMESPAN_MAP {
|
|||
start -> fog_timespan_start(),
|
||||
stop -> fog_timespan_stop(),
|
||||
});
|
||||
|
||||
// The Uuid functions are custom because test_get needs to use an outparam.
|
||||
// If we can make test_get optional, we can go back to using the macro to
|
||||
// generate the rest of the functions, or something.
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn fog_uuid_test_has_value(id: u32, storage_name: FfiStr) -> u8 {
|
||||
match crate::metrics::__glean_metric_maps::UUID_MAP.get(&id.into()) {
|
||||
Some(metric) => metric.test_get_value(storage_name.as_str()).is_some() as u8,
|
||||
None => panic!("No metric for id {}", id),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "with_gecko")]
|
||||
#[no_mangle]
|
||||
pub extern "C" fn fog_uuid_test_get_value(id: u32, storage_name: FfiStr, value: &mut nsACString) {
|
||||
match crate::metrics::__glean_metric_maps::UUID_MAP.get(&id.into()) {
|
||||
Some(uuid) => {
|
||||
value.assign(
|
||||
&uuid
|
||||
.test_get_value(storage_name.as_str())
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
);
|
||||
}
|
||||
None => panic!("No metric for id {}", id),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "with_gecko")]
|
||||
#[no_mangle]
|
||||
pub extern "C" fn fog_uuid_set(id: u32, value: &nsACString) {
|
||||
if let Ok(uuid) = Uuid::parse_str(&value.to_utf8()) {
|
||||
match crate::metrics::__glean_metric_maps::UUID_MAP.get(&id.into()) {
|
||||
Some(metric) => metric.set(uuid),
|
||||
None => panic!("No metric for id {}", id),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn fog_uuid_generate_and_set(id: u32) {
|
||||
match crate::metrics::__glean_metric_maps::UUID_MAP.get(&id.into()) {
|
||||
Some(metric) => metric.generate_and_set(),
|
||||
None => panic!("No metric for id {}", id),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,5 +7,6 @@
|
|||
|
||||
#include "mozilla/glean/Counter.h"
|
||||
#include "mozilla/glean/Timespan.h"
|
||||
#include "mozilla/glean/Uuid.h"
|
||||
|
||||
#endif // mozilla_Glean_MetricTypes_h
|
||||
|
|
|
@ -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/. */
|
||||
|
||||
#include "mozilla/glean/Uuid.h"
|
||||
|
||||
#include "nsString.h"
|
||||
#include "mozilla/Components.h"
|
||||
#include "nsIClassInfoImpl.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace glean {
|
||||
|
||||
NS_IMPL_CLASSINFO(GleanUuid, nullptr, 0, {0})
|
||||
NS_IMPL_ISUPPORTS_CI(GleanUuid, nsIGleanUuid)
|
||||
|
||||
NS_IMETHODIMP
|
||||
GleanUuid::Set(const nsACString& value, JSContext* cx) {
|
||||
this->mUuid.Set(value);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
GleanUuid::GenerateAndSet(JSContext* cx) {
|
||||
this->mUuid.GenerateAndSet();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
GleanUuid::TestHasValue(const nsACString& aStorageName, JSContext* cx,
|
||||
bool* result) {
|
||||
*result = this->mUuid.TestHasValue(PromiseFlatCString(aStorageName).get());
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
GleanUuid::TestGetValue(const nsACString& aStorageName, JSContext* cx,
|
||||
nsACString& result) {
|
||||
result.Assign(
|
||||
this->mUuid.TestGetValue(PromiseFlatCString(aStorageName).get()));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
} // namespace glean
|
||||
} // namespace mozilla
|
|
@ -0,0 +1,101 @@
|
|||
/* -*- 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_GleanUuid_h
|
||||
#define mozilla_glean_GleanUuid_h
|
||||
|
||||
#include "nsIGleanMetrics.h"
|
||||
#include "nsString.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace glean {
|
||||
|
||||
namespace impl {
|
||||
extern "C" {
|
||||
void fog_uuid_set(uint32_t id, const nsACString& uuid);
|
||||
void fog_uuid_generate_and_set(uint32_t id);
|
||||
uint32_t fog_uuid_test_has_value(uint32_t id, const char* storageName);
|
||||
void fog_uuid_test_get_value(uint32_t id, const char* storageName,
|
||||
nsACString& value);
|
||||
}
|
||||
|
||||
class UuidMetric {
|
||||
public:
|
||||
constexpr explicit UuidMetric(uint32_t id) : mId(id) {}
|
||||
|
||||
/*
|
||||
* Sets to the specified value.
|
||||
*
|
||||
* @param value The UUID to set the metric to.
|
||||
*/
|
||||
void Set(const nsACString& value) const { fog_uuid_set(mId, value); }
|
||||
|
||||
/*
|
||||
* Generate a new random UUID and set the metric to it.
|
||||
*/
|
||||
void GenerateAndSet() const { fog_uuid_generate_and_set(mId); }
|
||||
|
||||
/**
|
||||
* **Test-only API**
|
||||
*
|
||||
* Tests whether a value is stored for the metric.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Parent process only. Panics in child processes.
|
||||
*
|
||||
* @param aStorageName the name of the ping to retrieve the metric for.
|
||||
* @return true if metric value exists, otherwise false
|
||||
*/
|
||||
bool TestHasValue(const char* aStorageName) const {
|
||||
return fog_uuid_test_has_value(mId, aStorageName) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* **Test-only API**
|
||||
*
|
||||
* Gets the currently stored value as a hyphenated 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.
|
||||
* Panics if there is no value to get.
|
||||
*
|
||||
* @return value of the stored metric.
|
||||
*/
|
||||
nsCString TestGetValue(const char* aStorageName) const {
|
||||
nsCString ret;
|
||||
fog_uuid_test_get_value(mId, aStorageName, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
private:
|
||||
const uint32_t mId;
|
||||
};
|
||||
} // namespace impl
|
||||
|
||||
class GleanUuid final : public nsIGleanUuid {
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIGLEANUUID
|
||||
|
||||
explicit GleanUuid(uint32_t id) : mUuid(id){};
|
||||
|
||||
private:
|
||||
virtual ~GleanUuid() = default;
|
||||
|
||||
const impl::UuidMetric mUuid;
|
||||
};
|
||||
|
||||
} // namespace glean
|
||||
} // namespace mozilla
|
||||
|
||||
#endif /* mozilla_glean_GleanUuid.h */
|
|
@ -29,7 +29,7 @@ def generate_metric_ids(objs):
|
|||
return lambda metric: metric_id_mapping[(metric.category, metric.name)]
|
||||
|
||||
|
||||
IMPLEMENTED_CPP_TYPES = ["counter", "timespan"]
|
||||
IMPLEMENTED_CPP_TYPES = ["counter", "timespan", "uuid"]
|
||||
|
||||
|
||||
def is_implemented_metric_type(typ):
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include "nsString.h"
|
||||
|
||||
using mozilla::Preferences;
|
||||
using namespace mozilla::glean;
|
||||
|
||||
#define DATA_PREF "datareporting.healthreport.uploadEnabled"
|
||||
|
||||
|
@ -69,3 +70,18 @@ TEST(FOG, TestCppTimespanWorks)
|
|||
ASSERT_TRUE(
|
||||
mozilla::glean::test_only::can_we_time_it.TestGetValue("test-ping") > 0);
|
||||
}
|
||||
|
||||
TEST(FOG, TestCppUuidWorks)
|
||||
{
|
||||
nsCString kTestUuid("decafdec-afde-cafd-ecaf-decafdecafde");
|
||||
test_only::what_id_it.Set(kTestUuid);
|
||||
ASSERT_TRUE(test_only::what_id_it.TestHasValue("test-ping"));
|
||||
ASSERT_STREQ(kTestUuid.get(),
|
||||
test_only::what_id_it.TestGetValue("test-ping").get());
|
||||
|
||||
test_only::what_id_it.GenerateAndSet();
|
||||
// Since we generate v4 UUIDs, and the first character of the third group
|
||||
// isn't 4, this won't ever collide with kTestUuid.
|
||||
ASSERT_STRNE(kTestUuid.get(),
|
||||
test_only::what_id_it.TestGetValue("test-ping").get());
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@ if CONFIG["MOZ_GLEAN"]:
|
|||
"bindings/MetricTypes.h",
|
||||
"bindings/private/Counter.h",
|
||||
"bindings/private/Timespan.h",
|
||||
"bindings/private/Uuid.h",
|
||||
]
|
||||
|
||||
UNIFIED_SOURCES += [
|
||||
|
@ -31,6 +32,7 @@ if CONFIG["MOZ_GLEAN"]:
|
|||
"bindings/Glean.cpp",
|
||||
"bindings/private/Counter.cpp",
|
||||
"bindings/private/Timespan.cpp",
|
||||
"bindings/private/Uuid.cpp",
|
||||
"ipc/FOGIPC.cpp",
|
||||
]
|
||||
|
||||
|
|
|
@ -47,6 +47,18 @@ test_only:
|
|||
send_in_pings:
|
||||
- test-ping
|
||||
|
||||
what_id_it: # Using a different metrics yaml style for fun.
|
||||
type: uuid
|
||||
description: |
|
||||
Just a UUID.
|
||||
This is a test-only metric.
|
||||
bugs: ["https://bugzilla.mozilla.org/show_bug.cgi?id=1673664"]
|
||||
data_reviews: ["https://bugzilla.mozilla.org/show_bug.cgi?id=1673664#c1"]
|
||||
data_sensitivity: ["technical"]
|
||||
notification_emails: ["glean-team@mozilla.com"]
|
||||
expires: never
|
||||
send_in_pings: ["test-ping"]
|
||||
|
||||
test_only.ipc:
|
||||
a_counter:
|
||||
type: counter
|
||||
|
|
|
@ -109,3 +109,55 @@ interface nsIGleanTimespan : nsISupports
|
|||
[implicit_jscontext]
|
||||
long long testGetValue(in ACString aStorageName);
|
||||
};
|
||||
|
||||
[scriptable, uuid(395700e7-06f6-46be-adcc-ea58977fda6d)]
|
||||
interface nsIGleanUuid : nsISupports
|
||||
{
|
||||
/**
|
||||
* Set to the specified value.
|
||||
*
|
||||
* @param aValue The UUID to set the metric to.
|
||||
*/
|
||||
[implicit_jscontext]
|
||||
void set(in ACString aValue);
|
||||
|
||||
/**
|
||||
* Generate a new random UUID and set the metric to it.
|
||||
*/
|
||||
[implicit_jscontext]
|
||||
void generateAndSet();
|
||||
|
||||
/**
|
||||
* **Test-only API**
|
||||
*
|
||||
* Tests whether a value is stored for the metric.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Parent process only. Panics in child processes.
|
||||
*
|
||||
* @param aStorageName the name of the ping to retrieve the metric for.
|
||||
* @return true if metric value exists, otherwise false
|
||||
*/
|
||||
[implicit_jscontext]
|
||||
bool testHasValue(in ACString aStorageName);
|
||||
|
||||
/**
|
||||
* **Test-only API**
|
||||
*
|
||||
* Gets the currently stored value as an integer.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* @return value of the stored metric.
|
||||
*/
|
||||
[implicit_jscontext]
|
||||
ACString testGetValue(in ACString aStorageName);
|
||||
};
|
||||
|
|
|
@ -42,3 +42,18 @@ add_task(async function test_fog_timespan_works() {
|
|||
Assert.ok(Glean.test_only.can_we_time_it.testHasValue("test-ping"));
|
||||
Assert.ok(Glean.test_only.can_we_time_it.testGetValue("test-ping") > 0);
|
||||
});
|
||||
|
||||
add_task(async function test_fog_uuid_works() {
|
||||
const kTestUuid = "decafdec-afde-cafd-ecaf-decafdecafde";
|
||||
Glean.test_only.what_id_it.set(kTestUuid);
|
||||
Assert.ok(Glean.test_only.what_id_it.testHasValue("test-ping"));
|
||||
Assert.equal(kTestUuid, Glean.test_only.what_id_it.testGetValue("test-ping"));
|
||||
|
||||
Glean.test_only.what_id_it.generateAndSet();
|
||||
// Since we generate v4 UUIDs, and the first character of the third group
|
||||
// isn't 4, this won't ever collide with kTestUuid.
|
||||
Assert.notEqual(
|
||||
kTestUuid,
|
||||
Glean.test_only.what_id_it.testGetValue("test-ping")
|
||||
);
|
||||
});
|
||||
|
|
Загрузка…
Ссылка в новой задаче