glean-parser 17.0.1__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.0.1/docs/readme.md → glean_parser-17.2.0/PKG-INFO +30 -11
- {glean_parser-17.0.1 → glean_parser-17.2.0}/README.md +1 -11
- {glean_parser-17.0.1 → glean_parser-17.2.0}/glean_parser/lint.py +28 -9
- {glean_parser-17.0.1 → glean_parser-17.2.0}/glean_parser/metrics.py +56 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/glean_parser/parser.py +70 -30
- {glean_parser-17.0.1 → glean_parser-17.2.0}/glean_parser/rust.py +2 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/glean_parser/schemas/metrics.2-0-0.schema.yaml +65 -11
- {glean_parser-17.0.1 → glean_parser-17.2.0}/glean_parser/templates/rust.jinja2 +15 -2
- {glean_parser-17.0.1 → glean_parser-17.2.0}/glean_parser/util.py +9 -1
- glean_parser-17.2.0/pyproject.toml +76 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/tests/data/all_metrics.yaml +15 -0
- glean_parser-17.2.0/tests/data/attribution.yaml +93 -0
- glean_parser-17.2.0/tests/data/bad_attribution.yamlx +36 -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/reserved_categories.yamlx +33 -0
- glean_parser-17.2.0/tests/data/same_name_different_category.yaml +32 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/tests/test_lint.py +52 -4
- {glean_parser-17.0.1 → glean_parser-17.2.0}/tests/test_parser.py +106 -5
- {glean_parser-17.0.1 → glean_parser-17.2.0}/tests/test_rust.py +48 -0
- glean_parser-17.0.1/.circleci/config.yml +0 -271
- glean_parser-17.0.1/.editorconfig +0 -21
- glean_parser-17.0.1/.github/CODEOWNERS +0 -12
- glean_parser-17.0.1/.github/ISSUE_TEMPLATE.md +0 -15
- glean_parser-17.0.1/.github/dependabot.yml +0 -6
- glean_parser-17.0.1/.github/pull_request_template.md +0 -8
- glean_parser-17.0.1/.swiftlint.yml +0 -6
- glean_parser-17.0.1/CHANGELOG.md +0 -816
- glean_parser-17.0.1/CODE_OF_CONDUCT.md +0 -15
- glean_parser-17.0.1/CONTRIBUTING.md +0 -189
- glean_parser-17.0.1/MANIFEST.in +0 -14
- glean_parser-17.0.1/Makefile +0 -79
- glean_parser-17.0.1/PKG-INFO +0 -893
- glean_parser-17.0.1/docs/Makefile +0 -20
- glean_parser-17.0.1/docs/_static/glean.jpeg +0 -0
- glean_parser-17.0.1/docs/authors.md +0 -17
- glean_parser-17.0.1/docs/conf.py +0 -160
- glean_parser-17.0.1/docs/contributing.md +0 -189
- glean_parser-17.0.1/docs/history.md +0 -816
- glean_parser-17.0.1/docs/index.rst +0 -27
- glean_parser-17.0.1/docs/installation.md +0 -41
- glean_parser-17.0.1/docs/make.bat +0 -36
- glean_parser-17.0.1/docs/metrics-yaml.rst +0 -13
- glean_parser-17.0.1/docs/pings-yaml.rst +0 -13
- glean_parser-17.0.1/docs/tags-yaml.rst +0 -13
- glean_parser-17.0.1/glean_parser.egg-info/PKG-INFO +0 -893
- glean_parser-17.0.1/glean_parser.egg-info/SOURCES.txt +0 -170
- glean_parser-17.0.1/glean_parser.egg-info/dependency_links.txt +0 -1
- glean_parser-17.0.1/glean_parser.egg-info/entry_points.txt +0 -2
- glean_parser-17.0.1/glean_parser.egg-info/not-zip-safe +0 -1
- glean_parser-17.0.1/glean_parser.egg-info/requires.txt +0 -6
- glean_parser-17.0.1/glean_parser.egg-info/top_level.txt +0 -1
- glean_parser-17.0.1/pytest.ini +0 -7
- glean_parser-17.0.1/requirements_dev.txt +0 -13
- glean_parser-17.0.1/setup.cfg +0 -10
- glean_parser-17.0.1/setup.py +0 -77
- glean_parser-17.0.1/tools/extract_data_categories.py +0 -176
- {glean_parser-17.0.1 → glean_parser-17.2.0}/.gitignore +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/AUTHORS.md +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/LICENSE +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/glean_parser/__init__.py +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/glean_parser/__main__.py +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/glean_parser/coverage.py +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/glean_parser/data_review.py +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/glean_parser/go_server.py +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/glean_parser/javascript.py +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/glean_parser/javascript_server.py +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/glean_parser/kotlin.py +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/glean_parser/markdown.py +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/glean_parser/pings.py +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/glean_parser/python_server.py +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/glean_parser/ruby_server.py +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/glean_parser/rust_server.py +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/glean_parser/schemas/metrics.1-0-0.schema.yaml +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/glean_parser/schemas/pings.1-0-0.schema.yaml +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/glean_parser/schemas/pings.2-0-0.schema.yaml +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/glean_parser/schemas/tags.1-0-0.schema.yaml +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/glean_parser/swift.py +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/glean_parser/tags.py +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/glean_parser/templates/data_review.jinja2 +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/glean_parser/templates/go_server.jinja2 +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/glean_parser/templates/javascript.buildinfo.jinja2 +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/glean_parser/templates/javascript.jinja2 +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/glean_parser/templates/javascript_server.jinja2 +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/glean_parser/templates/kotlin.buildinfo.jinja2 +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/glean_parser/templates/kotlin.jinja2 +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/glean_parser/templates/markdown.jinja2 +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/glean_parser/templates/python_server.jinja2 +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/glean_parser/templates/qmldir.jinja2 +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/glean_parser/templates/ruby_server.jinja2 +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/glean_parser/templates/rust_server.jinja2 +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/glean_parser/templates/swift.jinja2 +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/glean_parser/translate.py +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/glean_parser/translation_options.py +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/glean_parser/validate_ping.py +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/server_telemetry/sdk-metrics-compat.yaml +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/server_telemetry/server-side-pings.yaml +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/tests/conftest.py +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/tests/data/all_pings.yaml +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/tests/data/bad_ping.yamlx +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/tests/data/core.yaml +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/tests/data/duplicate_labeled.yaml +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/tests/data/duplicate_send_in_ping.yaml +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/tests/data/empty.yaml +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/tests/data/event_key_ordering.yaml +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/tests/data/events_with_types.yaml +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/tests/data/fxa-server-metrics.yaml +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/tests/data/fxa-server-pings.yaml +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/tests/data/go_server_custom_ping_only_metrics.yaml +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/tests/data/go_server_custom_ping_only_pings.yaml +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/tests/data/go_server_events_and_custom_ping_metrics.yaml +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/tests/data/go_server_events_and_custom_ping_pings.yaml +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/tests/data/go_server_events_only_metrics.yaml +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/tests/data/go_server_metrics_unsupported.yaml +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/tests/data/invalid-ping-names.yaml +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/tests/data/invalid.yamlx +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/tests/data/jwe.yaml +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/tests/data/metric-with-tags.yaml +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/tests/data/mixed-expirations.yaml +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/tests/data/name_too_similar.yaml +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/tests/data/object.yaml +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/tests/data/old_event_api.yamlx +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/tests/data/ordering.yaml +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/tests/data/pings.yaml +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/tests/data/rate.yaml +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/tests/data/ruby_server_metrics_unsupported.yaml +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/tests/data/ruby_server_pings_unsupported.yaml +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/tests/data/rust_server_custom_ping_only_metrics.yaml +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/tests/data/rust_server_custom_ping_only_pings.yaml +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/tests/data/rust_server_events_and_custom_ping_metrics.yaml +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/tests/data/rust_server_events_and_custom_ping_pings.yaml +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/tests/data/rust_server_events_only_metrics.yaml +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/tests/data/rust_server_metrics_unsupported.yaml +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/tests/data/schema-violation.yaml +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/tests/data/send_if_empty_with_metrics.yaml +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/tests/data/server_custom_ping_only_compare.go +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/tests/data/server_custom_ping_only_compare.rs +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/tests/data/server_events_and_custom_ping_compare.go +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/tests/data/server_events_and_custom_ping_compare.rs +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/tests/data/server_events_compare.rb +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/tests/data/server_events_only_compare.go +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/tests/data/server_events_only_compare.rs +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/tests/data/server_metrics_no_events_no_pings.yaml +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/tests/data/server_metrics_with_event.yaml +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/tests/data/server_pings.yaml +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/tests/data/single_labeled.yaml +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/tests/data/smaller.yaml +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/tests/data/tags.yaml +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/tests/data/telemetry_mirror.yaml +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/tests/data/text.yaml +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/tests/data/text_invalid.yaml +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/tests/data/unknown_ping_used.yaml +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/tests/data/wrong_key.yamlx +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/tests/data/yaml_nits.yamlx +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/tests/detekt.yml +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/tests/test-go/test.go.tmpl +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/tests/test-js/package.json +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/tests/test-js/test.js.tmpl +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/tests/test-py/test.py +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/tests/test-rb/test.rb.tmpl +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/tests/test-rs/test.rs.tmpl +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/tests/test_cli.py +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/tests/test_go_server.py +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/tests/test_javascript.py +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/tests/test_javascript_server.py +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/tests/test_kotlin.py +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/tests/test_markdown.py +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/tests/test_metrics.py +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/tests/test_pings.py +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/tests/test_python_server.py +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/tests/test_ruby_server.py +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/tests/test_rust_server.py +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/tests/test_swift.py +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/tests/test_tags.py +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/tests/test_translate.py +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/tests/test_utils.py +0 -0
- {glean_parser-17.0.1 → glean_parser-17.2.0}/tests/test_validate_ping.py +0 -0
- {glean_parser-17.0.1 → 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
|
|
|
@@ -134,7 +134,6 @@ def check_unit_in_name(
|
|
|
134
134
|
|
|
135
135
|
time_unit = getattr(metric, "time_unit", None)
|
|
136
136
|
memory_unit = getattr(metric, "memory_unit", None)
|
|
137
|
-
unit = getattr(metric, "unit", None)
|
|
138
137
|
|
|
139
138
|
if time_unit is not None:
|
|
140
139
|
if (
|
|
@@ -175,14 +174,6 @@ def check_unit_in_name(
|
|
|
175
174
|
"Confirm the unit is correct and only include memory_unit."
|
|
176
175
|
)
|
|
177
176
|
|
|
178
|
-
elif unit is not None:
|
|
179
|
-
if unit_in_name == unit:
|
|
180
|
-
yield (
|
|
181
|
-
f"Suffix '{unit_in_name}' is redundant with unit param "
|
|
182
|
-
f"'{unit}'. "
|
|
183
|
-
"Only include unit."
|
|
184
|
-
)
|
|
185
|
-
|
|
186
177
|
|
|
187
178
|
def check_category_generic(
|
|
188
179
|
category_name: str, metrics: Iterable[metrics.Metric]
|
|
@@ -581,6 +572,20 @@ def lint_metrics(
|
|
|
581
572
|
|
|
582
573
|
nits.extend(_lint_all_objects(objs, parser_config))
|
|
583
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
|
+
|
|
584
589
|
for category_name, category in sorted(list(objs.items())):
|
|
585
590
|
if category_name == "pings":
|
|
586
591
|
nits.extend(_lint_pings(category, parser_config, valid_tag_names))
|
|
@@ -590,6 +595,20 @@ def lint_metrics(
|
|
|
590
595
|
# currently we have no linting for tags
|
|
591
596
|
continue
|
|
592
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
|
+
|
|
593
612
|
# Make sure the category has only Metrics, not Pings or Tags
|
|
594
613
|
category_metrics = dict(
|
|
595
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,25 +182,42 @@ 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
|
|
188
192
|
if category_key == "no_lint":
|
|
189
193
|
continue
|
|
190
194
|
if not config.get("allow_reserved") and category_key.split(".")[0] == "glean":
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
195
|
+
if category_key not in ("glean.attribution", "glean.distribution"):
|
|
196
|
+
yield util.format_error(
|
|
197
|
+
filepath,
|
|
198
|
+
f"For category '{category_key}'",
|
|
199
|
+
"Categories beginning with 'glean' are reserved for "
|
|
200
|
+
"Glean internal use.",
|
|
201
|
+
)
|
|
202
|
+
continue
|
|
198
203
|
all_objects.setdefault(category_key, DictWrapper())
|
|
199
204
|
|
|
200
205
|
if not isinstance(category_val, dict):
|
|
201
206
|
raise TypeError(f"Invalid content for {category_key}")
|
|
202
207
|
|
|
203
208
|
for metric_key, metric_val in sorted(category_val.items()):
|
|
209
|
+
if (
|
|
210
|
+
not config.get("allow_reserved")
|
|
211
|
+
and category_key in ("glean.attribution", "glean.distribution")
|
|
212
|
+
and metric_key != "ext"
|
|
213
|
+
):
|
|
214
|
+
yield util.format_error(
|
|
215
|
+
filepath,
|
|
216
|
+
f"For {category_key}.{metric_key}",
|
|
217
|
+
f"May only use semi-reserved category {category_key} with metric name 'ext'",
|
|
218
|
+
metric_val.defined_in["line"],
|
|
219
|
+
)
|
|
220
|
+
continue
|
|
204
221
|
try:
|
|
205
222
|
metric_obj = Metric.make_metric(
|
|
206
223
|
category_key, metric_key, metric_val, validated=True, config=config
|
|
@@ -214,18 +231,28 @@ def _instantiate_metrics(
|
|
|
214
231
|
)
|
|
215
232
|
metric_obj = None
|
|
216
233
|
else:
|
|
217
|
-
if (
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
234
|
+
if not config.get("allow_reserved"):
|
|
235
|
+
if "all-pings" in metric_obj.send_in_pings:
|
|
236
|
+
yield util.format_error(
|
|
237
|
+
filepath,
|
|
238
|
+
f"On instance {category_key}.{metric_key}",
|
|
239
|
+
'Only internal metrics may specify "all-pings" '
|
|
240
|
+
'in "send_in_pings"',
|
|
241
|
+
metric_val.defined_in["line"],
|
|
242
|
+
)
|
|
243
|
+
metric_obj = None
|
|
244
|
+
elif (
|
|
245
|
+
metric_obj.identifier()
|
|
246
|
+
in ("glean.attribution.ext", "glean.distribution.ext")
|
|
247
|
+
and metric_obj.type != "object"
|
|
248
|
+
):
|
|
249
|
+
yield util.format_error(
|
|
250
|
+
filepath,
|
|
251
|
+
f"On instance {category_key}.{metric_key}",
|
|
252
|
+
"Extended attribution/distribution metrics must be of type 'object'",
|
|
253
|
+
metric_val.defined_in["line"],
|
|
254
|
+
)
|
|
255
|
+
metric_obj = None
|
|
229
256
|
|
|
230
257
|
if metric_obj is not None:
|
|
231
258
|
metric_obj.no_lint = sorted(set(metric_obj.no_lint + global_no_lint))
|
|
@@ -250,6 +277,12 @@ def _instantiate_metrics(
|
|
|
250
277
|
metric_obj.defined_in["line"],
|
|
251
278
|
)
|
|
252
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
|
+
)
|
|
253
286
|
all_objects[category_key][metric_key] = metric_obj
|
|
254
287
|
sources[(category_key, metric_key)] = filepath
|
|
255
288
|
|
|
@@ -269,6 +302,15 @@ def _instantiate_pings(
|
|
|
269
302
|
assert isinstance(global_no_lint, list)
|
|
270
303
|
ping_schedule_reverse_map: Dict[str, Set[str]] = dict()
|
|
271
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
|
+
|
|
272
314
|
for ping_key, ping_val in sorted(content.items()):
|
|
273
315
|
if ping_key.startswith("$"):
|
|
274
316
|
continue
|
|
@@ -321,8 +363,7 @@ def _instantiate_pings(
|
|
|
321
363
|
yield util.format_error(
|
|
322
364
|
filepath,
|
|
323
365
|
"",
|
|
324
|
-
f"Duplicate ping name '{ping_key}' "
|
|
325
|
-
f"already defined in '{already_seen}'",
|
|
366
|
+
f"Duplicate ping name '{ping_key}' already defined in '{already_seen}'",
|
|
326
367
|
)
|
|
327
368
|
else:
|
|
328
369
|
all_objects.setdefault("pings", {})[ping_key] = ping_obj
|
|
@@ -380,8 +421,7 @@ def _instantiate_tags(
|
|
|
380
421
|
yield util.format_error(
|
|
381
422
|
filepath,
|
|
382
423
|
"",
|
|
383
|
-
f"Duplicate tag name '{tag_key}' "
|
|
384
|
-
f"already defined in '{already_seen}'",
|
|
424
|
+
f"Duplicate tag name '{tag_key}' already defined in '{already_seen}'",
|
|
385
425
|
)
|
|
386
426
|
else:
|
|
387
427
|
all_objects.setdefault("tags", {})[tag_key] = tag_obj
|
|
@@ -481,16 +521,16 @@ def parse_objects(
|
|
|
481
521
|
raise TypeError(f"Invalid content for {filepath}")
|
|
482
522
|
|
|
483
523
|
for category_key, category_val in sorted(content.items()):
|
|
484
|
-
|
|
485
|
-
|
|
524
|
+
if category_key.startswith("$"):
|
|
525
|
+
continue
|
|
486
526
|
|
|
487
|
-
|
|
527
|
+
interesting_metrics_dict.setdefault(category_key, DictWrapper())
|
|
488
528
|
|
|
489
|
-
|
|
490
|
-
|
|
529
|
+
if not isinstance(category_val, dict):
|
|
530
|
+
raise TypeError(f"Invalid category_val for {category_key}")
|
|
491
531
|
|
|
492
|
-
|
|
493
|
-
|
|
532
|
+
for metric_key, metric_val in sorted(category_val.items()):
|
|
533
|
+
interesting_metrics_dict[category_key][metric_key] = metric_val
|
|
494
534
|
|
|
495
535
|
for category_key, category_val in all_objects.items():
|
|
496
536
|
if category_key == "tags":
|
|
@@ -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
|
|
@@ -565,7 +619,7 @@ definitions:
|
|
|
565
619
|
Use is limited to Firefox Desktop only.
|
|
566
620
|
Has no effect when used with non-FOG outputters.
|
|
567
621
|
See FOG's documentation on mirroring for details -
|
|
568
|
-
https://firefox-source-docs.mozilla.org/toolkit/components/glean/
|
|
622
|
+
https://firefox-source-docs.mozilla.org/toolkit/components/glean/user/gifft.html
|
|
569
623
|
type: string
|
|
570
624
|
minLength: 6
|
|
571
625
|
|
|
@@ -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
|