# 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/. import sys from os import path import yaml header = """ # 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/. # THIS FILE IS AUTO-GENERATED BY glean_metrics.py. DO NOT EDIT! """ source_path = path.join(path.dirname(__file__), "generated_metrics.yaml") def make_bugzilla_url(bug): return f"https://bugzilla.mozilla.org/{bug}" def remove_non_glean_fields(glean): """Remove all known fields in the glean descriptor which aren't directly forwarded to the glean metrics definition file. """ if glean["type"] == "string_list": glean.pop("delimiter") glean.pop("custom_convert", None) def generate_string(annotations): output = { "$schema": "moz://mozilla.org/schemas/glean/metrics/2-0-0", "$tags": ["Toolkit :: Crash Reporting"], } for name, definition in annotations: glean = definition.get("glean") if glean is None: continue metric_category, _, metric_name = glean.pop("metric").rpartition(".") remove_non_glean_fields(glean) bug_urls = [ make_bugzilla_url(bug) for bug in definition.get("bugs", ["1950749"]) ] glean.update( { "description": definition["description"].strip(), "notification_emails": [ "crash-reporting-wg@mozilla.org", "stability@mozilla.org", ], "bugs": bug_urls, "data_reviews": bug_urls.copy(), # Copy so the produced yaml doesn't use anchors "data_sensitivity": ["technical"], "expires": "never", "send_in_pings": ["crash"], } ) output.setdefault(metric_category, {})[metric_name] = glean return header + yaml.safe_dump(output, explicit_start=True) def import_path(mod, path): import importlib.util spec = importlib.util.spec_from_file_location(mod, path) module = importlib.util.module_from_spec(spec) spec.loader.exec_module(module) return module def main(output, annotations_path): with open(annotations_path) as annotations_file: annotations = yaml.safe_load(annotations_file) out = generate_string(annotations) # Check whether the source path contents match what we would generate. source_contents = "" if path.exists(source_path): with open(source_path) as file: source_contents = file.read() if source_contents != out: sys.exit(f"{source_path} contents outdated; run ./mach crash-ping-metrics") output.write(out) return {source_path} if __name__.startswith("mach.commands"): from mach.decorators import Command @Command( "crash-ping-metrics", category="misc", description="Generate the crash ping annotations Glean metrics files.", ) def crash_ping_metrics(command_context): load = import_path( "annotations.load", path.join(path.dirname(__file__), "..", "annotations", "load.py"), ) annotations = load.read_annotations() with open(source_path, "w") as file: file.write(generate_string(annotations))