summaryrefslogtreecommitdiffstats
path: root/toolkit/components/glean/bindings
diff options
context:
space:
mode:
Diffstat (limited to 'toolkit/components/glean/bindings')
-rw-r--r--toolkit/components/glean/bindings/GleanMetric.h1
-rw-r--r--toolkit/components/glean/bindings/MetricTypes.h1
-rw-r--r--toolkit/components/glean/bindings/jog/src/lib.rs6
-rw-r--r--toolkit/components/glean/bindings/private/CustomDistribution.cpp8
-rw-r--r--toolkit/components/glean/bindings/private/DistributionData.h6
-rw-r--r--toolkit/components/glean/bindings/private/MemoryDistribution.cpp8
-rw-r--r--toolkit/components/glean/bindings/private/Object.cpp80
-rw-r--r--toolkit/components/glean/bindings/private/Object.h94
-rw-r--r--toolkit/components/glean/bindings/private/Timespan.cpp1
-rw-r--r--toolkit/components/glean/bindings/private/TimingDistribution.cpp29
10 files changed, 215 insertions, 19 deletions
diff --git a/toolkit/components/glean/bindings/GleanMetric.h b/toolkit/components/glean/bindings/GleanMetric.h
index 65ac75191d..c6bf6b4066 100644
--- a/toolkit/components/glean/bindings/GleanMetric.h
+++ b/toolkit/components/glean/bindings/GleanMetric.h
@@ -11,6 +11,7 @@
#include "nsIGlobalObject.h"
#include "nsWrapperCache.h"
#include "nsClassHashtable.h"
+#include "nsGlobalWindowInner.h"
#include "nsTHashMap.h"
#include "mozilla/DataMutex.h"
diff --git a/toolkit/components/glean/bindings/MetricTypes.h b/toolkit/components/glean/bindings/MetricTypes.h
index a7ae09fe19..6d855c2bf4 100644
--- a/toolkit/components/glean/bindings/MetricTypes.h
+++ b/toolkit/components/glean/bindings/MetricTypes.h
@@ -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"
diff --git a/toolkit/components/glean/bindings/jog/src/lib.rs b/toolkit/components/glean/bindings/jog/src/lib.rs
index 4f2d439d80..b62e54f6e8 100644
--- a/toolkit/components/glean/bindings/jog/src/lib.rs
+++ b/toolkit/components/glean/bindings/jog/src/lib.rs
@@ -138,6 +138,7 @@ pub extern "C" fn jog_test_register_ping(
include_client_id: bool,
send_if_empty: bool,
precise_timestamps: bool,
+ include_info_sections: bool,
reason_codes: &ThinVec<nsCString>,
) -> u32 {
let ping_name = name.to_string();
@@ -150,6 +151,7 @@ pub extern "C" fn jog_test_register_ping(
include_client_id,
send_if_empty,
precise_timestamps,
+ include_info_sections,
reason_codes,
)
.expect("Creation or registration of ping failed.") // permitted to panic in test-only method.
@@ -160,6 +162,7 @@ fn create_and_register_ping(
include_client_id: bool,
send_if_empty: bool,
precise_timestamps: bool,
+ include_info_sections: bool,
reason_codes: Vec<String>,
) -> Result<u32, Box<dyn std::error::Error>> {
let ns_name = nsCString::from(&ping_name);
@@ -168,6 +171,7 @@ fn create_and_register_ping(
include_client_id,
send_if_empty,
precise_timestamps,
+ include_info_sections,
reason_codes,
);
extern "C" {
@@ -214,6 +218,7 @@ struct PingDefinitionData {
include_client_id: bool,
send_if_empty: bool,
precise_timestamps: bool,
+ include_info_sections: bool,
reason_codes: Option<Vec<String>>,
}
@@ -260,6 +265,7 @@ pub extern "C" fn jog_load_jogfile(jogfile_path: &nsAString) -> bool {
ping.include_client_id,
ping.send_if_empty,
ping.precise_timestamps,
+ ping.include_info_sections,
ping.reason_codes.unwrap_or_else(Vec::new),
);
}
diff --git a/toolkit/components/glean/bindings/private/CustomDistribution.cpp b/toolkit/components/glean/bindings/private/CustomDistribution.cpp
index 2f0226cb58..a5a821a558 100644
--- a/toolkit/components/glean/bindings/private/CustomDistribution.cpp
+++ b/toolkit/components/glean/bindings/private/CustomDistribution.cpp
@@ -59,9 +59,10 @@ CustomDistributionMetric::TestGetValue(const nsACString& aPingName) const {
nsTArray<uint64_t> buckets;
nsTArray<uint64_t> counts;
uint64_t sum;
- fog_custom_distribution_test_get_value(mId, &aPingName, &sum, &buckets,
- &counts);
- return Some(DistributionData(buckets, counts, sum));
+ uint64_t count;
+ fog_custom_distribution_test_get_value(mId, &aPingName, &sum, &count,
+ &buckets, &counts);
+ return Some(DistributionData(buckets, counts, sum, count));
}
} // namespace impl
@@ -92,6 +93,7 @@ void GleanCustomDistribution::TestGetValue(
dom::GleanDistributionData ret;
ret.mSum = optresult.ref().sum;
+ ret.mCount = optresult.ref().count;
auto& data = optresult.ref().values;
for (const auto& entry : data) {
dom::binding_detail::RecordEntry<nsCString, uint64_t> bucket;
diff --git a/toolkit/components/glean/bindings/private/DistributionData.h b/toolkit/components/glean/bindings/private/DistributionData.h
index 6ff995f222..fb9bba720e 100644
--- a/toolkit/components/glean/bindings/private/DistributionData.h
+++ b/toolkit/components/glean/bindings/private/DistributionData.h
@@ -12,6 +12,7 @@ namespace mozilla::glean {
struct DistributionData final {
uint64_t sum;
+ uint64_t count;
nsTHashMap<nsUint64HashKey, uint64_t> values;
/**
@@ -19,8 +20,9 @@ struct DistributionData final {
* as returned by `fog_*_distribution_test_get_value`.
*/
DistributionData(const nsTArray<uint64_t>& aBuckets,
- const nsTArray<uint64_t>& aCounts, uint64_t aSum)
- : sum(aSum) {
+ const nsTArray<uint64_t>& aCounts, uint64_t aSum,
+ uint64_t aCount)
+ : sum(aSum), count(aCount) {
for (size_t i = 0; i < aBuckets.Length(); ++i) {
this->values.InsertOrUpdate(aBuckets[i], aCounts[i]);
}
diff --git a/toolkit/components/glean/bindings/private/MemoryDistribution.cpp b/toolkit/components/glean/bindings/private/MemoryDistribution.cpp
index a580c5df3c..64f3bf241c 100644
--- a/toolkit/components/glean/bindings/private/MemoryDistribution.cpp
+++ b/toolkit/components/glean/bindings/private/MemoryDistribution.cpp
@@ -44,9 +44,10 @@ MemoryDistributionMetric::TestGetValue(const nsACString& aPingName) const {
nsTArray<uint64_t> buckets;
nsTArray<uint64_t> counts;
uint64_t sum;
- fog_memory_distribution_test_get_value(mId, &aPingName, &sum, &buckets,
- &counts);
- return Some(DistributionData(buckets, counts, sum));
+ uint64_t count;
+ fog_memory_distribution_test_get_value(mId, &aPingName, &sum, &count,
+ &buckets, &counts);
+ return Some(DistributionData(buckets, counts, sum, count));
}
} // namespace impl
@@ -76,6 +77,7 @@ void GleanMemoryDistribution::TestGetValue(
dom::GleanDistributionData ret;
ret.mSum = optresult.ref().sum;
+ ret.mCount = optresult.ref().count;
auto& data = optresult.ref().values;
for (const auto& entry : data) {
dom::binding_detail::RecordEntry<nsCString, uint64_t> bucket;
diff --git a/toolkit/components/glean/bindings/private/Object.cpp b/toolkit/components/glean/bindings/private/Object.cpp
new file mode 100644
index 0000000000..817b14dc0f
--- /dev/null
+++ b/toolkit/components/glean/bindings/private/Object.cpp
@@ -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
diff --git a/toolkit/components/glean/bindings/private/Object.h b/toolkit/components/glean/bindings/private/Object.h
new file mode 100644
index 0000000000..4c81f8b096
--- /dev/null
+++ b/toolkit/components/glean/bindings/private/Object.h
@@ -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 */
diff --git a/toolkit/components/glean/bindings/private/Timespan.cpp b/toolkit/components/glean/bindings/private/Timespan.cpp
index 13e57317fa..2ab1f0dbba 100644
--- a/toolkit/components/glean/bindings/private/Timespan.cpp
+++ b/toolkit/components/glean/bindings/private/Timespan.cpp
@@ -36,6 +36,7 @@ class ScalarIDHashKey : public PLDHashEntryHdr {
return static_cast<std::underlying_type<ScalarID>::type>(*aKey);
}
enum { ALLOW_MEMMOVE = true };
+ static_assert(std::is_trivially_copyable_v<ScalarID>);
private:
const ScalarID mValue;
diff --git a/toolkit/components/glean/bindings/private/TimingDistribution.cpp b/toolkit/components/glean/bindings/private/TimingDistribution.cpp
index f7a78165ae..036db5f9db 100644
--- a/toolkit/components/glean/bindings/private/TimingDistribution.cpp
+++ b/toolkit/components/glean/bindings/private/TimingDistribution.cpp
@@ -21,7 +21,10 @@
namespace mozilla::glean {
using MetricId = uint32_t; // Same type as in api/src/private/mod.rs
-using MetricTimerTuple = std::tuple<MetricId, TimerId>;
+struct MetricTimerTuple {
+ MetricId mMetricId;
+ TimerId mTimerId;
+};
class MetricTimerTupleHashKey : public PLDHashEntryHdr {
public:
using KeyType = const MetricTimerTuple&;
@@ -34,16 +37,17 @@ class MetricTimerTupleHashKey : public PLDHashEntryHdr {
KeyType GetKey() const { return mValue; }
bool KeyEquals(KeyTypePointer aKey) const {
- return std::get<0>(*aKey) == std::get<0>(mValue) &&
- std::get<1>(*aKey) == std::get<1>(mValue);
+ return aKey->mMetricId == mValue.mMetricId &&
+ aKey->mTimerId == mValue.mTimerId;
}
static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; }
static PLDHashNumber HashKey(KeyTypePointer aKey) {
// Chosen because this is how nsIntegralHashKey does it.
- return HashGeneric(std::get<0>(*aKey), std::get<1>(*aKey));
+ return HashGeneric(aKey->mMetricId, aKey->mTimerId);
}
enum { ALLOW_MEMMOVE = true };
+ static_assert(std::is_trivially_copyable_v<MetricTimerTuple>);
private:
const MetricTimerTuple mValue;
@@ -103,7 +107,7 @@ extern "C" NS_EXPORT void GIFFT_TimingDistributionStart(
auto mirrorId = mozilla::glean::HistogramIdForMetric(aMetricId);
if (mirrorId) {
mozilla::glean::GetTimerIdToStartsLock().apply([&](auto& lock) {
- auto tuple = std::make_tuple(aMetricId, aTimerId);
+ auto tuple = mozilla::glean::MetricTimerTuple{aMetricId, aTimerId};
// It should be all but impossible for anyone to have already inserted
// this timer for this metric given the monotonicity of timer ids.
(void)NS_WARN_IF(lock.ref()->Remove(tuple));
@@ -118,7 +122,8 @@ extern "C" NS_EXPORT void GIFFT_TimingDistributionStopAndAccumulate(
auto mirrorId = mozilla::glean::HistogramIdForMetric(aMetricId);
if (mirrorId) {
mozilla::glean::GetTimerIdToStartsLock().apply([&](auto& lock) {
- auto optStart = lock.ref()->Extract(std::make_tuple(aMetricId, aTimerId));
+ auto tuple = mozilla::glean::MetricTimerTuple{aMetricId, aTimerId};
+ auto optStart = lock.ref()->Extract(tuple);
// The timer might not be in the map to be removed if it's already been
// cancelled or stop_and_accumulate'd.
if (!NS_WARN_IF(!optStart)) {
@@ -145,8 +150,8 @@ extern "C" NS_EXPORT void GIFFT_TimingDistributionCancel(
mozilla::glean::GetTimerIdToStartsLock().apply([&](auto& lock) {
// The timer might not be in the map to be removed if it's already been
// cancelled or stop_and_accumulate'd.
- (void)NS_WARN_IF(
- !lock.ref()->Remove(std::make_tuple(aMetricId, aTimerId)));
+ auto tuple = mozilla::glean::MetricTimerTuple{aMetricId, aTimerId};
+ (void)NS_WARN_IF(!lock.ref()->Remove(tuple));
});
}
}
@@ -187,9 +192,10 @@ TimingDistributionMetric::TestGetValue(const nsACString& aPingName) const {
nsTArray<uint64_t> buckets;
nsTArray<uint64_t> counts;
uint64_t sum;
- fog_timing_distribution_test_get_value(mId, &aPingName, &sum, &buckets,
- &counts);
- return Some(DistributionData(buckets, counts, sum));
+ uint64_t count;
+ fog_timing_distribution_test_get_value(mId, &aPingName, &sum, &count,
+ &buckets, &counts);
+ return Some(DistributionData(buckets, counts, sum, count));
}
} // namespace impl
@@ -225,6 +231,7 @@ void GleanTimingDistribution::TestGetValue(
dom::GleanDistributionData ret;
ret.mSum = optresult.ref().sum;
+ ret.mCount = optresult.ref().count;
auto& data = optresult.ref().values;
for (const auto& entry : data) {
dom::binding_detail::RecordEntry<nsCString, uint64_t> bucket;