commit 8c5a5504e9841668e60b1292e481e549f0492e65
parent 93e210ba11011cbc6f156d82c2d81b9ea8f1b453
Author: Bas Schouten <bschouten@mozilla.com>
Date: Wed, 8 Oct 2025 15:12:46 +0000
Bug 1988716 - Part 2: Add ProcessGet() function to labeled metrics. r=chutten,toolkit-telemetry-reviewers
This patch allows labeled metrics to easily and in a standardized manner label themselves according to the process they're recorded in. It does this by adding a base a ProcessGet() function that automatically creates a label for the right process.
In the process I've also cleaned up the code to use a single template rather than a set of specializations to increase code re-use, and using compile time evaluations to ensure no additional code is generated.
Differential Revision: https://phabricator.services.mozilla.com/D264976
Diffstat:
3 files changed, 157 insertions(+), 409 deletions(-)
diff --git a/toolkit/components/glean/bindings/private/Labeled.cpp b/toolkit/components/glean/bindings/private/Labeled.cpp
@@ -12,6 +12,9 @@
#include "mozilla/glean/bindings/MetricTypes.h"
#include "mozilla/glean/bindings/ScalarGIFFTMap.h"
#include "nsString.h"
+#include "nsXULAppAPI.h"
+#include "mozilla/dom/ContentChild.h"
+#include "mozilla/dom/RemoteType.h"
namespace mozilla::glean {
@@ -52,4 +55,29 @@ void GleanLabeled::GetSupportedNames(nsTArray<nsString>& aNames) {
// We really don't know, so don't do anything.
}
+namespace impl {
+
+// Helper function to get the current process type string for telemetry labeling
+nsCString GetProcessTypeForTelemetry() {
+ nsCString processType(XRE_GetProcessTypeString());
+
+ // For content processes, check the specific remote type
+ if (processType.EqualsLiteral("tab")) {
+ auto* cc = mozilla::dom::ContentChild::GetSingleton();
+ if (cc) {
+ const nsACString& remoteType = cc->GetRemoteType();
+ if (remoteType == EXTENSION_REMOTE_TYPE) {
+ processType.AssignLiteral("extension");
+ } else if (remoteType == INFERENCE_REMOTE_TYPE) {
+ processType.AssignLiteral("inference");
+ }
+ // Otherwise keep "tab" for regular content processes
+ }
+ }
+
+ return processType;
+}
+
+} // namespace impl
+
} // namespace mozilla::glean
diff --git a/toolkit/components/glean/bindings/private/Labeled.h b/toolkit/components/glean/bindings/private/Labeled.h
@@ -28,39 +28,8 @@ namespace mozilla::glean {
namespace impl {
-template <typename T, typename E>
-class Labeled {
- public:
- constexpr explicit Labeled(uint32_t id) : mId(id) {}
-
- /**
- * Gets a specific metric for a given label.
- *
- * If a set of acceptable labels were specified in the `metrics.yaml` file,
- * and the given label is not in the set, it will be recorded under the
- * special `OTHER_LABEL` label.
- *
- * If a set of acceptable labels was not specified in the `metrics.yaml` file,
- * only the first 16 unique labels will be used.
- * After that, any additional labels will be recorded under the special
- * `OTHER_LABEL` label.
- *
- * @param aLabel - a snake_case string under 30 characters in length,
- * otherwise the metric will be recorded under the special
- * `OTHER_LABEL` label and an error will be recorded.
- */
- T Get(const nsACString& aLabel) const;
-
- /**
- * Gets a specific metric for a given label, using the label's enum variant.
- *
- * @param aLabel - a variant of this label's label enum.
- */
- T EnumGet(E aLabel) const;
-
- private:
- const uint32_t mId;
-};
+// Helper function to get the current process type string for telemetry labeling
+nsCString GetProcessTypeForTelemetry();
static inline void UpdateLabeledMirror(Telemetry::ScalarID aMirrorId,
uint32_t aSubmetricId,
@@ -82,333 +51,114 @@ static inline void UpdateLabeledDistributionMirror(
});
}
-template <typename E>
-class Labeled<BooleanMetric, E> {
- public:
- constexpr explicit Labeled(uint32_t id) : mId(id) {}
-
- BooleanMetric Get(const nsACString& aLabel) const {
- auto submetricId = fog_labeled_boolean_get(mId, &aLabel);
- // If this labeled metric is mirrored, we need to map the submetric id back
- // to the label string and mirrored scalar so we can mirror its operations.
- auto mirrorId = ScalarIdForMetric(mId);
- if (mirrorId) {
- UpdateLabeledMirror(mirrorId.extract(), submetricId, aLabel);
- }
- return BooleanMetric(submetricId);
- }
-
- BooleanMetric EnumGet(E aLabel) const {
- auto submetricId =
- fog_labeled_boolean_enum_get(mId, static_cast<uint16_t>(aLabel));
- auto mirrorId = ScalarIdForMetric(mId);
- if (mirrorId) {
- // Telemetry's keyed scalars operate on (16-bit) strings,
- // so we're going to need the string for this enum.
- nsCString label;
- fog_labeled_enum_to_str(mId, static_cast<uint16_t>(aLabel), &label);
- UpdateLabeledMirror(mirrorId.extract(), submetricId, label);
- }
- return BooleanMetric(submetricId);
- }
-
- private:
- const uint32_t mId;
-};
-
-template <typename E>
-class Labeled<CounterMetric<CounterType::eBaseOrLabeled>, E> {
- public:
- constexpr explicit Labeled(uint32_t id) : mId(id) {}
-
- CounterMetric<CounterType::eBaseOrLabeled> Get(
- const nsACString& aLabel) const {
- auto submetricId = fog_labeled_counter_get(mId, &aLabel);
- // If this labeled metric is mirrored, we need to map the submetric id back
- // to the label string and mirrored scalar so we can mirror its operations.
- auto mirrorId = ScalarIdForMetric(mId);
- if (mirrorId) {
- UpdateLabeledMirror(mirrorId.extract(), submetricId, aLabel);
- } else if (auto mirrorHgramId = HistogramIdForMetric(mId)) {
- UpdateLabeledDistributionMirror(mirrorHgramId.extract(), submetricId,
- aLabel);
- }
- return CounterMetric<CounterType::eBaseOrLabeled>(submetricId);
- }
-
- CounterMetric<CounterType::eBaseOrLabeled> EnumGet(E aLabel) const {
- auto submetricId =
- fog_labeled_counter_enum_get(mId, static_cast<uint16_t>(aLabel));
- auto mirrorId = ScalarIdForMetric(mId);
- if (mirrorId) {
- // Telemetry's keyed scalars operate on (16-bit) strings,
- // so we're going to need the string for this enum.
- nsCString label;
- fog_labeled_enum_to_str(mId, static_cast<uint16_t>(aLabel), &label);
- UpdateLabeledMirror(mirrorId.extract(), submetricId, label);
- } else if (auto mirrorHgramId = HistogramIdForMetric(mId)) {
- nsCString label;
- fog_labeled_enum_to_str(mId, static_cast<uint16_t>(aLabel), &label);
- UpdateLabeledDistributionMirror(mirrorHgramId.extract(), submetricId,
- label);
- }
- return CounterMetric<CounterType::eBaseOrLabeled>(submetricId);
- }
+template <typename T>
+inline uint32_t fog_labeled_get(uint32_t aId, const nsACString* aLabel);
+template <typename T>
+inline uint32_t fog_labeled_enum_get(uint32_t aId, uint16_t aLabel);
+
+#define FOG_LABEL_TYPE_MAP(type, name) \
+ template <> \
+ inline uint32_t fog_labeled_get<type>(uint32_t aId, \
+ const nsACString* aLabel) { \
+ return fog_labeled_##name##_get(aId, aLabel); \
+ } \
+ template <> \
+ inline uint32_t fog_labeled_enum_get<type>(uint32_t aId, uint16_t aLabel) { \
+ return fog_labeled_##name##_enum_get(aId, aLabel); \
+ }
+
+FOG_LABEL_TYPE_MAP(BooleanMetric, boolean)
+FOG_LABEL_TYPE_MAP(QuantityMetric, quantity)
+FOG_LABEL_TYPE_MAP(StringMetric, string)
+FOG_LABEL_TYPE_MAP(CounterMetric<CounterType::eBaseOrLabeled>, counter)
+FOG_LABEL_TYPE_MAP(CustomDistributionMetric, custom_distribution)
+FOG_LABEL_TYPE_MAP(MemoryDistributionMetric, memory_distribution)
+FOG_LABEL_TYPE_MAP(TimingDistributionMetric, timing_distribution)
- private:
- const uint32_t mId;
-};
-
-template <typename E>
-class Labeled<CustomDistributionMetric, E> {
- public:
- constexpr explicit Labeled(uint32_t id) : mId(id) {}
-
- CustomDistributionMetric Get(const nsACString& aLabel) const {
- auto submetricId = fog_labeled_custom_distribution_get(mId, &aLabel);
- // If this labeled metric is mirrored, we need to map the submetric id back
- // to the label string and mirrored hgram so we can mirror its operations.
- auto mirrorId = HistogramIdForMetric(mId);
- if (mirrorId) {
- UpdateLabeledDistributionMirror(mirrorId.extract(), submetricId, aLabel);
- }
- return CustomDistributionMetric(submetricId);
- }
-
- CustomDistributionMetric EnumGet(E aLabel) const {
- auto submetricId = fog_labeled_custom_distribution_enum_get(
- mId, static_cast<uint16_t>(aLabel));
- auto mirrorId = HistogramIdForMetric(mId);
- if (mirrorId) {
- // Telemetry's keyed histograms operate on strings,
- // so we're going to need to store the string for this enum.
- nsCString label;
- fog_labeled_enum_to_str(mId, static_cast<uint16_t>(aLabel), &label);
- UpdateLabeledDistributionMirror(mirrorId.extract(), submetricId, label);
- }
- return CustomDistributionMetric(submetricId);
- }
-
- private:
- const uint32_t mId;
-};
-
-template <typename E>
-class Labeled<MemoryDistributionMetric, E> {
- public:
- constexpr explicit Labeled(uint32_t id) : mId(id) {}
-
- MemoryDistributionMetric Get(const nsACString& aLabel) const {
- auto submetricId = fog_labeled_memory_distribution_get(mId, &aLabel);
- // If this labeled metric is mirrored, we need to map the submetric id back
- // to the label string and mirrored hgram so we can mirror its operations.
- auto mirrorId = HistogramIdForMetric(mId);
- if (mirrorId) {
- UpdateLabeledDistributionMirror(mirrorId.extract(), submetricId, aLabel);
- }
- return MemoryDistributionMetric(submetricId);
- }
-
- MemoryDistributionMetric EnumGet(E aLabel) const {
- auto submetricId = fog_labeled_memory_distribution_enum_get(
- mId, static_cast<uint16_t>(aLabel));
- auto mirrorId = HistogramIdForMetric(mId);
- if (mirrorId) {
- // Telemetry's keyed histograms operate on strings,
- // so we're going to need to store the string for this enum.
- nsCString label;
- fog_labeled_enum_to_str(mId, static_cast<uint16_t>(aLabel), &label);
- UpdateLabeledDistributionMirror(mirrorId.extract(), submetricId, label);
- }
- return MemoryDistributionMetric(submetricId);
- }
-
- private:
- const uint32_t mId;
-};
-
-template <typename E>
-class Labeled<QuantityMetric, E> {
- public:
- constexpr explicit Labeled(uint32_t id) : mId(id) {}
-
- QuantityMetric Get(const nsACString& aLabel) const {
- auto submetricId = fog_labeled_quantity_get(mId, &aLabel);
- // If this labeled metric is mirrored, we need to map the submetric id back
- // to the label string and mirrored scalar so we can mirror its operations.
- auto mirrorId = ScalarIdForMetric(mId);
- if (mirrorId) {
- UpdateLabeledMirror(mirrorId.extract(), submetricId, aLabel);
- }
- return QuantityMetric(submetricId);
- }
-
- QuantityMetric EnumGet(E aLabel) const {
- auto submetricId =
- fog_labeled_quantity_enum_get(mId, static_cast<uint16_t>(aLabel));
- auto mirrorId = ScalarIdForMetric(mId);
- if (mirrorId) {
- // Telemetry's keyed scalars operate on (16-bit) strings,
- // so we're going to need the string for this enum.
- nsCString label;
- fog_labeled_enum_to_str(mId, static_cast<uint16_t>(aLabel), &label);
- UpdateLabeledMirror(mirrorId.extract(), submetricId, label);
- }
- return QuantityMetric(submetricId);
- }
-
- private:
- const uint32_t mId;
-};
-
-template <typename E>
-class Labeled<StringMetric, E> {
- public:
- constexpr explicit Labeled(uint32_t id) : mId(id) {}
-
- StringMetric Get(const nsACString& aLabel) const {
- auto submetricId = fog_labeled_string_get(mId, &aLabel);
- // Why no GIFFT map here?
- // Labeled Strings can't be mirrored. Telemetry has no compatible probe.
- return StringMetric(submetricId);
- }
-
- StringMetric EnumGet(E aLabel) const {
- auto submetricId =
- fog_labeled_string_enum_get(mId, static_cast<uint16_t>(aLabel));
- // Why no GIFFT map here?
- // Labeled Strings can't be mirrored. Telemetry has no compatible probe.
- return StringMetric(submetricId);
- }
-
- private:
- const uint32_t mId;
-};
-
-template <typename E>
-class Labeled<TimingDistributionMetric, E> {
- public:
- constexpr explicit Labeled(uint32_t id) : mId(id) {}
-
- TimingDistributionMetric Get(const nsACString& aLabel) const {
- auto submetricId = fog_labeled_timing_distribution_get(mId, &aLabel);
- // If this labeled metric is mirrored, we need to map the submetric id back
- // to the label string and mirrored hgram so we can mirror its operations.
- auto mirrorId = HistogramIdForMetric(mId);
- if (mirrorId) {
- UpdateLabeledDistributionMirror(mirrorId.extract(), submetricId, aLabel);
- }
- return TimingDistributionMetric(submetricId);
- }
-
- TimingDistributionMetric EnumGet(E aLabel) const {
- auto submetricId = fog_labeled_timing_distribution_enum_get(
- mId, static_cast<uint16_t>(aLabel));
- auto mirrorId = HistogramIdForMetric(mId);
- if (mirrorId) {
- // Telemetry's keyed histograms operate on strings,
- // so we're going to need to store the string for this enum.
- nsCString label;
- fog_labeled_enum_to_str(mId, static_cast<uint16_t>(aLabel), &label);
- UpdateLabeledDistributionMirror(mirrorId.extract(), submetricId, label);
- }
- return TimingDistributionMetric(submetricId);
- }
-
- private:
- const uint32_t mId;
-};
-
-template <>
-class Labeled<BooleanMetric, DynamicLabel> {
- public:
- constexpr explicit Labeled(uint32_t id) : mId(id) {}
-
- BooleanMetric Get(const nsACString& aLabel) const {
- auto submetricId = fog_labeled_boolean_get(mId, &aLabel);
- // If this labeled metric is mirrored, we need to map the submetric id back
- // to the label string and mirrored scalar so we can mirror its operations.
- auto mirrorId = ScalarIdForMetric(mId);
- if (mirrorId) {
- UpdateLabeledMirror(mirrorId.extract(), submetricId, aLabel);
- }
- return BooleanMetric(submetricId);
- }
-
- BooleanMetric EnumGet(DynamicLabel aLabel) const = delete;
-
- private:
- const uint32_t mId;
-};
-
-template <>
-class Labeled<CounterMetric<CounterType::eBaseOrLabeled>, DynamicLabel> {
+template <typename T, typename E>
+class Labeled {
public:
constexpr explicit Labeled(uint32_t id) : mId(id) {}
- CounterMetric<CounterType::eBaseOrLabeled> Get(
- const nsACString& aLabel) const {
- auto submetricId = fog_labeled_counter_get(mId, &aLabel);
- // If this labeled metric is mirrored, we need to map the submetric id back
- // to the label string and mirrored scalar so we can mirror its operations.
- auto mirrorId = ScalarIdForMetric(mId);
- if (mirrorId) {
- UpdateLabeledMirror(mirrorId.extract(), submetricId, aLabel);
- } else if (auto mirrorHgramId = HistogramIdForMetric(mId)) {
- UpdateLabeledDistributionMirror(mirrorHgramId.extract(), submetricId,
- aLabel);
- }
- return CounterMetric<CounterType::eBaseOrLabeled>(submetricId);
- }
-
- CounterMetric<CounterType::eBaseOrLabeled> EnumGet(
- DynamicLabel aLabel) const = delete;
-
- private:
- const uint32_t mId;
-};
-
-template <>
-class Labeled<CustomDistributionMetric, DynamicLabel> {
- public:
- constexpr explicit Labeled(uint32_t id) : mId(id) {}
+ /**
+ * Gets a specific metric for a given label.
+ *
+ * If a set of acceptable labels were specified in the `metrics.yaml` file,
+ * and the given label is not in the set, it will be recorded under the
+ * special `OTHER_LABEL` label.
+ *
+ * If a set of acceptable labels was not specified in the `metrics.yaml` file,
+ * only the first 16 unique labels will be used.
+ * After that, any additional labels will be recorded under the special
+ * `OTHER_LABEL` label.
+ *
+ * @param aLabel - a snake_case string under 30 characters in length,
+ * otherwise the metric will be recorded under the special
+ * `OTHER_LABEL` label and an error will be recorded.
+ */
+ T Get(const nsACString& aLabel) const {
+ uint32_t submetricId = fog_labeled_get<T>(mId, &aLabel);
- CustomDistributionMetric Get(const nsACString& aLabel) const {
- auto submetricId = fog_labeled_custom_distribution_get(mId, &aLabel);
- // If this labeled metric is mirrored, we need to map the submetric id back
- // to the label string and mirrored hgram so we can mirror its operations.
- auto mirrorId = HistogramIdForMetric(mId);
- if (mirrorId) {
- UpdateLabeledDistributionMirror(mirrorId.extract(), submetricId, aLabel);
+ Maybe<ScalarID> mirrorId;
+ if constexpr (MayBeScalarMirror()) {
+ mirrorId = ScalarIdForMetric(mId);
+ if (mirrorId) {
+ UpdateLabeledMirror(mirrorId.extract(), submetricId, aLabel);
+ }
}
- return CustomDistributionMetric(submetricId);
- }
-
- CustomDistributionMetric EnumGet(DynamicLabel aLabel) const = delete;
-
- private:
- const uint32_t mId;
-};
-
-template <>
-class Labeled<TimingDistributionMetric, DynamicLabel> {
- public:
- constexpr explicit Labeled(uint32_t id) : mId(id) {}
-
- TimingDistributionMetric Get(const nsACString& aLabel) const {
- auto submetricId = fog_labeled_memory_distribution_get(mId, &aLabel);
- // If this labeled metric is mirrored, we need to map the submetric id back
- // to the label string and mirrored hgram so we can mirror its operations.
- auto mirrorId = HistogramIdForMetric(mId);
- if (mirrorId) {
- UpdateLabeledDistributionMirror(mirrorId.extract(), submetricId, aLabel);
+ if constexpr (MayBeDistributionMirror()) {
+ if (!mirrorId) {
+ if (Maybe<HistogramID> mirrorHgramId = HistogramIdForMetric(mId)) {
+ UpdateLabeledDistributionMirror(mirrorHgramId.extract(), submetricId,
+ aLabel);
+ }
+ }
}
- return TimingDistributionMetric(submetricId);
+ return T(submetricId);
}
- TimingDistributionMetric EnumGet(DynamicLabel aLabel) const = delete;
-
- TimingDistributionMetric MaybeTruncateAndGet(const nsACString& aLabel) const {
+ /**
+ * Gets a specific metric for a given label, using the label's enum variant.
+ *
+ * @param aLabel - a variant of this label's label enum.
+ */
+ template <typename U = T>
+ std::enable_if_t<!std::is_same_v<U, DynamicLabel>, T> EnumGet(
+ E aLabel) const {
+ uint32_t submetricId =
+ fog_labeled_enum_get<T>(mId, static_cast<uint16_t>(aLabel));
+
+ Maybe<ScalarID> mirrorId;
+ if constexpr (MayBeScalarMirror()) {
+ mirrorId = ScalarIdForMetric(mId);
+ if (mirrorId) {
+ // Telemetry's keyed scalars operate on (16-bit) strings,
+ // so we're going to need the string for this enum.
+ nsCString label;
+ fog_labeled_enum_to_str(mId, static_cast<uint16_t>(aLabel), &label);
+ UpdateLabeledMirror(mirrorId.extract(), submetricId, label);
+ }
+ }
+ if constexpr (MayBeDistributionMirror()) {
+ if (!mirrorId) {
+ if (Maybe<HistogramID> mirrorHgramId = HistogramIdForMetric(mId)) {
+ nsCString label;
+ fog_labeled_enum_to_str(mId, static_cast<uint16_t>(aLabel), &label);
+ UpdateLabeledDistributionMirror(mirrorHgramId.extract(), submetricId,
+ label);
+ }
+ }
+ }
+ return T(submetricId);
+ }
+
+ // This is a workaround only needed in a rare case, ensure it's only compiled
+ // there.
+ template <typename U = T, typename V = E>
+ std::enable_if_t<std::is_same_v<U, TimingDistributionMetric> &&
+ std::is_same_v<V, DynamicLabel>,
+ T>
+ MaybeTruncateAndGet(const nsACString& aLabel) const {
// bug 1959765 is for incorporating this behaviour into the SDK.
if (aLabel.Length() < 112) {
return Get(aLabel);
@@ -419,70 +169,31 @@ class Labeled<TimingDistributionMetric, DynamicLabel> {
return Get(truncated);
}
- private:
- const uint32_t mId;
-};
-
-template <>
-class Labeled<QuantityMetric, DynamicLabel> {
- public:
- constexpr explicit Labeled(uint32_t id) : mId(id) {}
-
- QuantityMetric Get(const nsACString& aLabel) const {
- auto submetricId = fog_labeled_quantity_get(mId, &aLabel);
- // If this labeled metric is mirrored, we need to map the submetric id back
- // to the label string and mirrored scalar so we can mirror its operations.
- auto mirrorId = ScalarIdForMetric(mId);
- if (mirrorId) {
- UpdateLabeledMirror(mirrorId.extract(), submetricId, aLabel);
- }
- return QuantityMetric(submetricId);
- }
+ /**
+ * Gets a specific metric for the current process type.
+ *
+ * Automatically determines the process type and returns the appropriate
+ * labeled metric instance. For content processes, distinguishes between
+ * regular "tab" processes, "inference" processes, and "extension" processes.
+ */
+ T ProcessGet() const { return Get(GetProcessTypeForTelemetry()); }
- QuantityMetric EnumGet(DynamicLabel aLabel) const = delete;
+ protected:
+ uint32_t mId;
private:
- const uint32_t mId;
-};
-
-template <>
-class Labeled<StringMetric, DynamicLabel> {
- public:
- constexpr explicit Labeled(uint32_t id) : mId(id) {}
-
- StringMetric Get(const nsACString& aLabel) const {
- auto submetricId = fog_labeled_string_get(mId, &aLabel);
- // Why no GIFFT map here?
- // Labeled Strings can't be mirrored. Telemetry has no compatible probe.
- return StringMetric(submetricId);
+ static constexpr bool MayBeScalarMirror() {
+ return std::is_same_v<T, BooleanMetric> ||
+ std::is_same_v<T, CounterMetric<CounterType::eBaseOrLabeled>> ||
+ std::is_same_v<T, QuantityMetric>;
}
- StringMetric EnumGet(DynamicLabel aLabel) const = delete;
-
- private:
- const uint32_t mId;
-};
-
-template <>
-class Labeled<MemoryDistributionMetric, DynamicLabel> {
- public:
- constexpr explicit Labeled(uint32_t id) : mId(id) {}
-
- MemoryDistributionMetric Get(const nsACString& aLabel) const {
- auto submetricId = fog_labeled_timing_distribution_get(mId, &aLabel);
- // If this labeled metric is mirrored, we need to map the submetric id back
- // to the label string and mirrored hgram so we can mirror its operations.
- auto mirrorId = HistogramIdForMetric(mId);
- if (mirrorId) {
- UpdateLabeledDistributionMirror(mirrorId.extract(), submetricId, aLabel);
- }
- return MemoryDistributionMetric(submetricId);
+ static constexpr bool MayBeDistributionMirror() {
+ return std::is_same_v<T, CounterMetric<CounterType::eBaseOrLabeled>> ||
+ std::is_same_v<T, CustomDistributionMetric> ||
+ std::is_same_v<T, MemoryDistributionMetric> ||
+ std::is_same_v<T, TimingDistributionMetric>;
}
-
- MemoryDistributionMetric EnumGet(DynamicLabel aLabel) const = delete;
-
- private:
- const uint32_t mId;
};
} // namespace impl
diff --git a/toolkit/components/glean/tests/gtest/TestFog.cpp b/toolkit/components/glean/tests/gtest/TestFog.cpp
@@ -437,6 +437,15 @@ TEST_F(FOGFixture, TestLabeledCounterWithLabelsWorks) {
.ref());
}
+TEST_F(FOGFixture, TestLabeledCounterProcessGetWorks) {
+ test_only::mabels_kitchen_counters.ProcessGet().Add(5);
+
+ ASSERT_EQ(5, test_only::mabels_kitchen_counters.Get("default"_ns)
+ .TestGetValue()
+ .unwrap()
+ .ref());
+}
+
TEST_F(FOGFixture, TestLabeledStringWorks) {
ASSERT_EQ(mozilla::Nothing(),
test_only::mabels_balloon_strings.Get("twine"_ns)