diff --git a/CHANGELOG.md b/CHANGELOG.md index c1dfda3c..3c2d3ffb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +- BREAKING CHANGE: Generate labeled {custom|memory|timing} distribution for mobile ([#857](https://github.com/mozilla/glean_parser/pull/857)) + ## 20.2.0 - Allow renaming of fields when serializing metrics ([mozilla/glean-dictionary#2309](https://github.com/mozilla/glean-dictionary/issues/2309)) diff --git a/glean_parser/templates/kotlin.jinja2 b/glean_parser/templates/kotlin.jinja2 index b2e743f6..97a4a3dc 100644 --- a/glean_parser/templates/kotlin.jinja2 +++ b/glean_parser/templates/kotlin.jinja2 @@ -289,6 +289,10 @@ import {{ glean_namespace }}.private.{{ obj_type }} // ktlint-disable import-ord {% endfor %} {% if has_labeled_metrics %} import {{ glean_namespace }}.private.LabeledMetricType // ktlint-disable import-ordering +import {{ glean_namespace }}.private.CommonLabeledMetricData // ktlint-disable import-ordering no-unused-imports +import {{ glean_namespace }}.private.CustomDistributionLabeledMetricData // ktlint-disable import-ordering no-unused-imports +import {{ glean_namespace }}.private.MemoryDistributionLabeledMetricData // ktlint-disable import-ordering no-unused-imports +import {{ glean_namespace }}.private.TimingDistributionLabeledMetricData // ktlint-disable import-ordering no-unused-imports {% endif %} {% if has_object_metrics %} import {{ glean_namespace }}.private.intoSerializedObject @@ -344,12 +348,59 @@ internal object {{ category_name|Camelize }} { */ val {{ obj.name|camelize }}: LabeledMetricType<{{ obj|type_name }}> by lazy { // generated from {{ obj.identifier() }} LabeledMetricType( - category = {{ obj.category|kotlin }}, - name = {{ obj.name|kotlin }}, + {% if obj.type == "labeled_custom_distribution" %} + CustomDistributionLabeledMetricData( + cmd = CommonMetricData( + category = {{ obj.category|kotlin }}, + name = {{ obj.name|kotlin }}, + disabled = {{ obj.is_disabled()|kotlin }}, + lifetime = {{ obj.lifetime|kotlin }}, + sendInPings = {{ obj.send_in_pings|kotlin }} + ) + {%- for arg_name in extra_metric_args if obj[arg_name] is defined -%} + , {{ arg_name|camelize }} = {{ obj[arg_name]|kotlin }} + {%- endfor -%} + ), + {% elif obj.type == "labeled_memory_distribution" %} + MemoryDistributionLabeledMetricData( + cmd = CommonMetricData( + category = {{ obj.category|kotlin }}, + name = {{ obj.name|kotlin }}, + disabled = {{ obj.is_disabled()|kotlin }}, + lifetime = {{ obj.lifetime|kotlin }}, + sendInPings = {{ obj.send_in_pings|kotlin }} + ) + {%- for arg_name in extra_metric_args if obj[arg_name] is defined -%} + , {{ arg_name|camelize }} = {{ obj[arg_name]|kotlin }} + {%- endfor -%} + ), + {% elif obj.type == "labeled_timing_distribution" %} + TimingDistributionLabeledMetricData( + cmd = CommonMetricData( + category = {{ obj.category|kotlin }}, + name = {{ obj.name|kotlin }}, + disabled = {{ obj.is_disabled()|kotlin }}, + lifetime = {{ obj.lifetime|kotlin }}, + sendInPings = {{ obj.send_in_pings|kotlin }} + ) + {%- for arg_name in extra_metric_args if obj[arg_name] is defined -%} + , {{ arg_name|camelize }} = {{ obj[arg_name]|kotlin }} + {%- endfor -%} + ), + {% elif obj.labeled %} + CommonLabeledMetricData( + cmd = CommonMetricData( + category = {{ obj.category|kotlin }}, + name = {{ obj.name|kotlin }}, + disabled = {{ obj.is_disabled()|kotlin }}, + lifetime = {{ obj.lifetime|kotlin }}, + sendInPings = {{ obj.send_in_pings|kotlin }} + ) + ), + {% else %} + UNKNOWN + {% endif %} subMetric = {{ obj.name|camelize }}Label, - disabled = {{ obj.is_disabled()|kotlin }}, - lifetime = {{ obj.lifetime|kotlin }}, - sendInPings = {{ obj.send_in_pings|kotlin }}, labels = {{ obj.labels|kotlin }} ) } diff --git a/glean_parser/templates/swift.jinja2 b/glean_parser/templates/swift.jinja2 index e3622292..eb8cfc85 100644 --- a/glean_parser/templates/swift.jinja2 +++ b/glean_parser/templates/swift.jinja2 @@ -217,11 +217,61 @@ extension {{ namespace }} { {{ obj_declaration(obj, 'Label', 'private ') | indent }} /// {{ obj.description|wordwrap() | replace('\n', '\n /// ') }} static let {{ obj.name|camelize|variable_name }} = try! LabeledMetricType<{{ obj|type_name }}>( // generated from {{ obj.identifier() }} - category: {{ obj.category|swift }}, - name: {{ obj.name|swift }}, - sendInPings: {{ obj.send_in_pings|swift }}, - lifetime: {{ obj.lifetime|swift }}, - disabled: {{ obj.is_disabled()|swift }}, + {% if obj.type == "labeled_custom_distribution" %} + .customDistribution( + cmd: CommonMetricData( + category: {{ obj.category|swift }}, + name: {{ obj.name|swift }}, + sendInPings: {{ obj.send_in_pings|swift }}, + lifetime: {{ obj.lifetime|swift }}, + disabled: {{ obj.is_disabled()|swift }}, + ) + {% for arg_name in extra_metric_args if obj[arg_name] is defined %} + , {{ obj[arg_name]|swift }} + {% endfor %} + ), + {% elif obj.type == "labeled_memory_distribution" %} + .memoryDistribution( + cmd: CommonMetricData( + category: {{ obj.category|swift }}, + name: {{ obj.name|swift }}, + sendInPings: {{ obj.send_in_pings|swift }}, + lifetime: {{ obj.lifetime|swift }}, + disabled: {{ obj.is_disabled()|swift }}, + ) + {% for arg_name in extra_metric_args if obj[arg_name] is defined %} + , {{ obj[arg_name]|swift }} + {% endfor %} + ), + {% elif obj.type == "labeled_timing_distribution" %} + .timingDistribution( + cmd: CommonMetricData( + category: {{ obj.category|swift }}, + name: {{ obj.name|swift }}, + sendInPings: {{ obj.send_in_pings|swift }}, + lifetime: {{ obj.lifetime|swift }}, + disabled: {{ obj.is_disabled()|swift }}, + ) + {% for arg_name in extra_metric_args if obj[arg_name] is defined %} + , {{ obj[arg_name]|swift }} + {% endfor %} + ), + {% elif obj.labeled %} + .common( + cmd: CommonMetricData( + category: {{ obj.category|swift }}, + name: {{ obj.name|swift }}, + sendInPings: {{ obj.send_in_pings|swift }}, + lifetime: {{ obj.lifetime|swift }}, + disabled: {{ obj.is_disabled()|swift }}, + ) + {% for arg_name in extra_metric_args if obj[arg_name] is defined %} + , {{ obj[arg_name]|swift }} + {% endfor %} + ), + {% else %} + UNKNOWN + {% endif %} subMetric: {{ obj.name|camelize }}Label, labels: {{ obj.labels|swift }} ) diff --git a/tests/data/single_labeled.yaml b/tests/data/single_labeled.yaml index d3fba921..101f838f 100644 --- a/tests/data/single_labeled.yaml +++ b/tests/data/single_labeled.yaml @@ -4,10 +4,13 @@ --- $schema: moz://mozilla.org/schemas/glean/metrics/2-0-0 +no_lint: + - EXPIRATION_DATE_TOO_FAR + category: - labeled_counter: + labeled_counter: &defaults type: labeled_counter - lifetime: user + lifetime: ping description: > Foo bugs: @@ -19,3 +22,46 @@ category: send_in_pings: - core expires: 2100-01-01 + + labeled_boolean: + <<: *defaults + type: labeled_boolean + + labeled_string: + <<: *defaults + type: labeled_string + + labeled_custom_distribution: + <<: *defaults + type: labeled_custom_distribution + range_min: 0 + range_max: 100 + bucket_count: 10 + histogram_type: linear + labels: + - aLabel + - 2label + + labeled_memory_distribution: + <<: *defaults + type: labeled_memory_distribution + memory_unit: kilobyte + labels: + - aLabel + - 2label + + labeled_timing_distribution: + <<: *defaults + type: labeled_timing_distribution + time_unit: millisecond + labels: + - aLabel + - 2label + + labeled_quantity: + <<: *defaults + type: labeled_quantity + unit: tabs + labels: + - aLabel + - 2label diff --git a/tests/test_kotlin.py b/tests/test_kotlin.py index ed91466a..dcdb532c 100644 --- a/tests/test_kotlin.py +++ b/tests/test_kotlin.py @@ -411,3 +411,35 @@ def test_object_metric(tmp_path): assert "var moduleIndex: Int? = null," in content assert "var ip: String? = null," in content assert "var trust: String? = null," in content + + +def test_labeled_metrics(tmp_path): + """ + Assert that labeled metrics are created. + """ + translate.translate( + ROOT / "data" / "single_labeled.yaml", + "kotlin", + tmp_path, + {"namespace": "Foo"}, + ) + + assert set(x.name for x in tmp_path.iterdir()) == set( + ["Category.kt", "GleanBuildInfo.kt"] + ) + + with (tmp_path / "Category.kt").open("r", encoding="utf-8") as fd: + content = fd.read() + content = " ".join(content.split()) + + assert "LabeledMetricType" in content + assert "CommonMetricData(" in content + assert "LabeledMetricType" in content + assert "LabeledMetricType" in content + assert "LabeledMetricType" in content + assert "LabeledMetricType" in content + assert "CustomDistributionLabeledMetricData(" in content + assert "LabeledMetricType" in content + assert "TimingDistributionLabeledMetricData(" in content + assert "LabeledMetricType" in content + assert "MemoryDistributionLabeledMetricData(" in content diff --git a/tests/test_swift.py b/tests/test_swift.py index 6b6e1a5e..a4567744 100644 --- a/tests/test_swift.py +++ b/tests/test_swift.py @@ -380,3 +380,33 @@ def test_object_metric(tmp_path): assert "var moduleIndex: Int64?" in content assert "var ip: String?" in content assert "var trust: String?" in content + + +def test_labeled_metrics(tmp_path): + """ + Assert that labeled metrics are created. + """ + translate.translate( + ROOT / "data" / "single_labeled.yaml", + "swift", + tmp_path, + {"namespace": "Foo"}, + ) + + assert set(x.name for x in tmp_path.iterdir()) == set(["Metrics.swift"]) + + with (tmp_path / "Metrics.swift").open("r", encoding="utf-8") as fd: + content = fd.read() + content = " ".join(content.split()) + + assert "LabeledMetricType" in content + assert ".common(" in content + assert "LabeledMetricType" in content + assert "LabeledMetricType" in content + assert "LabeledMetricType" in content + assert "LabeledMetricType" in content + assert ".customDistribution(" in content + assert "LabeledMetricType" in content + assert ".timingDistribution(" in content + assert "LabeledMetricType" in content + assert ".memoryDistribution(" in content