1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
|
# 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/.
"""
Utility functions for the glean_parser-based code generator
"""
import copy
from hashlib import sha1
from glean_parser import util
def generate_ping_ids(objs):
"""
Return a lookup function for ping IDs per ping name.
:param objs: A tree of objects as returned from `parser.parse_objects`.
"""
if "pings" not in objs:
def no_ping_ids_for_you():
assert False
return no_ping_ids_for_you
# Ping ID 0 is reserved (but unused) right now.
ping_id = 1
ping_id_mapping = {}
for ping_name in objs["pings"].keys():
ping_id_mapping[ping_name] = ping_id
ping_id += 1
return lambda ping_name: ping_id_mapping[ping_name]
def generate_metric_ids(objs, options):
"""
Return a lookup function for metric IDs per metric object.
:param objs: A tree of metrics as returned from `parser.parse_objects`.
"""
# Mapping from a tuple of (category name, metric name) to the metric's numeric ID
metric_id_mapping = {}
if options.get("is_local_build"):
# Metric ID 0 is reserved (but unused) right now.
metric_ids = {0}
for category_name, metrics in objs.items():
if category_name == "tags":
continue
for metric in metrics.values():
metric_id = (
int(sha1(str.encode(metric.identifier())).hexdigest(), 16) % 2**25
)
# Avoid collisions by incrementing the number until we find an unused id.
while metric_id in metric_ids:
metric_id = (metric_id + 1) % 2**25
assert metric_id < 2**25
metric_ids.add(metric_id)
metric_id_mapping[(category_name, metric.name)] = metric_id
else:
# Metric ID 0 is reserved (but unused) right now.
metric_id = 1
for category_name, metrics in objs.items():
for metric in metrics.values():
metric_id_mapping[(category_name, metric.name)] = metric_id
metric_id += 1
return lambda metric: metric_id_mapping[(metric.category, metric.name)]
def get_metrics(objs):
"""
Returns *just* the metrics in a set of Glean objects
"""
ret = copy.copy(objs)
for category in ["pings", "tags"]:
if ret.get(category):
del ret[category]
return ret
def type_ids_and_categories(objs) -> tuple[dict[str, tuple[int, list[str]]], list[str]]:
"""
Iterates over the metrics in objs, constructing two metadata structures:
- metric_types: dict[str, tuple[int, list[str]]] - map from a metric
type (snake_case) to its metric type id and ordered list of arguments.
- categories: list[str] - category names (snake_case)
Is stable across invocations: Will generate same ids for same objs.
(If it doesn't, JOG's factory disagreeing with GleanJSMetricsLookup
will break the build).
Uses the same order of metric args set out in glean_parser.util's
common_metric_args and extra_metric_args.
(If it didn't, it would supply args in the wrong order to metric type
constructors with multiple extra args (e.g. custom_distribution)).
"""
metric_types = set()
metric_type_ids = {}
categories = []
for category_name, objects in get_metrics(objs).items():
for metric in objects.values():
if metric.type not in metric_type_ids:
metric_types.add(metric.type)
metric_types = sorted(metric_types)
for category_name, objects in get_metrics(objs).items():
categories.append(category_name)
for metric in objects.values():
if metric.type not in metric_type_ids:
type_id = (
next(i for i, v in enumerate(metric_types) if v == metric.type) + 1
)
args = util.common_metric_args.copy()
for arg_name in util.extra_metric_args:
if hasattr(metric, arg_name):
args.append(arg_name)
metric_type_ids[metric.type] = {"id": type_id, "args": args}
metric_type_ids = dict(sorted(metric_type_ids.items()))
categories = sorted(categories)
return (metric_type_ids, categories)
|