glean-parser 17.1.0__tar.gz → 17.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- glean_parser-17.1.0/docs/readme.md → glean_parser-17.2.0/PKG-INFO +30 -11
- {glean_parser-17.1.0 → glean_parser-17.2.0}/README.md +1 -11
- {glean_parser-17.1.0 → glean_parser-17.2.0}/glean_parser/lint.py +28 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/glean_parser/metrics.py +56 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/glean_parser/parser.py +21 -4
- {glean_parser-17.1.0 → glean_parser-17.2.0}/glean_parser/rust.py +2 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/glean_parser/schemas/metrics.2-0-0.schema.yaml +64 -10
- {glean_parser-17.1.0 → glean_parser-17.2.0}/glean_parser/templates/rust.jinja2 +15 -2
- {glean_parser-17.1.0 → glean_parser-17.2.0}/glean_parser/util.py +9 -1
- glean_parser-17.2.0/pyproject.toml +76 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/tests/data/all_metrics.yaml +15 -0
- glean_parser-17.2.0/tests/data/dual_labeled.yaml +96 -0
- glean_parser-17.2.0/tests/data/dual_labeled_invalid.yaml +72 -0
- glean_parser-17.2.0/tests/data/redefined_category.yamlx +32 -0
- glean_parser-17.2.0/tests/data/redefined_metric.yamlx +31 -0
- glean_parser-17.2.0/tests/data/redefined_ping.yamlx +30 -0
- glean_parser-17.2.0/tests/data/same_name_different_category.yaml +32 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/tests/test_lint.py +48 -1
- {glean_parser-17.1.0 → glean_parser-17.2.0}/tests/test_parser.py +74 -1
- {glean_parser-17.1.0 → glean_parser-17.2.0}/tests/test_rust.py +48 -0
- glean_parser-17.1.0/.circleci/config.yml +0 -271
- glean_parser-17.1.0/.editorconfig +0 -21
- glean_parser-17.1.0/.github/CODEOWNERS +0 -12
- glean_parser-17.1.0/.github/ISSUE_TEMPLATE.md +0 -15
- glean_parser-17.1.0/.github/dependabot.yml +0 -6
- glean_parser-17.1.0/.github/pull_request_template.md +0 -8
- glean_parser-17.1.0/.swiftlint.yml +0 -6
- glean_parser-17.1.0/CHANGELOG.md +0 -820
- glean_parser-17.1.0/CODE_OF_CONDUCT.md +0 -15
- glean_parser-17.1.0/CONTRIBUTING.md +0 -189
- glean_parser-17.1.0/MANIFEST.in +0 -14
- glean_parser-17.1.0/Makefile +0 -79
- glean_parser-17.1.0/PKG-INFO +0 -897
- glean_parser-17.1.0/docs/Makefile +0 -20
- glean_parser-17.1.0/docs/_static/glean.jpeg +0 -0
- glean_parser-17.1.0/docs/authors.md +0 -17
- glean_parser-17.1.0/docs/conf.py +0 -160
- glean_parser-17.1.0/docs/contributing.md +0 -189
- glean_parser-17.1.0/docs/history.md +0 -820
- glean_parser-17.1.0/docs/index.rst +0 -27
- glean_parser-17.1.0/docs/installation.md +0 -41
- glean_parser-17.1.0/docs/make.bat +0 -36
- glean_parser-17.1.0/docs/metrics-yaml.rst +0 -13
- glean_parser-17.1.0/docs/pings-yaml.rst +0 -13
- glean_parser-17.1.0/docs/tags-yaml.rst +0 -13
- glean_parser-17.1.0/glean_parser.egg-info/PKG-INFO +0 -897
- glean_parser-17.1.0/glean_parser.egg-info/SOURCES.txt +0 -173
- glean_parser-17.1.0/glean_parser.egg-info/dependency_links.txt +0 -1
- glean_parser-17.1.0/glean_parser.egg-info/entry_points.txt +0 -2
- glean_parser-17.1.0/glean_parser.egg-info/not-zip-safe +0 -1
- glean_parser-17.1.0/glean_parser.egg-info/requires.txt +0 -6
- glean_parser-17.1.0/glean_parser.egg-info/top_level.txt +0 -1
- glean_parser-17.1.0/pytest.ini +0 -7
- glean_parser-17.1.0/requirements_dev.txt +0 -13
- glean_parser-17.1.0/setup.cfg +0 -10
- glean_parser-17.1.0/setup.py +0 -77
- glean_parser-17.1.0/tools/extract_data_categories.py +0 -176
- {glean_parser-17.1.0 → glean_parser-17.2.0}/.gitignore +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/AUTHORS.md +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/LICENSE +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/glean_parser/__init__.py +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/glean_parser/__main__.py +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/glean_parser/coverage.py +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/glean_parser/data_review.py +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/glean_parser/go_server.py +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/glean_parser/javascript.py +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/glean_parser/javascript_server.py +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/glean_parser/kotlin.py +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/glean_parser/markdown.py +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/glean_parser/pings.py +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/glean_parser/python_server.py +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/glean_parser/ruby_server.py +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/glean_parser/rust_server.py +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/glean_parser/schemas/metrics.1-0-0.schema.yaml +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/glean_parser/schemas/pings.1-0-0.schema.yaml +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/glean_parser/schemas/pings.2-0-0.schema.yaml +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/glean_parser/schemas/tags.1-0-0.schema.yaml +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/glean_parser/swift.py +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/glean_parser/tags.py +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/glean_parser/templates/data_review.jinja2 +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/glean_parser/templates/go_server.jinja2 +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/glean_parser/templates/javascript.buildinfo.jinja2 +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/glean_parser/templates/javascript.jinja2 +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/glean_parser/templates/javascript_server.jinja2 +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/glean_parser/templates/kotlin.buildinfo.jinja2 +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/glean_parser/templates/kotlin.jinja2 +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/glean_parser/templates/markdown.jinja2 +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/glean_parser/templates/python_server.jinja2 +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/glean_parser/templates/qmldir.jinja2 +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/glean_parser/templates/ruby_server.jinja2 +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/glean_parser/templates/rust_server.jinja2 +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/glean_parser/templates/swift.jinja2 +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/glean_parser/translate.py +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/glean_parser/translation_options.py +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/glean_parser/validate_ping.py +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/server_telemetry/sdk-metrics-compat.yaml +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/server_telemetry/server-side-pings.yaml +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/tests/conftest.py +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/tests/data/all_pings.yaml +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/tests/data/attribution.yaml +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/tests/data/bad_attribution.yamlx +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/tests/data/bad_ping.yamlx +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/tests/data/core.yaml +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/tests/data/duplicate_labeled.yaml +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/tests/data/duplicate_send_in_ping.yaml +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/tests/data/empty.yaml +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/tests/data/event_key_ordering.yaml +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/tests/data/events_with_types.yaml +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/tests/data/fxa-server-metrics.yaml +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/tests/data/fxa-server-pings.yaml +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/tests/data/go_server_custom_ping_only_metrics.yaml +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/tests/data/go_server_custom_ping_only_pings.yaml +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/tests/data/go_server_events_and_custom_ping_metrics.yaml +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/tests/data/go_server_events_and_custom_ping_pings.yaml +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/tests/data/go_server_events_only_metrics.yaml +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/tests/data/go_server_metrics_unsupported.yaml +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/tests/data/invalid-ping-names.yaml +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/tests/data/invalid.yamlx +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/tests/data/jwe.yaml +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/tests/data/metric-with-tags.yaml +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/tests/data/mixed-expirations.yaml +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/tests/data/name_too_similar.yaml +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/tests/data/object.yaml +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/tests/data/old_event_api.yamlx +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/tests/data/ordering.yaml +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/tests/data/pings.yaml +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/tests/data/rate.yaml +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/tests/data/reserved_categories.yamlx +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/tests/data/ruby_server_metrics_unsupported.yaml +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/tests/data/ruby_server_pings_unsupported.yaml +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/tests/data/rust_server_custom_ping_only_metrics.yaml +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/tests/data/rust_server_custom_ping_only_pings.yaml +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/tests/data/rust_server_events_and_custom_ping_metrics.yaml +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/tests/data/rust_server_events_and_custom_ping_pings.yaml +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/tests/data/rust_server_events_only_metrics.yaml +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/tests/data/rust_server_metrics_unsupported.yaml +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/tests/data/schema-violation.yaml +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/tests/data/send_if_empty_with_metrics.yaml +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/tests/data/server_custom_ping_only_compare.go +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/tests/data/server_custom_ping_only_compare.rs +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/tests/data/server_events_and_custom_ping_compare.go +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/tests/data/server_events_and_custom_ping_compare.rs +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/tests/data/server_events_compare.rb +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/tests/data/server_events_only_compare.go +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/tests/data/server_events_only_compare.rs +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/tests/data/server_metrics_no_events_no_pings.yaml +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/tests/data/server_metrics_with_event.yaml +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/tests/data/server_pings.yaml +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/tests/data/single_labeled.yaml +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/tests/data/smaller.yaml +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/tests/data/tags.yaml +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/tests/data/telemetry_mirror.yaml +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/tests/data/text.yaml +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/tests/data/text_invalid.yaml +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/tests/data/unknown_ping_used.yaml +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/tests/data/wrong_key.yamlx +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/tests/data/yaml_nits.yamlx +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/tests/detekt.yml +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/tests/test-go/test.go.tmpl +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/tests/test-js/package.json +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/tests/test-js/test.js.tmpl +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/tests/test-py/test.py +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/tests/test-rb/test.rb.tmpl +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/tests/test-rs/test.rs.tmpl +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/tests/test_cli.py +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/tests/test_go_server.py +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/tests/test_javascript.py +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/tests/test_javascript_server.py +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/tests/test_kotlin.py +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/tests/test_markdown.py +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/tests/test_metrics.py +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/tests/test_pings.py +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/tests/test_python_server.py +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/tests/test_ruby_server.py +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/tests/test_rust_server.py +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/tests/test_swift.py +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/tests/test_tags.py +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/tests/test_translate.py +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/tests/test_utils.py +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/tests/test_validate_ping.py +0 -0
- {glean_parser-17.1.0 → glean_parser-17.2.0}/tests/util.py +0 -0
|
@@ -1,3 +1,32 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: glean-parser
|
|
3
|
+
Version: 17.2.0
|
|
4
|
+
Summary: Parser tools for Mozilla's Glean telemetry
|
|
5
|
+
Project-URL: Homepage, https://mozilla.github.io/glean
|
|
6
|
+
Project-URL: Repository, https://github.com/mozilla/glean_parser
|
|
7
|
+
Project-URL: Changelog, https://github.com/mozilla/glean_parser/blob/main/CHANGELOG.md
|
|
8
|
+
Author-email: The Glean Team <glean-team@mozilla.com>
|
|
9
|
+
License-File: AUTHORS.md
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: Natural Language :: English
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
21
|
+
Requires-Python: >=3.8
|
|
22
|
+
Requires-Dist: click>=7
|
|
23
|
+
Requires-Dist: diskcache>=4
|
|
24
|
+
Requires-Dist: jinja2>=2.10.1
|
|
25
|
+
Requires-Dist: jsonschema>=3.0.2
|
|
26
|
+
Requires-Dist: platformdirs>=2.4.0
|
|
27
|
+
Requires-Dist: pyyaml>=5.3.1
|
|
28
|
+
Description-Content-Type: text/markdown
|
|
29
|
+
|
|
1
30
|
# Glean Parser
|
|
2
31
|
|
|
3
32
|
Parser tools for Mozilla's Glean telemetry.
|
|
@@ -16,17 +45,7 @@ code for various integrations, linting and coverage testing.
|
|
|
16
45
|
|
|
17
46
|
## Requirements
|
|
18
47
|
|
|
19
|
-
-
|
|
20
|
-
|
|
21
|
-
The following library requirements are installed automatically when
|
|
22
|
-
`glean_parser` is installed by `pip`.
|
|
23
|
-
|
|
24
|
-
- Click
|
|
25
|
-
- diskcache
|
|
26
|
-
- Jinja2
|
|
27
|
-
- jsonschema
|
|
28
|
-
- platformdirs
|
|
29
|
-
- PyYAML
|
|
48
|
+
- Python 3.8 (or later)
|
|
30
49
|
|
|
31
50
|
## Usage
|
|
32
51
|
|
|
@@ -16,17 +16,7 @@ code for various integrations, linting and coverage testing.
|
|
|
16
16
|
|
|
17
17
|
## Requirements
|
|
18
18
|
|
|
19
|
-
-
|
|
20
|
-
|
|
21
|
-
The following library requirements are installed automatically when
|
|
22
|
-
`glean_parser` is installed by `pip`.
|
|
23
|
-
|
|
24
|
-
- Click
|
|
25
|
-
- diskcache
|
|
26
|
-
- Jinja2
|
|
27
|
-
- jsonschema
|
|
28
|
-
- platformdirs
|
|
29
|
-
- PyYAML
|
|
19
|
+
- Python 3.8 (or later)
|
|
30
20
|
|
|
31
21
|
## Usage
|
|
32
22
|
|
|
@@ -572,6 +572,20 @@ def lint_metrics(
|
|
|
572
572
|
|
|
573
573
|
nits.extend(_lint_all_objects(objs, parser_config))
|
|
574
574
|
|
|
575
|
+
# The information for whether there's duplicate categories found within the
|
|
576
|
+
# same YAML document is on the objs value, which is not presently linted
|
|
577
|
+
# (we pull out its metrics, pings, and tags and lint those).
|
|
578
|
+
# So we perform that custom work here.
|
|
579
|
+
if getattr(objs, "duplicate", None):
|
|
580
|
+
nits.append(
|
|
581
|
+
GlinterNit(
|
|
582
|
+
"REDEFINED_CATEGORY",
|
|
583
|
+
getattr(objs, "duplicate", ""),
|
|
584
|
+
f"Category redefined {objs.duplicate}", # type: ignore[attr-defined]
|
|
585
|
+
CheckType.error,
|
|
586
|
+
)
|
|
587
|
+
)
|
|
588
|
+
|
|
575
589
|
for category_name, category in sorted(list(objs.items())):
|
|
576
590
|
if category_name == "pings":
|
|
577
591
|
nits.extend(_lint_pings(category, parser_config, valid_tag_names))
|
|
@@ -581,6 +595,20 @@ def lint_metrics(
|
|
|
581
595
|
# currently we have no linting for tags
|
|
582
596
|
continue
|
|
583
597
|
|
|
598
|
+
# The information for whether there's duplicate metrics found within the
|
|
599
|
+
# same YAML document is on the category value, which is not presently linted
|
|
600
|
+
# (we lint only its metrics).
|
|
601
|
+
# So we perform that custom work here.
|
|
602
|
+
if getattr(objs[category_name], "duplicate", None):
|
|
603
|
+
nits.append(
|
|
604
|
+
GlinterNit(
|
|
605
|
+
"REDEFINED_METRIC",
|
|
606
|
+
category_name,
|
|
607
|
+
f"Metric redefined {getattr(objs[category_name], 'duplicate', '')}",
|
|
608
|
+
CheckType.error,
|
|
609
|
+
)
|
|
610
|
+
)
|
|
611
|
+
|
|
584
612
|
# Make sure the category has only Metrics, not Pings or Tags
|
|
585
613
|
category_metrics = dict(
|
|
586
614
|
(name, metric)
|
|
@@ -416,18 +416,23 @@ class LabeledString(Labeled, String):
|
|
|
416
416
|
class LabeledCounter(Labeled, Counter):
|
|
417
417
|
typename = "labeled_counter"
|
|
418
418
|
|
|
419
|
+
|
|
419
420
|
class LabeledCustomDistribution(Labeled, CustomDistribution):
|
|
420
421
|
typename = "labeled_custom_distribution"
|
|
421
422
|
|
|
423
|
+
|
|
422
424
|
class LabeledMemoryDistribution(Labeled, MemoryDistribution):
|
|
423
425
|
typename = "labeled_memory_distribution"
|
|
424
426
|
|
|
427
|
+
|
|
425
428
|
class LabeledTimingDistribution(Labeled, TimingDistribution):
|
|
426
429
|
typename = "labeled_timing_distribution"
|
|
427
430
|
|
|
431
|
+
|
|
428
432
|
class LabeledQuantity(Labeled, Quantity):
|
|
429
433
|
typename = "labeled_quantity"
|
|
430
434
|
|
|
435
|
+
|
|
431
436
|
class Rate(Metric):
|
|
432
437
|
typename = "rate"
|
|
433
438
|
|
|
@@ -527,4 +532,55 @@ class Object(Metric):
|
|
|
527
532
|
return structure
|
|
528
533
|
|
|
529
534
|
|
|
535
|
+
class DualLabeledCounter(Metric):
|
|
536
|
+
typename = "dual_labeled_counter"
|
|
537
|
+
dual_labeled = True
|
|
538
|
+
|
|
539
|
+
def __init__(self, *args, **kwargs):
|
|
540
|
+
dual_labels = kwargs.pop("dual_labels", None)
|
|
541
|
+
if not dual_labels:
|
|
542
|
+
raise ValueError(
|
|
543
|
+
"`dual_labeled_counter` is missing required parameter `dual_labels`"
|
|
544
|
+
)
|
|
545
|
+
k = dual_labels.get("key", None)
|
|
546
|
+
if not k:
|
|
547
|
+
raise ValueError("`dual_labels` is missing required parameter `key`")
|
|
548
|
+
c = dual_labels.get("category", None)
|
|
549
|
+
if not c:
|
|
550
|
+
raise ValueError("`dual_labels` is missing required parameter `categories`")
|
|
551
|
+
keys = k.get("labels", None)
|
|
552
|
+
if keys is not None:
|
|
553
|
+
if not isinstance(keys, list) or not all(isinstance(k, str) for k in keys):
|
|
554
|
+
raise ValueError("key `labels` must be a list of strings")
|
|
555
|
+
self.ordered_keys = keys
|
|
556
|
+
self.keys = set([CowString(key) for key in keys])
|
|
557
|
+
else:
|
|
558
|
+
self.ordered_keys = None
|
|
559
|
+
self.keys = None
|
|
560
|
+
categories = c.get("labels", None)
|
|
561
|
+
if categories is not None:
|
|
562
|
+
if not isinstance(categories, list) or not all(
|
|
563
|
+
isinstance(c, str) for c in categories
|
|
564
|
+
):
|
|
565
|
+
raise ValueError("category `labels` must be a list of strings")
|
|
566
|
+
self.ordered_categories = categories
|
|
567
|
+
self.categories = set([CowString(category) for category in categories])
|
|
568
|
+
else:
|
|
569
|
+
self.ordered_categories = None
|
|
570
|
+
self.categories = None
|
|
571
|
+
super().__init__(*args, **kwargs)
|
|
572
|
+
|
|
573
|
+
def serialize(self) -> Dict[str, util.JSONType]:
|
|
574
|
+
"""
|
|
575
|
+
Serialize the metric back to JSON object model.
|
|
576
|
+
"""
|
|
577
|
+
d = super().serialize()
|
|
578
|
+
d["keys"] = self.ordered_keys
|
|
579
|
+
d["categories"] = self.ordered_categories
|
|
580
|
+
del d["ordered_keys"]
|
|
581
|
+
del d["ordered_categories"]
|
|
582
|
+
del d["dual_labeled"]
|
|
583
|
+
return d
|
|
584
|
+
|
|
585
|
+
|
|
530
586
|
ObjectTree = Dict[str, Dict[str, Union[Metric, pings.Ping, tags.Tag]]]
|
|
@@ -182,6 +182,10 @@ def _instantiate_metrics(
|
|
|
182
182
|
global_tags = content.get("$tags", [])
|
|
183
183
|
assert isinstance(global_tags, list)
|
|
184
184
|
|
|
185
|
+
# Duplicate category names end up on the root content.
|
|
186
|
+
if not hasattr(all_objects, "duplicate"):
|
|
187
|
+
setattr(all_objects, "duplicate", getattr(content, "duplicate", None))
|
|
188
|
+
|
|
185
189
|
for category_key, category_val in sorted(content.items()):
|
|
186
190
|
if category_key.startswith("$"):
|
|
187
191
|
continue
|
|
@@ -273,6 +277,12 @@ def _instantiate_metrics(
|
|
|
273
277
|
metric_obj.defined_in["line"],
|
|
274
278
|
)
|
|
275
279
|
else:
|
|
280
|
+
if not hasattr(all_objects[category_key], "duplicate"):
|
|
281
|
+
setattr(
|
|
282
|
+
all_objects[category_key],
|
|
283
|
+
"duplicate",
|
|
284
|
+
getattr(content[category_key], "duplicate", None),
|
|
285
|
+
)
|
|
276
286
|
all_objects[category_key][metric_key] = metric_obj
|
|
277
287
|
sources[(category_key, metric_key)] = filepath
|
|
278
288
|
|
|
@@ -292,6 +302,15 @@ def _instantiate_pings(
|
|
|
292
302
|
assert isinstance(global_no_lint, list)
|
|
293
303
|
ping_schedule_reverse_map: Dict[str, Set[str]] = dict()
|
|
294
304
|
|
|
305
|
+
# Duplicate ping names end up on the root content.
|
|
306
|
+
duplicate_ping = getattr(content, "duplicate", None)
|
|
307
|
+
if duplicate_ping:
|
|
308
|
+
yield util.format_error(
|
|
309
|
+
filepath,
|
|
310
|
+
"",
|
|
311
|
+
f"Duplicate ping named '{duplicate_ping}'.",
|
|
312
|
+
)
|
|
313
|
+
|
|
295
314
|
for ping_key, ping_val in sorted(content.items()):
|
|
296
315
|
if ping_key.startswith("$"):
|
|
297
316
|
continue
|
|
@@ -344,8 +363,7 @@ def _instantiate_pings(
|
|
|
344
363
|
yield util.format_error(
|
|
345
364
|
filepath,
|
|
346
365
|
"",
|
|
347
|
-
f"Duplicate ping name '{ping_key}' "
|
|
348
|
-
f"already defined in '{already_seen}'",
|
|
366
|
+
f"Duplicate ping name '{ping_key}' already defined in '{already_seen}'",
|
|
349
367
|
)
|
|
350
368
|
else:
|
|
351
369
|
all_objects.setdefault("pings", {})[ping_key] = ping_obj
|
|
@@ -403,8 +421,7 @@ def _instantiate_tags(
|
|
|
403
421
|
yield util.format_error(
|
|
404
422
|
filepath,
|
|
405
423
|
"",
|
|
406
|
-
f"Duplicate tag name '{tag_key}' "
|
|
407
|
-
f"already defined in '{already_seen}'",
|
|
424
|
+
f"Duplicate tag name '{tag_key}' already defined in '{already_seen}'",
|
|
408
425
|
)
|
|
409
426
|
else:
|
|
410
427
|
all_objects.setdefault("tags", {})[tag_key] = tag_obj
|
|
@@ -101,6 +101,8 @@ def type_name(obj):
|
|
|
101
101
|
|
|
102
102
|
if getattr(obj, "labeled", False):
|
|
103
103
|
return "LabeledMetric<{}>".format(class_name(obj.type))
|
|
104
|
+
if getattr(obj, "dual_labeled_counter", False):
|
|
105
|
+
return "DualLabeledCounterMetric"
|
|
104
106
|
generate_enums = getattr(obj, "_generate_enums", []) # Extra Keys? Reasons?
|
|
105
107
|
if len(generate_enums):
|
|
106
108
|
generic = None
|
|
@@ -52,7 +52,16 @@ definitions:
|
|
|
52
52
|
labeled_metric_id:
|
|
53
53
|
type: string
|
|
54
54
|
pattern: "^[ -~]+$"
|
|
55
|
-
maxLength:
|
|
55
|
+
maxLength: 111 # Note: this should be category + metric + 1
|
|
56
|
+
|
|
57
|
+
optional_labels:
|
|
58
|
+
anyOf:
|
|
59
|
+
- type: array
|
|
60
|
+
uniqueItems: true
|
|
61
|
+
items:
|
|
62
|
+
$ref: "#/definitions/labeled_metric_id"
|
|
63
|
+
maxItems: 4096
|
|
64
|
+
- type: "null"
|
|
56
65
|
|
|
57
66
|
metric:
|
|
58
67
|
description: |
|
|
@@ -121,14 +130,20 @@ definitions:
|
|
|
121
130
|
metric types include:
|
|
122
131
|
|
|
123
132
|
`labeled_boolean`, `labeled_string`, `labeled_counter`,
|
|
124
|
-
`
|
|
125
|
-
`
|
|
133
|
+
`dual_labeled_counter`, `labeled_custom_distribution`,
|
|
134
|
+
`labeled_memory_distribution`, `labeled_timing_distribution`,
|
|
135
|
+
`labeled_quantity`.
|
|
126
136
|
|
|
127
137
|
- `text`: Record long text data.
|
|
128
138
|
|
|
129
139
|
- `object`: Record structured data based on a pre-defined schema
|
|
130
140
|
Additional properties: `structure`.
|
|
131
141
|
|
|
142
|
+
- `dual_labeled_counter`: A counter with two label dimensions.
|
|
143
|
+
This metric type is used to record a counter with two different
|
|
144
|
+
label axes, such as a key and a category. Additional properties:
|
|
145
|
+
`dual_labels`.
|
|
146
|
+
|
|
132
147
|
type: string
|
|
133
148
|
enum:
|
|
134
149
|
- event
|
|
@@ -155,6 +170,7 @@ definitions:
|
|
|
155
170
|
- rate
|
|
156
171
|
- text
|
|
157
172
|
- object
|
|
173
|
+
- dual_labeled_counter
|
|
158
174
|
|
|
159
175
|
description:
|
|
160
176
|
title: Description
|
|
@@ -370,13 +386,51 @@ definitions:
|
|
|
370
386
|
labels in the special label `__other__`.
|
|
371
387
|
|
|
372
388
|
Valid with any of the labeled metric types.
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
389
|
+
$ref: "#/definitions/optional_labels"
|
|
390
|
+
|
|
391
|
+
dual_labels:
|
|
392
|
+
type: object
|
|
393
|
+
description: Defines the two label dimensions for a dual-labeled metric.
|
|
394
|
+
properties:
|
|
395
|
+
key:
|
|
396
|
+
type: object
|
|
397
|
+
description: The primary label dimension.
|
|
398
|
+
properties:
|
|
399
|
+
description:
|
|
400
|
+
type: string
|
|
401
|
+
description: |
|
|
402
|
+
Human-readable description of the key dimension (first label
|
|
403
|
+
axis).
|
|
404
|
+
labels:
|
|
405
|
+
description: |
|
|
406
|
+
Optional list of statically defined label values for the key
|
|
407
|
+
dimension.
|
|
408
|
+
$ref: "#/definitions/optional_labels"
|
|
409
|
+
required:
|
|
410
|
+
- description
|
|
411
|
+
additionalProperties: false
|
|
412
|
+
category:
|
|
413
|
+
type: object
|
|
414
|
+
description: The secondary label dimension.
|
|
415
|
+
properties:
|
|
416
|
+
description:
|
|
417
|
+
type: string
|
|
418
|
+
description: |
|
|
419
|
+
Human-readable description of the category dimension (second
|
|
420
|
+
label axis).
|
|
421
|
+
labels:
|
|
422
|
+
description: |
|
|
423
|
+
Optional list of statically defined label values for the
|
|
424
|
+
category dimension.
|
|
425
|
+
$ref: "#/definitions/optional_labels"
|
|
426
|
+
required:
|
|
427
|
+
- description
|
|
428
|
+
additionalProperties: false
|
|
429
|
+
required:
|
|
430
|
+
- key
|
|
431
|
+
- category
|
|
432
|
+
additionalProperties: false
|
|
433
|
+
|
|
380
434
|
|
|
381
435
|
extra_keys:
|
|
382
436
|
title: Extra keys
|
|
@@ -89,7 +89,7 @@ CommonMetricData {
|
|
|
89
89
|
disabled: {{ obj.is_disabled()|rust }},
|
|
90
90
|
..Default::default()
|
|
91
91
|
}
|
|
92
|
-
{
|
|
92
|
+
{%- endmacro -%}
|
|
93
93
|
{% for category in categories %}
|
|
94
94
|
{% if category.contains_pings %}
|
|
95
95
|
{% for obj in category.objs.values() %}
|
|
@@ -150,7 +150,7 @@ pub mod {{ category.name|snake_case }} {
|
|
|
150
150
|
{%- for arg_name in extra_metric_args if not obj.labeled and obj[arg_name] is defined and arg_name != 'allowed_extra_keys' -%}
|
|
151
151
|
, {{ obj[arg_name]|rust }}
|
|
152
152
|
{%- endfor -%}
|
|
153
|
-
{{ ", " if obj.labeled else ")\n" }}
|
|
153
|
+
{{ ", " if obj.labeled or obj.dual_labeled else ")\n" }}
|
|
154
154
|
{%- if obj.labeled -%}
|
|
155
155
|
{%- if obj.labels -%}
|
|
156
156
|
Some({{ obj.labels|rust }})
|
|
@@ -158,6 +158,19 @@ pub mod {{ category.name|snake_case }} {
|
|
|
158
158
|
None
|
|
159
159
|
{%- endif -%})
|
|
160
160
|
{% endif %}
|
|
161
|
+
{%- if obj.dual_labeled -%}
|
|
162
|
+
{%- if obj.keys -%}
|
|
163
|
+
Some({{ obj.keys|rust }})
|
|
164
|
+
{%- else -%}
|
|
165
|
+
None
|
|
166
|
+
{%- endif -%}
|
|
167
|
+
{{ ", " }}
|
|
168
|
+
{%- if obj.categories -%}
|
|
169
|
+
Some({{ obj.categories|rust }})
|
|
170
|
+
{%- else -%}
|
|
171
|
+
None
|
|
172
|
+
{%- endif -%})
|
|
173
|
+
{% endif %}
|
|
161
174
|
});
|
|
162
175
|
{% endfor %}
|
|
163
176
|
}
|
|
@@ -88,7 +88,15 @@ def yaml_load(stream):
|
|
|
88
88
|
|
|
89
89
|
def _construct_mapping_adding_line(loader, node):
|
|
90
90
|
loader.flatten_mapping(node)
|
|
91
|
-
|
|
91
|
+
pairs = loader.construct_pairs(node)
|
|
92
|
+
|
|
93
|
+
# Redefinition of a key might be a mistake if that key is a metric name.
|
|
94
|
+
mapping = DictWrapper()
|
|
95
|
+
for pair in pairs:
|
|
96
|
+
if pair[0] in mapping:
|
|
97
|
+
mapping.duplicate = pair[0]
|
|
98
|
+
mapping[pair[0]] = pair[1]
|
|
99
|
+
|
|
92
100
|
mapping.defined_in = {"line": node.start_mark.line}
|
|
93
101
|
return mapping
|
|
94
102
|
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "glean-parser"
|
|
3
|
+
dynamic = ["version"]
|
|
4
|
+
authors = [
|
|
5
|
+
{ name = "The Glean Team", email = "glean-team@mozilla.com" }
|
|
6
|
+
]
|
|
7
|
+
description = "Parser tools for Mozilla's Glean telemetry"
|
|
8
|
+
readme = "README.md"
|
|
9
|
+
classifiers = [
|
|
10
|
+
"Development Status :: 5 - Production/Stable",
|
|
11
|
+
"Intended Audience :: Developers",
|
|
12
|
+
"Natural Language :: English",
|
|
13
|
+
"Programming Language :: Python :: 3",
|
|
14
|
+
"Programming Language :: Python :: 3.8",
|
|
15
|
+
"Programming Language :: Python :: 3.9",
|
|
16
|
+
"Programming Language :: Python :: 3.10",
|
|
17
|
+
"Programming Language :: Python :: 3.11",
|
|
18
|
+
"Programming Language :: Python :: 3.12",
|
|
19
|
+
"Programming Language :: Python :: 3.13",
|
|
20
|
+
]
|
|
21
|
+
requires-python = ">=3.8"
|
|
22
|
+
dependencies = [
|
|
23
|
+
"Click>=7",
|
|
24
|
+
"diskcache>=4",
|
|
25
|
+
"Jinja2>=2.10.1",
|
|
26
|
+
"jsonschema>=3.0.2",
|
|
27
|
+
"platformdirs>=2.4.0",
|
|
28
|
+
"PyYAML>=5.3.1",
|
|
29
|
+
]
|
|
30
|
+
|
|
31
|
+
[project.urls]
|
|
32
|
+
Homepage = "https://mozilla.github.io/glean"
|
|
33
|
+
Repository = "https://github.com/mozilla/glean_parser"
|
|
34
|
+
Changelog = "https://github.com/mozilla/glean_parser/blob/main/CHANGELOG.md"
|
|
35
|
+
|
|
36
|
+
[project.scripts]
|
|
37
|
+
glean_parser = "glean_parser.__main__:main_wrapper"
|
|
38
|
+
|
|
39
|
+
[build-system]
|
|
40
|
+
requires = ["hatchling", "hatch-vcs"]
|
|
41
|
+
build-backend = "hatchling.build"
|
|
42
|
+
|
|
43
|
+
[dependency-groups]
|
|
44
|
+
dev = [
|
|
45
|
+
"coverage>=7.6.1",
|
|
46
|
+
"mypy>=1.14.1",
|
|
47
|
+
"pip-licenses>=4.5.1",
|
|
48
|
+
"pytest>=8.3.4",
|
|
49
|
+
"recommonmark>=0.7.1",
|
|
50
|
+
"ruff>=0.9.3",
|
|
51
|
+
"sphinx>=7.1.2",
|
|
52
|
+
"types-pyyaml>=6.0.12.20241230",
|
|
53
|
+
"yamllint>=1.35.1",
|
|
54
|
+
]
|
|
55
|
+
|
|
56
|
+
[tool.hatch.build.targets.sdist]
|
|
57
|
+
include = [
|
|
58
|
+
"/glean_parser",
|
|
59
|
+
"/server_telemetry",
|
|
60
|
+
"/tests",
|
|
61
|
+
]
|
|
62
|
+
|
|
63
|
+
[tool.hatch.version]
|
|
64
|
+
source = "vcs"
|
|
65
|
+
|
|
66
|
+
[tool.hatch.version.raw-options]
|
|
67
|
+
version_scheme = "no-guess-dev"
|
|
68
|
+
|
|
69
|
+
[tool.pytest.ini_options]
|
|
70
|
+
markers = [
|
|
71
|
+
"web_dependency: mark a test that requires a web connection.",
|
|
72
|
+
"node_dependency: mark a test that requires node.",
|
|
73
|
+
"ruby_dependency: mark a test that requires ruby.",
|
|
74
|
+
"go_dependency: mark a test that requires go.",
|
|
75
|
+
"rust_dependency: mark a test that requires rust.",
|
|
76
|
+
]
|
|
@@ -27,6 +27,21 @@ all_metrics:
|
|
|
27
27
|
- label_a
|
|
28
28
|
- label_b
|
|
29
29
|
|
|
30
|
+
dual_labeled_counter:
|
|
31
|
+
<<: *defaults
|
|
32
|
+
type: dual_labeled_counter
|
|
33
|
+
dual_labels:
|
|
34
|
+
key:
|
|
35
|
+
description: The key for the dual labeled counter
|
|
36
|
+
labels:
|
|
37
|
+
- key1
|
|
38
|
+
- key2
|
|
39
|
+
category:
|
|
40
|
+
description: The category for the dual labeled counter
|
|
41
|
+
labels:
|
|
42
|
+
- category1
|
|
43
|
+
- category2
|
|
44
|
+
|
|
30
45
|
bool:
|
|
31
46
|
<<: *defaults
|
|
32
47
|
type: boolean
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
# Any copyright is dedicated to the Public Domain.
|
|
2
|
+
# https://creativecommons.org/publicdomain/zero/1.0/
|
|
3
|
+
|
|
4
|
+
---
|
|
5
|
+
$schema: moz://mozilla.org/schemas/glean/metrics/2-0-0
|
|
6
|
+
|
|
7
|
+
no_lint: [EXPIRATION_DATE_TOO_FAR]
|
|
8
|
+
|
|
9
|
+
test.dual_labeled:
|
|
10
|
+
static_static:
|
|
11
|
+
type: dual_labeled_counter
|
|
12
|
+
description: >
|
|
13
|
+
A dual labeled counter with static keys and categories
|
|
14
|
+
dual_labels:
|
|
15
|
+
key:
|
|
16
|
+
description: >
|
|
17
|
+
The key for the dual labeled counter
|
|
18
|
+
labels:
|
|
19
|
+
- key1
|
|
20
|
+
- key2
|
|
21
|
+
category:
|
|
22
|
+
description: >
|
|
23
|
+
The category for the dual labeled counter
|
|
24
|
+
labels:
|
|
25
|
+
- category1
|
|
26
|
+
- category2
|
|
27
|
+
bugs:
|
|
28
|
+
- https://bugzilla.mozilla.org/11137353
|
|
29
|
+
data_reviews:
|
|
30
|
+
- http://example.com/reviews
|
|
31
|
+
notification_emails:
|
|
32
|
+
- CHANGE-ME@example.com
|
|
33
|
+
expires: 2100-01-01
|
|
34
|
+
|
|
35
|
+
static_dynamic:
|
|
36
|
+
type: dual_labeled_counter
|
|
37
|
+
description: >
|
|
38
|
+
A dual labeled counter with static keys and dynamic categories
|
|
39
|
+
dual_labels:
|
|
40
|
+
key:
|
|
41
|
+
description: >
|
|
42
|
+
The key for the dual labeled counter
|
|
43
|
+
labels:
|
|
44
|
+
- key1
|
|
45
|
+
- key2
|
|
46
|
+
category:
|
|
47
|
+
description: >
|
|
48
|
+
The category for the dual labeled counter
|
|
49
|
+
bugs:
|
|
50
|
+
- https://bugzilla.mozilla.org/11137353
|
|
51
|
+
data_reviews:
|
|
52
|
+
- http://example.com/reviews
|
|
53
|
+
notification_emails:
|
|
54
|
+
- CHANGE-ME@example.com
|
|
55
|
+
expires: 2100-01-01
|
|
56
|
+
|
|
57
|
+
dynamic_static:
|
|
58
|
+
type: dual_labeled_counter
|
|
59
|
+
description: >
|
|
60
|
+
A dual labeled counter with dynamic keys and static categories
|
|
61
|
+
dual_labels:
|
|
62
|
+
key:
|
|
63
|
+
description: >
|
|
64
|
+
The key for the dual labeled counter
|
|
65
|
+
category:
|
|
66
|
+
description: >
|
|
67
|
+
The category for the dual labeled counter
|
|
68
|
+
labels:
|
|
69
|
+
- category1
|
|
70
|
+
- category2
|
|
71
|
+
bugs:
|
|
72
|
+
- https://bugzilla.mozilla.org/11137353
|
|
73
|
+
data_reviews:
|
|
74
|
+
- http://example.com/reviews
|
|
75
|
+
notification_emails:
|
|
76
|
+
- CHANGE-ME@example.com
|
|
77
|
+
expires: 2100-01-01
|
|
78
|
+
|
|
79
|
+
dynamic_dynamic:
|
|
80
|
+
type: dual_labeled_counter
|
|
81
|
+
description: >
|
|
82
|
+
A dual labeled counter with dynamic keys and dynamic categories
|
|
83
|
+
dual_labels:
|
|
84
|
+
key:
|
|
85
|
+
description: >
|
|
86
|
+
The key for the dual labeled counter
|
|
87
|
+
category:
|
|
88
|
+
description: >
|
|
89
|
+
The category for the dual labeled counter
|
|
90
|
+
bugs:
|
|
91
|
+
- https://bugzilla.mozilla.org/11137353
|
|
92
|
+
data_reviews:
|
|
93
|
+
- http://example.com/reviews
|
|
94
|
+
notification_emails:
|
|
95
|
+
- CHANGE-ME@example.com
|
|
96
|
+
expires: 2100-01-01
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# Any copyright is dedicated to the Public Domain.
|
|
2
|
+
# https://creativecommons.org/publicdomain/zero/1.0/
|
|
3
|
+
|
|
4
|
+
---
|
|
5
|
+
$schema: moz://mozilla.org/schemas/glean/metrics/2-0-0
|
|
6
|
+
|
|
7
|
+
no_lint: [EXPIRATION_DATE_TOO_FAR]
|
|
8
|
+
|
|
9
|
+
test.dual_labeled:
|
|
10
|
+
missing_key:
|
|
11
|
+
type: dual_labeled_counter
|
|
12
|
+
description: >
|
|
13
|
+
A dual labeled counter with missing `key` property of `dual_labels`
|
|
14
|
+
dual_labels:
|
|
15
|
+
category:
|
|
16
|
+
description: >
|
|
17
|
+
The category for the dual labeled counter
|
|
18
|
+
labels:
|
|
19
|
+
- category1
|
|
20
|
+
- category2
|
|
21
|
+
bugs:
|
|
22
|
+
- https://bugzilla.mozilla.org/11137353
|
|
23
|
+
data_reviews:
|
|
24
|
+
- http://example.com/reviews
|
|
25
|
+
notification_emails:
|
|
26
|
+
- CHANGE-ME@example.com
|
|
27
|
+
expires: 2100-01-01
|
|
28
|
+
|
|
29
|
+
missing_category:
|
|
30
|
+
type: dual_labeled_counter
|
|
31
|
+
description: >
|
|
32
|
+
A dual labeled counter with missing `category` property of `dual_labels`
|
|
33
|
+
dual_labels:
|
|
34
|
+
key:
|
|
35
|
+
description: >
|
|
36
|
+
The key for the dual labeled counter
|
|
37
|
+
labels:
|
|
38
|
+
- key1
|
|
39
|
+
- key2
|
|
40
|
+
bugs:
|
|
41
|
+
- https://bugzilla.mozilla.org/11137353
|
|
42
|
+
data_reviews:
|
|
43
|
+
- http://example.com/reviews
|
|
44
|
+
notification_emails:
|
|
45
|
+
- CHANGE-ME@example.com
|
|
46
|
+
expires: 2100-01-01
|
|
47
|
+
|
|
48
|
+
missing_dual_labels:
|
|
49
|
+
type: dual_labeled_counter
|
|
50
|
+
description: >
|
|
51
|
+
A dual labeled counter with missing `dual_labels` property
|
|
52
|
+
bugs:
|
|
53
|
+
- https://bugzilla.mozilla.org/11137353
|
|
54
|
+
data_reviews:
|
|
55
|
+
- http://example.com/reviews
|
|
56
|
+
notification_emails:
|
|
57
|
+
- CHANGE-ME@example.com
|
|
58
|
+
expires: 2100-01-01
|
|
59
|
+
|
|
60
|
+
missing_key_and_category:
|
|
61
|
+
type: dual_labeled_counter
|
|
62
|
+
description: >
|
|
63
|
+
A dual labeled counter with missing both `key` and `category` properties
|
|
64
|
+
dual_labels:
|
|
65
|
+
foo: bar
|
|
66
|
+
bugs:
|
|
67
|
+
- https://bugzilla.mozilla.org/11137353
|
|
68
|
+
data_reviews:
|
|
69
|
+
- http://example.com/reviews
|
|
70
|
+
notification_emails:
|
|
71
|
+
- CHANGE-ME@example.com
|
|
72
|
+
expires: 2100-01-01
|