diff --git a/CHANGELOG.md b/CHANGELOG.md index 19df5f0d6..45ed5cfed 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ## Unreleased - **Breaking change:** Updating Kotlin template import statement as part of removing `service-glean` from Android Components. ([bug 1906941](https://bugzilla.mozilla.org/show_bug.cgi?id=1906941)) +- **Breaking change:** Do not generate Geckoview Streaming helper code ([#743](https://github.com/mozilla/glean_parser/pull/743)) ## 14.5.2 diff --git a/glean_parser/kotlin.py b/glean_parser/kotlin.py index 6d9ea8dcf..47d9b8768 100644 --- a/glean_parser/kotlin.py +++ b/glean_parser/kotlin.py @@ -8,7 +8,6 @@ Outputter to generate Kotlin code for metrics. """ -from collections import OrderedDict import enum import json from pathlib import Path @@ -17,9 +16,7 @@ from . import __version__ from . import metrics from . import pings -from . import tags from . import util -from .util import DictWrapper def kotlin_datatypes_filter(value: util.JSONType) -> str: @@ -179,105 +176,6 @@ def generate_build_date(date: Optional[str]) -> str: return f'Calendar.getInstance(TimeZone.getTimeZone("GMT+0")).also {{ cal -> cal.set({components}) }}' # noqa -def output_gecko_lookup( - objs: metrics.ObjectTree, output_dir: Path, options: Optional[Dict[str, Any]] = None -) -> None: - """ - Given a tree of objects, generate a Kotlin map between Gecko histograms and - Glean SDK metric types. - - :param objects: A tree of objects (metrics and pings) as returned from - `parser.parse_objects`. - :param output_dir: Path to an output directory to write to. - :param options: options dictionary, with the following optional keys: - - - `namespace`: The package namespace to declare at the top of the - generated files. Defaults to `GleanMetrics`. - - `glean_namespace`: The package namespace of the glean library itself. - This is where glean objects will be imported from in the generated - code. - """ - if options is None: - options = {} - - template = util.get_jinja2_template( - "kotlin.geckoview.jinja2", - filters=( - ("kotlin", kotlin_datatypes_filter), - ("type_name", type_name), - ("class_name", class_name), - ), - ) - - namespace = options.get("namespace", "GleanMetrics") - glean_namespace = options.get("glean_namespace", "mozilla.components.service.glean") - - # Build a dictionary that contains data for metrics that are - # histogram-like/scalar-like and contain a gecko_datapoint, with this format: - # - # { - # "histograms": { - # "category": [ - # {"gecko_datapoint": "the-datapoint", "name": "the-metric-name"}, - # ... - # ], - # ... - # }, - # "other-type": {} - # } - gecko_metrics: Dict[str, Dict[str, List[Dict[str, str]]]] = DictWrapper() - - # Define scalar-like types. - SCALAR_LIKE_TYPES = ["boolean", "string", "quantity"] - - for category_key, category_val in objs.items(): - # Support exfiltration of Gecko metrics from products using both the - # Glean SDK and GeckoView. See bug 1566356 for more context. - for metric in category_val.values(): - # This is not a Gecko metric, skip it. - if ( - isinstance(metric, pings.Ping) - or isinstance(metric, tags.Tag) - or not getattr(metric, "gecko_datapoint", False) - ): - continue - - # Put scalars in their own categories, histogram-like in "histograms" and - # categorical histograms in "categoricals". - type_category = "histograms" - if metric.type in SCALAR_LIKE_TYPES: - type_category = metric.type - elif metric.type == "labeled_counter": - # Labeled counters with a 'gecko_datapoint' property - # are categorical histograms. - type_category = "categoricals" - - gecko_metrics.setdefault(type_category, OrderedDict()) - gecko_metrics[type_category].setdefault(category_key, []) - - gecko_metrics[type_category][category_key].append( - {"gecko_datapoint": metric.gecko_datapoint, "name": metric.name} - ) - - if not gecko_metrics: - # Bail out and don't create a file if no gecko metrics - # are found. - return - - filepath = output_dir / "GleanGeckoMetricsMapping.kt" - with filepath.open("w", encoding="utf-8") as fd: - fd.write( - template.render( - parser_version=__version__, - gecko_metrics=gecko_metrics, - namespace=namespace, - glean_namespace=glean_namespace, - ) - ) - # Jinja2 squashes the final newline, so we explicitly add it - fd.write("\n") - - def output_kotlin( objs: metrics.ObjectTree, output_dir: Path, options: Optional[Dict[str, Any]] = None ) -> None: @@ -376,6 +274,3 @@ def output_kotlin( ) # Jinja2 squashes the final newline, so we explicitly add it fd.write("\n") - - # TODO: Maybe this should just be a separate outputter? - output_gecko_lookup(objs, output_dir, options) diff --git a/glean_parser/templates/kotlin.geckoview.jinja2 b/glean_parser/templates/kotlin.geckoview.jinja2 deleted file mode 100644 index 359460dc7..000000000 --- a/glean_parser/templates/kotlin.geckoview.jinja2 +++ /dev/null @@ -1,124 +0,0 @@ -// -*- mode: kotlin -*- - -/* - * AUTOGENERATED BY glean_parser v{{ parser_version }}. DO NOT EDIT. DO NOT COMMIT. - */ -{# The rendered markdown 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/. */ - -@file:Suppress("PackageNaming", "MaxLineLength") -package {{ namespace }} - -import {{ glean_namespace }}.private.BooleanMetricType // ktlint-disable import-ordering no-unused-imports -import {{ glean_namespace }}.private.CounterMetricType // ktlint-disable import-ordering no-unused-imports -import {{ glean_namespace }}.private.HistogramBase // ktlint-disable import-ordering no-unused-imports -import {{ glean_namespace }}.private.LabeledMetricType // ktlint-disable import-ordering no-unused-imports -import {{ glean_namespace }}.private.QuantityMetricType // ktlint-disable import-ordering no-unused-imports -import {{ glean_namespace }}.private.StringMetricType // ktlint-disable import-ordering no-unused-imports - -/* - * This class performs the mapping between Gecko metrics and Glean SDK - * metric types. - */ -internal object GleanGeckoMetricsMapping { - // Support exfiltration of Gecko histograms from products using both the - // Glean SDK and GeckoView. See bug 1566356 for more context. - @Suppress("UNUSED_PARAMETER") - fun getHistogram(geckoMetricName: String): HistogramBase? { - {% if 'histograms' in gecko_metrics %} - return when (geckoMetricName) { - {% for category in gecko_metrics['histograms'].keys()|sort %} - // From {{ category|Camelize }}.kt - {% for metric in gecko_metrics['histograms'][category] %} - "{{ metric.gecko_datapoint }}" -> {{ category|Camelize }}.{{ metric.name|camelize }} - {% endfor %} - {%- endfor %} - else -> null - } - {% else %} - return null - {% endif %} - } - - // Support exfiltration of Gecko categorical histograms from products using - // both the Glean SDK and GeckoView. See bug 1571740 for more context. - @Suppress("UNUSED_PARAMETER") - fun getCategoricalMetric( - geckoMetricName: String - ): LabeledMetricType? { - {% if 'categoricals' in gecko_metrics %} - return when (geckoMetricName) { - {% for category in gecko_metrics['categoricals'].keys()|sort %} - // From {{ category|Camelize }}.kt - {% for metric in gecko_metrics['categoricals'][category] %} - "{{ metric.gecko_datapoint }}" -> {{ category|Camelize }}.{{ metric.name|camelize }} - {% endfor %} - {%- endfor %} - else -> null - } - {% else %} - return null - {% endif %} - } - - // Support exfiltration of Gecko boolean scalars from products using both the - // Glean SDK and GeckoView. See bug 1579365 for more context. - @Suppress("UNUSED_PARAMETER") - fun getBooleanScalar(geckoMetricName: String): BooleanMetricType? { - {% if 'boolean' in gecko_metrics %} - return when (geckoMetricName) { - {% for category in gecko_metrics['boolean'].keys()|sort %} - // From {{ category|Camelize }}.kt - {% for metric in gecko_metrics['boolean'][category] %} - "{{ metric.gecko_datapoint }}" -> {{ category|Camelize }}.{{ metric.name|camelize }} - {% endfor %} - {%- endfor %} - else -> null - } - {% else %} - return null - {% endif %} - } - - // Support exfiltration of Gecko string scalars from products using both the - // Glean SDK and GeckoView. See bug 1579365 for more context. - @Suppress("UNUSED_PARAMETER") - fun getStringScalar(geckoMetricName: String): StringMetricType? { - {% if 'string' in gecko_metrics %} - return when (geckoMetricName) { - {% for category in gecko_metrics['string'].keys()|sort %} - // From {{ category|Camelize }}.kt - {% for metric in gecko_metrics['string'][category] %} - "{{ metric.gecko_datapoint }}" -> {{ category|Camelize }}.{{ metric.name|camelize }} - {% endfor %} - {%- endfor %} - else -> null - } - {% else %} - return null - {% endif %} - } - - // Support exfiltration of Gecko quantity scalars from products using both the - // Glean SDK and GeckoView. See bug 1579365 for more context. - @Suppress("UNUSED_PARAMETER") - fun getQuantityScalar(geckoMetricName: String): QuantityMetricType? { - {% if 'quantity' in gecko_metrics %} - return when (geckoMetricName) { - {% for category in gecko_metrics['quantity'].keys()|sort %} - // From {{ category|Camelize }}.kt - {% for metric in gecko_metrics['quantity'][category] %} - "{{ metric.gecko_datapoint }}" -> {{ category|Camelize }}.{{ metric.name|camelize }} - {% endfor %} - {%- endfor %} - else -> null - } - {% else %} - return null - {% endif %} - } -} diff --git a/tests/data/gecko.yaml b/tests/data/gecko.yaml deleted file mode 100644 index 2fc0cd684..000000000 --- a/tests/data/gecko.yaml +++ /dev/null @@ -1,133 +0,0 @@ -# Any copyright is dedicated to the Public Domain. -# https://creativecommons.org/publicdomain/zero/1.0/ - ---- -$schema: moz://mozilla.org/schemas/glean/metrics/2-0-0 - -page.perf: - load_time: - type: timing_distribution - gecko_datapoint: GV_PAGE_LOAD_MS - time_unit: millisecond - lifetime: application - description: > - A sample timing distribution metric exported from Gecko. - bugs: - - https://bugzilla.mozilla.org/11566356 - data_reviews: - - http://example.com/reviews - notification_emails: - - CHANGE-ME@example.com - expires: 2100-01-01 - - reload_time: - type: timing_distribution - gecko_datapoint: GV_PAGE_RELOAD_MS - time_unit: millisecond - lifetime: application - description: > - Another sample timing distribution metric exported from Gecko. - bugs: - - https://bugzilla.mozilla.org/11566356 - data_reviews: - - http://example.com/reviews - notification_emails: - - CHANGE-ME@example.com - expires: 2100-01-01 - - dom_script_preload: - type: labeled_counter - gecko_datapoint: DOM_SCRIPT_PRELOAD_RESULT - labels: - - used - - rejected_by_policy - - request_mismatch - - load_error - - not_used - lifetime: application - description: > - A sample categorical metric exported from Gecko. - bugs: - - https://bugzilla.mozilla.org/11571740 - data_reviews: - - http://example.com/reviews - notification_emails: - - CHANGE-ME@example.com - expires: 2100-01-01 - no_lint: - - TYPE_IN_NAME - -gfx.content.checkerboard: - duration: - type: timing_distribution - gecko_datapoint: CHECKERBOARD_DURATION - time_unit: millisecond - lifetime: application - description: > - A sample timing distribution metric exported from Gecko. - bugs: - - https://bugzilla.mozilla.org/11566356 - data_reviews: - - http://example.com/reviews - notification_emails: - - CHANGE-ME@example.com - expires: 2100-01-01 - -gfx.info.adapter: - vendor_id: - type: string - gecko_datapoint: gfx_adapter.vendor_id - lifetime: application - description: > - A sample string metric. It's a string scalar exported from Gecko. - bugs: - - https://bugzilla.mozilla.org/11579365 - data_reviews: - - http://example.com/reviews - notification_emails: - - CHANGE-ME@example.com - expires: 2100-01-01 - - stand_alone: - type: boolean - gecko_datapoint: gfx_adapter.stand_alone - lifetime: application - description: > - A sample boolean metric. It's a boolean scalar exported from Gecko. - bugs: - - https://bugzilla.mozilla.org/11579365 - data_reviews: - - http://example.com/reviews - notification_emails: - - CHANGE-ME@example.com - expires: 2100-01-01 - - screen_width: - type: quantity - gecko_datapoint: gfx_adapter.width - unit: pixel - lifetime: application - description: > - A sample quantity metric. It's a uint scalar exported from Gecko. - bugs: - - https://bugzilla.mozilla.org/11579365 - data_reviews: - - http://example.com/reviews - notification_emails: - - CHANGE-ME@example.com - expires: 2100-01-01 - -non.gecko.metrics: - app_load_time: - type: timing_distribution - time_unit: millisecond - lifetime: application - description: > - A sample timing distribution that is not tied to a Gecko datapoint. - bugs: - - https://bugzilla.mozilla.org/11566356 - data_reviews: - - http://example.com/reviews - notification_emails: - - CHANGE-ME@example.com - expires: 2100-01-01 diff --git a/tests/test_kotlin.py b/tests/test_kotlin.py index 074406871..7fe33afc3 100644 --- a/tests/test_kotlin.py +++ b/tests/test_kotlin.py @@ -249,100 +249,6 @@ def test_glean_namespace(tmp_path): assert content.count("import Bar.private.CounterMetricType") == 1 -def test_gecko_datapoints(tmp_path): - """Test translating metrics to Kotlin files.""" - translate.translate( - ROOT / "data" / "gecko.yaml", - "kotlin", - tmp_path, - {"glean_namespace": "Bar"}, - {"allow_reserved": True}, - ) - - metrics_files = [ - "GfxContentCheckerboard.kt", - "GfxInfoAdapter.kt", - "PagePerf.kt", - "NonGeckoMetrics.kt", - "GleanBuildInfo.kt", - ] - assert set(x.name for x in tmp_path.iterdir()) == set( - ["GleanGeckoMetricsMapping.kt"] + metrics_files - ) - - # Make sure descriptions made it in - with (tmp_path / "GleanGeckoMetricsMapping.kt").open("r", encoding="utf-8") as fd: - content = fd.read() - # Make sure we're adding the relevant Glean SDK import, once. - assert content.count("import Bar.private.HistogramBase") == 1 - - # Validate the generated Gecko metric mapper Kotlin functions. - # NOTE: Indentation, whitespaces and text formatting of the block - # below are important. Do not change them unless the file format - # changes, otherwise validation will fail. - expected_func = """ fun getHistogram(geckoMetricName: String): HistogramBase? { - return when (geckoMetricName) { - // From GfxContentCheckerboard.kt - "CHECKERBOARD_DURATION" -> GfxContentCheckerboard.duration - // From PagePerf.kt - "GV_PAGE_LOAD_MS" -> PagePerf.loadTime - "GV_PAGE_RELOAD_MS" -> PagePerf.reloadTime - else -> null - } - }""" # noqa - - assert expected_func in content - - expected_func = """ fun getCategoricalMetric( - geckoMetricName: String - ): LabeledMetricType? { - return when (geckoMetricName) { - // From PagePerf.kt - "DOM_SCRIPT_PRELOAD_RESULT" -> PagePerf.domScriptPreload - else -> null - } - }""" - - assert expected_func in content - - expected_func = """ fun getBooleanScalar(geckoMetricName: String): BooleanMetricType? { - return when (geckoMetricName) { - // From GfxInfoAdapter.kt - "gfx_adapter.stand_alone" -> GfxInfoAdapter.standAlone - else -> null - } - }""" # noqa - - assert expected_func in content - - expected_func = """ fun getStringScalar(geckoMetricName: String): StringMetricType? { - return when (geckoMetricName) { - // From GfxInfoAdapter.kt - "gfx_adapter.vendor_id" -> GfxInfoAdapter.vendorId - else -> null - } - }""" # noqa - - assert expected_func in content - - expected_func = """ fun getQuantityScalar(geckoMetricName: String): QuantityMetricType? { - return when (geckoMetricName) { - // From GfxInfoAdapter.kt - "gfx_adapter.width" -> GfxInfoAdapter.screenWidth - else -> null - } - }""" # noqa - - assert expected_func in content - - for file_name in metrics_files: - with (tmp_path / file_name).open("r", encoding="utf-8") as fd: - content = fd.read() - assert "HistogramBase" not in content - - run_linters(tmp_path.glob("*.kt")) - - def test_event_extra_keys_in_correct_order(tmp_path): """ Assert that the extra keys appear in the parameter and the enumeration in