// -*- mode: C++ -*- // AUTOGENERATED BY glean_parser. DO NOT EDIT. {# The rendered source is autogenerated, but this Jinja2 template is not. Please file bugs! #} /* 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/GleanJSMetricsLookup.h" #include "mozilla/PerfectHash.h" #include "mozilla/Maybe.h" #include "mozilla/glean/bindings/MetricTypes.h" #include "mozilla/glean/fog_ffi_generated.h" #include "nsString.h" #define GLEAN_INDEX_BITS ({{index_bits}}) #define GLEAN_TYPE_BITS ({{type_bits}}) #define GLEAN_ID_BITS ({{id_bits}}) #define GLEAN_TYPE_ID(id) ((id) >> GLEAN_ID_BITS) #define GLEAN_METRIC_ID(id) ((id) & ((1ULL << GLEAN_ID_BITS) - 1)) #define GLEAN_OFFSET(entry) (entry & ((1ULL << GLEAN_INDEX_BITS) - 1)) namespace mozilla::glean { // The category lookup table's entry type using category_entry_t = uint32_t; // The metric lookup table's entry type // This is a bitpacked type with {{index_bits}} bits available to index into // the string table, {{type_bits}} bits available to signify the metric type, // and the remaining {{id_bits}} bits devoted to {{id_signal_bits}} "signal" // bits to signify important characteristics (metric's a labeled metric's // submetric, metric's been registered at runtime) and {{id_bits - id_signal_bits}} bits // for built-in metric ids. // Gives room for {{2 ** (id_bits - id_signal_bits)}} of each combination of // characteristics (which hopefully will prove to be enough). 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({{ categories|length }} < UINT32_MAX, "Too many metric categories generated."); static_assert({{ metric_id_mapping|length }} < {{2 ** (id_bits - id_signal_bits)}}, "Too many metrics generated. Need room for {{id_signal_bits}} signal bits."); static_assert({{ metric_type_ids|length }} < {{2 ** type_bits}}, "Too many different metric types."); already_AddRefed NewMetricFromId(uint32_t id, nsISupports* aParent) { uint32_t typeId = GLEAN_TYPE_ID(id); uint32_t metricId = GLEAN_METRIC_ID(id); switch (typeId) { {% for (type_name, subtype_name), (type_id, original_type) in metric_type_ids.items() %} case {{ type_id }}: /* {{ original_type }} */ { return MakeAndAddRef<{{type_name}}>(metricId{% if subtype_name|length > 0 %}, {{ type_id }}{% endif %}, aParent); } {% endfor %} default: MOZ_ASSERT_UNREACHABLE("Invalid type ID reached when trying to instantiate a new metric"); return nullptr; } } /** * Create a submetric instance for a labeled metric of the provided type and id for the given label. * Assigns or retrieves an id for the submetric from the SDK. * * @param aParentTypeId - The type of the parent labeled metric identified as a number generated during codegen. * Only used to identify which X of LabeledX you are so that X can be created here. * @param aParentMetricId - The metric id for the parent labeled metric. * @param aLabel - The label for the submetric. Might not adhere to the SDK label format. * @param aSubmetricId - an outparam which is assigned the submetric's SDK-generated submetric id. * Used only by GIFFT. */ already_AddRefed NewSubMetricFromIds(uint32_t aParentTypeId, uint32_t aParentMetricId, const nsACString& aLabel, uint32_t* aSubmetricId, nsISupports* aParent) { switch (aParentTypeId) { {% for (type_name, subtype_name), (type_id, original_type) in metric_type_ids.items() %} {# TODO: Remove the subtype inclusion clause when we suport the rest of labeled_* #} {% if subtype_name|length > 0 and original_type in ['labeled_boolean', 'labeled_counter', 'labeled_string'] %} case {{ type_id }}: { /* {{ original_type }} */ auto id = impl::fog_{{original_type}}_get(aParentMetricId, &aLabel); *aSubmetricId = id; return MakeAndAddRef<{{subtype_name}}>(id, aParent); } {% endif %} {% endfor %} default: { MOZ_ASSERT_UNREACHABLE("Invalid type ID for submetric."); return nullptr; } } } static Maybe category_result_check(const nsACString& aKey, category_entry_t entry); static Maybe metric_result_check(const nsACString& aKey, metric_entry_t entry); {{ category_string_table }} static_assert(sizeof(gCategoryStringTable) < UINT32_MAX, "Category string table is too large."); {{ category_by_name_lookup }} {{ metric_string_table }} static_assert(sizeof(gMetricStringTable) < {{2 ** index_bits}}, "Metric string table is too large."); {{ metric_by_name_lookup }} /** * Get a category's name from the string table. */ const char* GetCategoryName(category_entry_t entry) { MOZ_ASSERT(entry < sizeof(gCategoryStringTable), "Entry identifier offset larger than string table"); return &gCategoryStringTable[entry]; } /** * Get a metric's identifier from the string table. */ const char* GetMetricIdentifier(metric_entry_t entry) { uint32_t offset = GLEAN_OFFSET(entry); MOZ_ASSERT(offset < sizeof(gMetricStringTable), "Entry identifier offset larger than string table"); return &gMetricStringTable[offset]; } /** * Check that the found entry is pointing to the right key * and return it. * Or return `Nothing()` if the entry was not found. */ static Maybe category_result_check(const nsACString& aKey, category_entry_t entry) { if (MOZ_UNLIKELY(entry > sizeof(gCategoryStringTable))) { return Nothing(); } if (aKey.EqualsASCII(gCategoryStringTable + entry)) { return Some(entry); } return Nothing(); } /** * Check if the found entry index is pointing to the right key * and return the corresponding metric ID. * Or return `Nothing()` if the entry was not found. */ static Maybe metric_result_check(const nsACString& aKey, uint64_t entry) { uint32_t metricId = entry >> GLEAN_INDEX_BITS; uint32_t offset = GLEAN_OFFSET(entry); if (offset > sizeof(gMetricStringTable)) { return Nothing(); } if (aKey.EqualsASCII(gMetricStringTable + offset)) { return Some(metricId); } return Nothing(); } #undef GLEAN_INDEX_BITS #undef GLEAN_ID_BITS #undef GLEAN_TYPE_ID #undef GLEAN_METRIC_ID #undef GLEAN_OFFSET } // namespace mozilla::glean