forked from mirrors/gecko-dev
Bug 1626969 - Include locale in Glean pings.r=chutten,supply-chain-reviewers
Differential Revision: https://phabricator.services.mozilla.com/D185153
This commit is contained in:
parent
ba2e07af4d
commit
aa6cb926b7
45 changed files with 616 additions and 285 deletions
8
Cargo.lock
generated
8
Cargo.lock
generated
|
|
@ -2235,9 +2235,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "glean"
|
||||
version = "53.1.0"
|
||||
version = "53.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0efbf048a79e634cd5ccd224f972018e3f217c72d4071bbe6ebee382037bffcb"
|
||||
checksum = "df470f5f41c8fc6113bd48fa18e0f1a8193e1e2b1f3942f8255b064e60db42ff"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"crossbeam-channel",
|
||||
|
|
@ -2255,9 +2255,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "glean-core"
|
||||
version = "53.1.0"
|
||||
version = "53.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "826ac72df83806896eda459414972a0ca288d4d206811fd10a8a00a581b85498"
|
||||
checksum = "6f72ce41516d772676db57c87fee1c99545bbda4b430793f24d0c81918cfbd8a"
|
||||
dependencies = [
|
||||
"android_logger",
|
||||
"bincode",
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ allprojects {
|
|||
topsrcdir = gradle.mozconfig.topsrcdir
|
||||
topobjdir = gradle.mozconfig.topobjdir
|
||||
|
||||
gleanVersion = "53.1.0"
|
||||
gleanVersion = "53.2.0"
|
||||
if (gleanVersion != getRustVersionFor("glean")) {
|
||||
throw new StopExecutionException("Mismatched Glean version, expected: ${gleanVersion}," +
|
||||
" found ${getRustVersionFor("glean")}")
|
||||
|
|
|
|||
8
gfx/wr/Cargo.lock
generated
8
gfx/wr/Cargo.lock
generated
|
|
@ -987,9 +987,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "glean"
|
||||
version = "53.1.0"
|
||||
version = "53.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0efbf048a79e634cd5ccd224f972018e3f217c72d4071bbe6ebee382037bffcb"
|
||||
checksum = "df470f5f41c8fc6113bd48fa18e0f1a8193e1e2b1f3942f8255b064e60db42ff"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"crossbeam-channel",
|
||||
|
|
@ -1007,9 +1007,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "glean-core"
|
||||
version = "53.1.0"
|
||||
version = "53.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "826ac72df83806896eda459414972a0ca288d4d206811fd10a8a00a581b85498"
|
||||
checksum = "6f72ce41516d772676db57c87fee1c99545bbda4b430793f24d0c81918cfbd8a"
|
||||
dependencies = [
|
||||
"android_logger",
|
||||
"bincode",
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ svg_fmt = "0.4"
|
|||
tracy-rs = "0.1.2"
|
||||
derive_more = { version = "0.99", default-features = false, features = ["add_assign"] }
|
||||
etagere = "0.2.6"
|
||||
glean = "53.1.0"
|
||||
glean = "53.2.0"
|
||||
firefox-on-glean = { version = "0.1.0", optional = true }
|
||||
swgl = { path = "../swgl", optional = true }
|
||||
topological-sort = "0.1"
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ tracy-rs = "0.1.2"
|
|||
log = "0.4"
|
||||
lazy_static = "1"
|
||||
fxhash = "0.2.1"
|
||||
glean = { version = "53.1.0", optional = true }
|
||||
glean = { version = "53.2.0", optional = true }
|
||||
firefox-on-glean = { version = "0.1.0", optional = true }
|
||||
serde = { optional = true, version = "1.0", features = ["serde_derive"] }
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,8 @@
|
|||
|
||||
Classes = [
|
||||
{
|
||||
'js_name': 'locale',
|
||||
'name': 'Locale',
|
||||
'js_name': 'locale',
|
||||
'cid': '{92735ff4-6384-4ad6-8508-757010e149ee}',
|
||||
'contract_ids': ['@mozilla.org/intl/localeservice;1'],
|
||||
'interfaces': ['mozILocaleService'],
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@ vendored:third_party/python/wheel
|
|||
vendored:third_party/python/zipp
|
||||
# glean-sdk may not be installable if a wheel isn't available
|
||||
# and it has to be built from source.
|
||||
pypi-optional:glean-sdk==53.1.0:telemetry will not be collected
|
||||
pypi-optional:glean-sdk==53.2.0:telemetry will not be collected
|
||||
# Mach gracefully handles the case where `psutil` is unavailable.
|
||||
# We aren't (yet) able to pin packages in automation, so we have to
|
||||
# support down to the oldest locally-installed version (5.4.2).
|
||||
|
|
|
|||
|
|
@ -191,15 +191,15 @@ user-login = "jrmuizel"
|
|||
user-name = "Jeff Muizelaar"
|
||||
|
||||
[[publisher.glean]]
|
||||
version = "53.1.0"
|
||||
when = "2023-06-28"
|
||||
version = "53.2.0"
|
||||
when = "2023-08-02"
|
||||
user-id = 48
|
||||
user-login = "badboy"
|
||||
user-name = "Jan-Erik Rediger"
|
||||
|
||||
[[publisher.glean-core]]
|
||||
version = "53.1.0"
|
||||
when = "2023-06-28"
|
||||
version = "53.2.0"
|
||||
when = "2023-08-02"
|
||||
user-id = 48
|
||||
user-login = "badboy"
|
||||
user-name = "Jan-Erik Rediger"
|
||||
|
|
@ -1233,3 +1233,15 @@ criteria = "safe-to-deploy"
|
|||
version = "1.4.0"
|
||||
notes = "I have read over the macros, and audited the unsafe code."
|
||||
aggregated-from = "https://raw.githubusercontent.com/mozilla/cargo-vet/main/supply-chain/audits.toml"
|
||||
|
||||
[[audits.mozilla.audits.time]]
|
||||
who = "Kershaw Chang <kershaw@mozilla.com>"
|
||||
criteria = "safe-to-deploy"
|
||||
delta = "0.1.45 -> 0.3.17"
|
||||
aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml"
|
||||
|
||||
[[audits.mozilla.audits.time-macros]]
|
||||
who = "Kershaw Chang <kershaw@mozilla.com>"
|
||||
criteria = "safe-to-deploy"
|
||||
version = "0.2.6"
|
||||
aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml"
|
||||
|
|
|
|||
|
|
@ -1,13 +1,11 @@
|
|||
Metadata-Version: 2.1
|
||||
Name: glean-parser
|
||||
Version: 7.2.1
|
||||
Version: 8.1.0
|
||||
Summary: Parser tools for Mozilla's Glean telemetry
|
||||
Home-page: https://github.com/mozilla/glean_parser
|
||||
Author: The Glean Team
|
||||
Author-email: glean-team@mozilla.com
|
||||
License: UNKNOWN
|
||||
Keywords: glean_parser
|
||||
Platform: UNKNOWN
|
||||
Classifier: Development Status :: 5 - Production/Stable
|
||||
Classifier: Intended Audience :: Developers
|
||||
Classifier: Natural Language :: English
|
||||
|
|
@ -19,6 +17,8 @@ Classifier: Programming Language :: Python :: 3.9
|
|||
Classifier: Programming Language :: Python :: 3.10
|
||||
Classifier: Programming Language :: Python :: 3.11
|
||||
Description-Content-Type: text/markdown
|
||||
License-File: LICENSE
|
||||
License-File: AUTHORS.md
|
||||
Requires-Dist: appdirs (>=1.4)
|
||||
Requires-Dist: Click (>=7)
|
||||
Requires-Dist: diskcache (>=4)
|
||||
|
|
@ -86,6 +86,17 @@ $ glean_parser check < ping.json
|
|||
|
||||
## Unreleased
|
||||
|
||||
## 8.1.0
|
||||
|
||||
- Increased the maximum metric name length in version 2.0.0 schema ([#596](https://github.com/mozilla/glean_parser/pull/596))
|
||||
|
||||
## 8.0.0
|
||||
|
||||
- BREAKING CHANGE: Remove exposed `lint_yaml_files` function ([#580](https://github.com/mozilla/glean_parser/pull/580))
|
||||
- Rust: Removed `__glean_metric_maps` from the Rust Jinja template. This functionality is better placed downstream ([Bug 1816526](https://bugzilla.mozilla.org/show_bug.cgi?id=1816526))
|
||||
- New lint: check that all referenced pings are known ([#584](https://github.com/mozilla/glean_parser/pull/584))
|
||||
- Add experimental server-side JavaScript outputter ([FXA-7922](https://mozilla-hub.atlassian.net/browse/FXA-7922))
|
||||
|
||||
## 7.2.1
|
||||
|
||||
- Unbreak last minor release ([#579](https://github.com/mozilla/glean_parser/pull/579))
|
||||
|
|
@ -722,5 +733,3 @@ $ glean_parser check < ping.json
|
|||
## 0.1.0 (2018-10-15)
|
||||
|
||||
- First release on PyPI.
|
||||
|
||||
|
||||
|
|
@ -3,38 +3,40 @@ glean_parser/__main__.py,sha256=7kIBMO-kL7boJxYrKp3CkRr4xX4_ct4BqCiCvtg2jjU,8631
|
|||
glean_parser/coverage.py,sha256=2IwC4XMDtDamMkBFoYilmqJzW4gyypq65YVCur8SNas,4405
|
||||
glean_parser/data_review.py,sha256=BweeeTkNNS6HrIDkztawhbDByrk_-Avxpg7YeST3VAs,2152
|
||||
glean_parser/javascript.py,sha256=w4ZhNBHBKWYk0h3t7G0Ud2tR__hRqzn9dlEXNKLdQrA,11230
|
||||
glean_parser/javascript_server.py,sha256=a-mpoSZ_ZnDWtRGKIVxH6NxSUST42yP9vJU85kQcRKE,6004
|
||||
glean_parser/kotlin.py,sha256=5z8_74xlqvHDsedwZhGf1_qb7swPEgIZumkJIuj3ef8,12598
|
||||
glean_parser/lint.py,sha256=A21ZKb9WSrgug6t8q1YHvXUxlB198xrkmZ26HCUDSlE,16303
|
||||
glean_parser/lint.py,sha256=Ik8n_L4HERuHk0kU83N8fjdQ1avE3wKi0WgkAf-c5hk,18248
|
||||
glean_parser/markdown.py,sha256=GkCr1CrV6mnRQseT6FO1-JJ7Eup8X3lxUfRMBTxXpe4,9066
|
||||
glean_parser/metrics.py,sha256=CSad9CbUWKF771Z82LhBAFAL9uXum0ycRwIHtl_i91E,12384
|
||||
glean_parser/metrics.py,sha256=2IuTEN8bNUEDwwS0kSXW-nEf040LvycTMY9Zg0Rr1m4,12431
|
||||
glean_parser/parser.py,sha256=cUOnvSXKfEBg8YTpRcWiPcMwpFpK1TTqsVO_zjUtpR4,15309
|
||||
glean_parser/pings.py,sha256=yh_DzRAI9k2_NiCIlpQiNg-ggVrttB4hk7gwtKlr72s,2815
|
||||
glean_parser/rust.py,sha256=PJzTfYWzAumJYCP5IYPc6fhS_Qa30Q8NTK9plg3sDnk,6744
|
||||
glean_parser/swift.py,sha256=T1BSGahd9wUd6VDeNC89SdN6M34jKXDlydMpSI0QLOs,8379
|
||||
glean_parser/tags.py,sha256=bemKYvcbMO4JrghiNSe-A4BNNDtx_FlUPkgrPPJy84Y,1391
|
||||
glean_parser/translate.py,sha256=S_a4PMXt3PyD7Wg35OM4xHEwPraqkcJzm_w95IEegPU,7962
|
||||
glean_parser/translate.py,sha256=Z28qdCFXKKT6ILu4FQEO6PfJ6Ia8MCFYYP2ArgK4mF8,8148
|
||||
glean_parser/translation_options.py,sha256=Lxzr6G7MP0tC_ZYlZXftS4j0SLiqO-5mGVTEc7ggXis,2037
|
||||
glean_parser/util.py,sha256=Hei33QDq4a_lIHp5j98KovN6C7tmLrvVamEX2a1DcTo,16825
|
||||
glean_parser/validate_ping.py,sha256=0TNvILH6dtzJDys3W8Kqorw6kk03me73OCUDtpoHcXU,2118
|
||||
glean_parser/schemas/metrics.1-0-0.schema.yaml,sha256=cND3cvi6iBfPUVmtfIBQfGJV9AALpbvN7nu8E33_J-o,19566
|
||||
glean_parser/schemas/metrics.2-0-0.schema.yaml,sha256=SOgqMzRs9QxyCBhjZwUhzlryeNLeaVAKMTwggG7XtQk,23843
|
||||
glean_parser/schemas/metrics.2-0-0.schema.yaml,sha256=wAlXT7hKZDzF1P8yyIftkmIhrcRhJ1XEjZV0FUTIks8,25849
|
||||
glean_parser/schemas/pings.1-0-0.schema.yaml,sha256=hwCnsKpEysmrmVp-QHGBArEkVY3vaU1rVsxlTwhAzws,4315
|
||||
glean_parser/schemas/pings.2-0-0.schema.yaml,sha256=rD1s-rfz1xC9biHyLfBCnsoQxVYHwpe_S05awfe2xDA,4363
|
||||
glean_parser/schemas/tags.1-0-0.schema.yaml,sha256=OGXIJlvvVW1vaqB_NVZnwKeZ-sLlfH57vjBSHbj6DNI,1231
|
||||
glean_parser/templates/data_review.jinja2,sha256=jeYU29T1zLSyu9fKBBFu5BFPfIw8_hmOUXw8RXhRXK8,3287
|
||||
glean_parser/templates/javascript.buildinfo.jinja2,sha256=4mXiZCQIk9if4lxlA05kpSIL4a95IdwGwqle2OqqNAs,474
|
||||
glean_parser/templates/javascript.jinja2,sha256=cT_bG-jC6m4afECXmcsqHwiiHjRuVtJnfv90OD2Mwxw,2669
|
||||
glean_parser/templates/javascript_server.jinja2,sha256=0kVF0yrVpNs1WnNlIAyuJVFS0QzasBD7J5Z0Blav_io,5246
|
||||
glean_parser/templates/kotlin.buildinfo.jinja2,sha256=X0lk2SNu5OIIj2i6mUyF9CWFQIonLgfqkgT5fA-5G6c,920
|
||||
glean_parser/templates/kotlin.geckoview.jinja2,sha256=MJOgtoDXmBjE9pwk-G6T89y36RZuMbDWM_-DBN_gFJo,5099
|
||||
glean_parser/templates/kotlin.jinja2,sha256=3DqUMXJRkmTvSp_5IRyvGmw5iXYWdox7coMFe3YDxcc,5247
|
||||
glean_parser/templates/markdown.jinja2,sha256=vAHHGGm28HRDPd3zO_wQMAUZIuxE9uQ7hl3NpXxcKV4,3425
|
||||
glean_parser/templates/qmldir.jinja2,sha256=m6IGsp-tgTiOfQ7VN8XW6GqX0gJqJkt3B6Pkaul6FVo,156
|
||||
glean_parser/templates/rust.jinja2,sha256=tznLKaZxi_Z9puGqDKD0uuWefZcVHiNdQHB4BP9zJfs,10797
|
||||
glean_parser/templates/rust.jinja2,sha256=tMuBBsC_96UC4-AMBFHpu9u5aojoArkP_hwnREfWNQU,3600
|
||||
glean_parser/templates/swift.jinja2,sha256=OsaEIlEdcOrUMvI_UzbxWv75lluTAWZGncH_pU-pbZQ,4809
|
||||
glean_parser-7.2.1.dist-info/AUTHORS.md,sha256=yxgj8MioO4wUnrh0gmfb8l3DJJrf-l4HmmEDbQsbbNI,455
|
||||
glean_parser-7.2.1.dist-info/LICENSE,sha256=HyVuytGSiAUQ6ErWBHTqt1iSGHhLmlC8fO7jTCuR8dU,16725
|
||||
glean_parser-7.2.1.dist-info/METADATA,sha256=6ZY8M4qK01Cz54nm4d9tOii3CBbW9lSaUSpHwUnm9JA,28275
|
||||
glean_parser-7.2.1.dist-info/WHEEL,sha256=pkctZYzUS4AYVn6dJ-7367OJZivF2e8RA9b_ZBjif18,92
|
||||
glean_parser-7.2.1.dist-info/entry_points.txt,sha256=s-clJTIqp-PpJD-n3AnIQZFkTafIrzsTbAPX9vNY018,69
|
||||
glean_parser-7.2.1.dist-info/top_level.txt,sha256=q7T3duD-9tYZFyDry6Wv2LcdMsK2jGnzdDFhxWcT2Z8,13
|
||||
glean_parser-7.2.1.dist-info/RECORD,,
|
||||
glean_parser-8.1.0.dist-info/AUTHORS.md,sha256=yxgj8MioO4wUnrh0gmfb8l3DJJrf-l4HmmEDbQsbbNI,455
|
||||
glean_parser-8.1.0.dist-info/LICENSE,sha256=HyVuytGSiAUQ6ErWBHTqt1iSGHhLmlC8fO7jTCuR8dU,16725
|
||||
glean_parser-8.1.0.dist-info/METADATA,sha256=u3C1jRfAODOsD1lxYfKoIGlTTTX6ud14p3Ohhrb0Zo4,28967
|
||||
glean_parser-8.1.0.dist-info/WHEEL,sha256=AtBG6SXL3KF_v0NxLf0ehyVOh0cold-JbJYXNGorC6Q,92
|
||||
glean_parser-8.1.0.dist-info/entry_points.txt,sha256=mf9d3sv8BwSjjR58x9KDnpVkONCnv3fPQC2NjJl15Xg,68
|
||||
glean_parser-8.1.0.dist-info/top_level.txt,sha256=q7T3duD-9tYZFyDry6Wv2LcdMsK2jGnzdDFhxWcT2Z8,13
|
||||
glean_parser-8.1.0.dist-info/RECORD,,
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
Wheel-Version: 1.0
|
||||
Generator: bdist_wheel (0.40.0)
|
||||
Generator: bdist_wheel (0.41.0)
|
||||
Root-Is-Purelib: true
|
||||
Tag: py3-none-any
|
||||
|
||||
|
|
@ -1,3 +1,2 @@
|
|||
[console_scripts]
|
||||
glean_parser = glean_parser.__main__:main_wrapper
|
||||
|
||||
162
third_party/python/glean_parser/glean_parser/javascript_server.py
vendored
Normal file
162
third_party/python/glean_parser/glean_parser/javascript_server.py
vendored
Normal file
|
|
@ -0,0 +1,162 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
# 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/.
|
||||
|
||||
"""
|
||||
Outputter to generate server Javascript code for collecting events.
|
||||
|
||||
This outputter is different from the rest of the outputters in that the code it
|
||||
generates does not use the Glean SDK. It is meant to be used to collect events
|
||||
using "events as pings" pattern in server-side environments. In these environments
|
||||
SDK assumptions to measurement window and connectivity don't hold.
|
||||
Generated code takes care of assembling pings with metrics, serializing to messages
|
||||
conforming to Glean schema, and logging with mozlog. Then it's the role of the ingestion
|
||||
pipeline to pick the messages up and process.
|
||||
|
||||
Warning: this outputter supports limited set of metrics,
|
||||
see `SUPPORTED_METRIC_TYPES` below.
|
||||
"""
|
||||
from collections import defaultdict
|
||||
from pathlib import Path
|
||||
from typing import Any, Dict, Optional, List
|
||||
|
||||
from . import __version__
|
||||
from . import metrics
|
||||
from . import util
|
||||
|
||||
# Adding a metric here will require updating the `generate_js_metric_type` function
|
||||
# and might require changes to the template.
|
||||
SUPPORTED_METRIC_TYPES = ["string"]
|
||||
|
||||
|
||||
def event_class_name(pingName: str) -> str:
|
||||
return util.Camelize(pingName) + "ServerEvent"
|
||||
|
||||
|
||||
def generate_metric_name(metric: metrics.Metric) -> str:
|
||||
return f"{metric.category}.{metric.name}"
|
||||
|
||||
|
||||
def generate_metric_argument_name(metric: metrics.Metric) -> str:
|
||||
return f"{metric.category}_{metric.name}"
|
||||
|
||||
|
||||
def generate_js_metric_type(metric: metrics.Metric) -> str:
|
||||
return metric.type
|
||||
|
||||
|
||||
def generate_metric_argument_description(metric: metrics.Metric) -> str:
|
||||
return metric.description.replace("\n", " ").rstrip()
|
||||
|
||||
|
||||
def generate_ping_factory_method(ping: str) -> str:
|
||||
return f"create{util.Camelize(ping)}Event"
|
||||
|
||||
|
||||
def output(
|
||||
lang: str,
|
||||
objs: metrics.ObjectTree,
|
||||
output_dir: Path,
|
||||
) -> None:
|
||||
"""
|
||||
Given a tree of objects, output Javascript or Typescript code to `output_dir`.
|
||||
|
||||
The output is a single file containing all the code for assembling pings with
|
||||
metrics, serializing, and submitting.
|
||||
|
||||
:param lang: Either "javascript" or "typescript";
|
||||
: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.
|
||||
"""
|
||||
|
||||
template = util.get_jinja2_template(
|
||||
"javascript_server.jinja2",
|
||||
filters=(
|
||||
("event_class_name", event_class_name),
|
||||
("metric_name", generate_metric_name),
|
||||
("metric_argument_name", generate_metric_argument_name),
|
||||
("js_metric_type", generate_js_metric_type),
|
||||
("metric_argument_description", generate_metric_argument_description),
|
||||
("factory_method", generate_ping_factory_method),
|
||||
),
|
||||
)
|
||||
|
||||
# In this environment we don't use a concept of measurement window for collecting
|
||||
# metrics. Only "events as pings" are supported.
|
||||
# For each ping we generate code which contains all the logic for assembling it
|
||||
# with metrics, serializing, and submitting. Therefore we don't generate classes for
|
||||
# each metric as in standard outputters.
|
||||
PING_METRIC_ERROR_MSG = (
|
||||
" Server-side environment is simplified and this"
|
||||
+ " parser doesn't generate individual metric files. Make sure to pass all"
|
||||
+ " your ping and metric definitions in a single invocation of the parser."
|
||||
)
|
||||
if "pings" not in objs:
|
||||
print("❌ No ping definition found." + PING_METRIC_ERROR_MSG)
|
||||
return
|
||||
|
||||
# Go through all metrics in objs and build a map of
|
||||
# ping->list of metric categories->list of metrics
|
||||
# for easier processing in the template.
|
||||
ping_to_metrics: Dict[str, Dict[str, List[metrics.Metric]]] = defaultdict(dict)
|
||||
for _category_key, category_val in objs.items():
|
||||
for _metric_name, metric in category_val.items():
|
||||
if isinstance(metric, metrics.Metric):
|
||||
if metric.type not in SUPPORTED_METRIC_TYPES:
|
||||
print(
|
||||
"❌ Ignoring unsupported metric type: "
|
||||
+ f"{metric.type}:{metric.name}."
|
||||
+ " Reach out to Glean team to add support for this"
|
||||
+ " metric type."
|
||||
)
|
||||
continue
|
||||
for ping in metric.send_in_pings:
|
||||
metrics_by_type = ping_to_metrics[ping]
|
||||
metrics_list = metrics_by_type.setdefault(metric.type, [])
|
||||
metrics_list.append(metric)
|
||||
|
||||
if not ping_to_metrics:
|
||||
print("❌ No pings with metrics found." + PING_METRIC_ERROR_MSG)
|
||||
return
|
||||
|
||||
extension = ".js" if lang == "javascript" else ".ts"
|
||||
filepath = output_dir / ("server_events" + extension)
|
||||
with filepath.open("w", encoding="utf-8") as fd:
|
||||
fd.write(
|
||||
template.render(
|
||||
parser_version=__version__,
|
||||
pings=ping_to_metrics,
|
||||
lang=lang,
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def output_javascript(
|
||||
objs: metrics.ObjectTree, output_dir: Path, options: Optional[Dict[str, Any]] = None
|
||||
) -> None:
|
||||
"""
|
||||
Given a tree of objects, output Javascript code to `output_dir`.
|
||||
|
||||
: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.
|
||||
"""
|
||||
|
||||
output("javascript", objs, output_dir)
|
||||
|
||||
|
||||
def output_typescript(
|
||||
objs: metrics.ObjectTree, output_dir: Path, options: Optional[Dict[str, Any]] = None
|
||||
) -> None:
|
||||
"""
|
||||
Given a tree of objects, output Typescript code to `output_dir`.
|
||||
|
||||
: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.
|
||||
"""
|
||||
|
||||
output("typescript", objs, output_dir)
|
||||
|
|
@ -27,8 +27,12 @@ from . import tags
|
|||
from . import util
|
||||
|
||||
|
||||
# Yield only an error message
|
||||
LintGenerator = Generator[str, None, None]
|
||||
|
||||
# Yield fully constructed GlinterNits
|
||||
NitGenerator = Generator["GlinterNit", None, None]
|
||||
|
||||
|
||||
class CheckType(enum.Enum):
|
||||
warning = 0
|
||||
|
|
@ -304,6 +308,40 @@ def check_redundant_ping(
|
|||
yield ("The word 'custom' is redundant.")
|
||||
|
||||
|
||||
def check_unknown_ping(
|
||||
check_name: str,
|
||||
check_type: CheckType,
|
||||
all_pings: Dict[str, pings.Ping],
|
||||
metrics: Dict[str, metrics.Metric],
|
||||
parser_config: Dict[str, Any],
|
||||
) -> NitGenerator:
|
||||
"""
|
||||
Check that all pings in `send_in_pings` for all metrics are either a builtin ping
|
||||
or in the list of defined custom pings.
|
||||
"""
|
||||
available_pings = [p for p in all_pings]
|
||||
|
||||
for _, metric in metrics.items():
|
||||
if check_name in metric.no_lint:
|
||||
continue
|
||||
|
||||
send_in_pings = metric.send_in_pings
|
||||
for target_ping in send_in_pings:
|
||||
if target_ping in pings.RESERVED_PING_NAMES:
|
||||
continue
|
||||
|
||||
if target_ping not in available_pings:
|
||||
msg = f"Ping `{target_ping} `in `send_in_pings` is unknown."
|
||||
name = ".".join([metric.category, metric.name])
|
||||
nit = GlinterNit(
|
||||
check_name,
|
||||
name,
|
||||
msg,
|
||||
check_type,
|
||||
)
|
||||
yield nit
|
||||
|
||||
|
||||
# The checks that operate on an entire category of metrics:
|
||||
# {NAME: (function, is_error)}
|
||||
CATEGORY_CHECKS: Dict[
|
||||
|
|
@ -341,6 +379,20 @@ PING_CHECKS: Dict[
|
|||
"REDUNDANT_PING": (check_redundant_ping, CheckType.error),
|
||||
}
|
||||
|
||||
ALL_OBJECT_CHECKS: Dict[
|
||||
str,
|
||||
Tuple[
|
||||
Callable[
|
||||
# check name, check type, pings, metrics, config
|
||||
[str, CheckType, dict, dict, dict],
|
||||
NitGenerator,
|
||||
],
|
||||
CheckType,
|
||||
],
|
||||
] = {
|
||||
"UNKNOWN_PING_REFERENCED": (check_unknown_ping, CheckType.error),
|
||||
}
|
||||
|
||||
|
||||
class GlinterNit:
|
||||
def __init__(self, check_name: str, name: str, msg: str, check_type: CheckType):
|
||||
|
|
@ -410,6 +462,29 @@ def _lint_pings(
|
|||
return nits
|
||||
|
||||
|
||||
def _lint_all_objects(
|
||||
objects: Dict[str, Dict[str, Union[metrics.Metric, pings.Ping, tags.Tag]]],
|
||||
parser_config: Dict[str, Any],
|
||||
) -> List[GlinterNit]:
|
||||
nits: List[GlinterNit] = []
|
||||
|
||||
pings = objects.get("pings")
|
||||
if not pings:
|
||||
return []
|
||||
|
||||
metrics = objects.get("all_metrics")
|
||||
if not metrics:
|
||||
return []
|
||||
|
||||
for check_name, (check_func, check_type) in ALL_OBJECT_CHECKS.items():
|
||||
new_nits = list(
|
||||
check_func(check_name, check_type, pings, metrics, parser_config)
|
||||
)
|
||||
nits.extend(new_nits)
|
||||
|
||||
return nits
|
||||
|
||||
|
||||
def lint_metrics(
|
||||
objs: metrics.ObjectTree,
|
||||
parser_config: Optional[Dict[str, Any]] = None,
|
||||
|
|
@ -427,6 +502,9 @@ def lint_metrics(
|
|||
|
||||
nits: List[GlinterNit] = []
|
||||
valid_tag_names = [tag for tag in objs.get("tags", [])]
|
||||
|
||||
nits.extend(_lint_all_objects(objs, parser_config))
|
||||
|
||||
for category_name, category in sorted(list(objs.items())):
|
||||
if category_name == "pings":
|
||||
nits.extend(_lint_pings(category, parser_config, valid_tag_names))
|
||||
|
|
@ -495,15 +573,6 @@ def lint_metrics(
|
|||
return nits
|
||||
|
||||
|
||||
def lint_yaml_files(
|
||||
input_filepaths: Iterable[Path],
|
||||
file=sys.stderr,
|
||||
parser_config: Optional[Dict[str, Any]] = None,
|
||||
) -> List:
|
||||
"""Always empty."""
|
||||
return []
|
||||
|
||||
|
||||
def glinter(
|
||||
input_filepaths: Iterable[Path],
|
||||
parser_config: Optional[Dict[str, Any]] = None,
|
||||
|
|
|
|||
|
|
@ -29,7 +29,8 @@ class Lifetime(enum.Enum):
|
|||
class DataSensitivity(enum.Enum):
|
||||
technical = 1
|
||||
interaction = 2
|
||||
web_activity = 3
|
||||
stored_content = 3
|
||||
web_activity = 3 # Old, deprecated name
|
||||
highly_sensitive = 4
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ definitions:
|
|||
short_id:
|
||||
allOf:
|
||||
- $ref: "#/definitions/snake_case"
|
||||
- maxLength: 30
|
||||
- maxLength: 70
|
||||
|
||||
labeled_metric_id:
|
||||
type: string
|
||||
|
|
@ -483,27 +483,60 @@ definitions:
|
|||
tabs, addons, or windows a user has open; uses of specific Firefox
|
||||
features; session length, scrolls and clicks; and the status of
|
||||
discrete user preferences.
|
||||
It also includes information about the user's in-product journeys
|
||||
and product choices helpful to understand engagement (attitudes).
|
||||
For example, selections of add-ons or tiles to determine
|
||||
potential interest categories etc.
|
||||
|
||||
- **Category 3: Web activity data:** (`web_activity`) Information
|
||||
about user web browsing that could be considered sensitive. Examples
|
||||
include users’ specific web browsing history; general information
|
||||
about their web browsing history (such as TLDs or categories of
|
||||
webpages visited over time); and potentially certain types of
|
||||
interaction data about specific webpages visited.
|
||||
- **Category 3: Stored Content & Communications:**
|
||||
(`stored_content`, formerly Web activity data, `web_activity`)
|
||||
Information about what people store, sync, communicate or connect to
|
||||
where the information is generally considered to be more sensitive
|
||||
and personal in nature.
|
||||
Examples include users' saved URLs or URL history,
|
||||
specific web browsing history, general information
|
||||
about their web browsing history
|
||||
(such as TLDs or categories of webpages visited over time)
|
||||
and potentially certain types of interaction data
|
||||
about specific web pages or stories visited
|
||||
(such as highlighted portions of a story).
|
||||
It also includes information such as content saved by users to
|
||||
an individual account like saved URLs, tags, notes, passwords
|
||||
and files as well as communications that users have with one another
|
||||
through a Mozilla service.
|
||||
|
||||
- **Category 4: Highly sensitive data
|
||||
or clearly identifiable personal data:** (`highly_sensitive`)
|
||||
|
||||
- **Category 4: Highly sensitive data:** (`highly_sensitive`)
|
||||
Information that directly identifies a person, or if combined with
|
||||
other data could identify a person. Examples include e-mail,
|
||||
usernames, identifiers such as google ad id, apple id, fxaccount,
|
||||
city or country (unless small ones are explicitly filtered out), or
|
||||
certain cookies. It may be embedded within specific website content,
|
||||
such as memory contents, dumps, captures of screen data, or DOM
|
||||
data.
|
||||
other data could identify a person.
|
||||
This data may be embedded within specific website content,
|
||||
such as memory contents, dumps, captures of screen data,
|
||||
or DOM data.
|
||||
Examples include account registration data like name, password,
|
||||
and email address associated with an account,
|
||||
payment data in connection with subscriptions or donations,
|
||||
contact information such as phone numbers or mailing addresses,
|
||||
email addresses associated with surveys, promotions
|
||||
and customer support contacts.
|
||||
It also includes any data from different categories that,
|
||||
when combined, can identify a person, device, household or account.
|
||||
For example Category 1 log data combined with Category 3 saved URLs.
|
||||
Additional examples are: voice audio commands
|
||||
(including a voice audio file), speech-to-text or text-to-speech
|
||||
(including transcripts), biometric data, demographic information,
|
||||
and precise location data associated with a persistent identifier,
|
||||
individual or small population cohorts.
|
||||
This is location inferred or determined from mechanisms
|
||||
other than IP such as wi-fi access points, Bluetooth beacons,
|
||||
cell phone towers or provided directly to us,
|
||||
such as in a survey or a profile.
|
||||
type: array
|
||||
items:
|
||||
enum:
|
||||
- technical
|
||||
- interaction
|
||||
- stored_content
|
||||
- web_activity
|
||||
- highly_sensitive
|
||||
type: string
|
||||
|
|
@ -687,11 +720,13 @@ additionalProperties:
|
|||
|
||||
data_sensitivity:
|
||||
description: >
|
||||
Text metrics require Category 3 (`web_activity`)
|
||||
Text metrics require Category 3
|
||||
(`stored_content` / `web_activity`)
|
||||
or Category 4 (`highly_sensitive`).
|
||||
type: array
|
||||
items:
|
||||
enum:
|
||||
- stored_content
|
||||
- web_activity
|
||||
- highly_sensitive
|
||||
|
||||
|
|
|
|||
154
third_party/python/glean_parser/glean_parser/templates/javascript_server.jinja2
vendored
Normal file
154
third_party/python/glean_parser/glean_parser/templates/javascript_server.jinja2
vendored
Normal file
|
|
@ -0,0 +1,154 @@
|
|||
{# The final Javascript/Typescript code 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/. */
|
||||
|
||||
// AUTOGENERATED BY glean_parser v{{ parser_version }}. DO NOT EDIT. DO NOT COMMIT.
|
||||
|
||||
// This requires `uuid` and `mozlog` libraries to be in the environment
|
||||
{% if lang == "typescript" %}
|
||||
// @types/uuid and mozlog types definitions are required in devDependencies
|
||||
// for the latter see https://github.com/mozilla/fxa/blob/85bda71cda376c417b8c850ba82aa14252208c3c/types/mozlog/index.d.ts
|
||||
{% endif %}
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
import mozlog{% if lang == "typescript" %}, { Logger }{% endif %} from 'mozlog';
|
||||
|
||||
const GLEAN_EVENT_MOZLOG_TYPE = 'glean-server-event';
|
||||
|
||||
let _logger{% if lang == "typescript" %}: Logger{% endif %};
|
||||
|
||||
{% for ping, metrics_by_type in pings.items() %}
|
||||
class {{ ping|event_class_name }} {
|
||||
{% if lang == "typescript" %}
|
||||
_applicationId: string;
|
||||
_appDisplayVersion: string;
|
||||
_channel: string;
|
||||
{% endif %}
|
||||
/**
|
||||
* Create {{ ping|event_class_name }} instance.
|
||||
*
|
||||
* @param {string} applicationId - The application ID.
|
||||
* @param {string} appDisplayVersion - The application display version.
|
||||
* @param {string} channel - The channel.
|
||||
*/
|
||||
{% if lang == "typescript" %}
|
||||
constructor(
|
||||
applicationId: string,
|
||||
appDisplayVersion: string,
|
||||
channel: string,
|
||||
logger_options: any
|
||||
) {
|
||||
{% else %}
|
||||
constructor(applicationId, appDisplayVersion, channel, logger_options) {
|
||||
{% endif %}
|
||||
this._applicationId = applicationId;
|
||||
this._appDisplayVersion = appDisplayVersion;
|
||||
this._channel = channel;
|
||||
|
||||
if (!_logger) {
|
||||
// append '-glean' to `logger_options.app` to avoid collision with other loggers and double logging
|
||||
logger_options.app = logger_options.app + '-glean';
|
||||
// set the format to `heka` so messages are properly ingested and decoded
|
||||
logger_options.fmt = 'heka';
|
||||
{% if lang == "typescript" %}
|
||||
// mozlog types declaration requires a typePrefix to be passed when creating a logger
|
||||
// we don't want a typePrefix, so we pass `undefined`
|
||||
_logger = mozlog(logger_options)(undefined);
|
||||
{% else %}
|
||||
_logger = mozlog(logger_options)();
|
||||
{% endif %}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Record and submit a server event object.
|
||||
* Event is logged using internal mozlog logger.
|
||||
*
|
||||
{% for metric_type, metrics in metrics_by_type.items() %}
|
||||
{% for metric in metrics %}
|
||||
* @param { {{-metric|js_metric_type-}} } {{ metric|metric_argument_name }} - {{ metric|metric_argument_description }}.
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
*/
|
||||
record({
|
||||
{% for metric_type, metrics in metrics_by_type.items() %}
|
||||
{% for metric in metrics %}
|
||||
{{ metric|metric_argument_name }},
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
{% if lang == "typescript" %}
|
||||
}: {
|
||||
{% for metric_type, metrics in metrics_by_type.items() %}
|
||||
{% for metric in metrics %}
|
||||
{{ metric|metric_argument_name }}: {{ metric|js_metric_type }};
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
}) {
|
||||
let timestamp = new Date().toISOString();
|
||||
let eventPayload = {
|
||||
metrics: {
|
||||
{% for metric_type, metrics in metrics_by_type.items() %}
|
||||
{{ metric_type }}: {
|
||||
{% for metric in metrics %}
|
||||
'{{ metric|metric_name }}': {{ metric|metric_argument_name }},
|
||||
{% endfor %}
|
||||
},
|
||||
{% endfor %}
|
||||
},
|
||||
ping_info: {
|
||||
seq: 0, // this is required, however doesn't seem to be useful in server context
|
||||
start_time: timestamp,
|
||||
end_time: timestamp,
|
||||
},
|
||||
// `Unknown` fields below are required in the Glean schema, however they are not useful in server context
|
||||
client_info: {
|
||||
telemetry_sdk_build: 'glean_parser v{{ parser_version }}',
|
||||
first_run_date: 'Unknown',
|
||||
os: 'Unknown',
|
||||
os_version: 'Unknown',
|
||||
architecture: 'Unknown',
|
||||
app_build: 'Unknown',
|
||||
app_display_version: this._appDisplayVersion,
|
||||
app_channel: this._channel,
|
||||
},
|
||||
};
|
||||
let eventPayloadSerialized = JSON.stringify(eventPayload);
|
||||
|
||||
// This is the message structure that Decoder expects: https://github.com/mozilla/gcp-ingestion/pull/2400
|
||||
let ping = {
|
||||
document_namespace: this._applicationId,
|
||||
document_type: '{{ ping }}',
|
||||
document_version: '1',
|
||||
document_id: uuidv4(),
|
||||
payload: eventPayloadSerialized,
|
||||
};
|
||||
|
||||
// this is similar to how FxA currently logs with mozlog: https://github.com/mozilla/fxa/blob/4c5c702a7fcbf6f8c6b1f175e9172cdd21471eac/packages/fxa-auth-server/lib/log.js#L289
|
||||
_logger.info(GLEAN_EVENT_MOZLOG_TYPE, ping);
|
||||
}
|
||||
}
|
||||
{% endfor %}
|
||||
{% for ping in pings %}
|
||||
|
||||
export const {{ ping|factory_method }} = function ({
|
||||
applicationId,
|
||||
appDisplayVersion,
|
||||
channel,
|
||||
logger_options
|
||||
{% if lang == "typescript" %}
|
||||
}: {
|
||||
applicationId: string;
|
||||
appDisplayVersion: string;
|
||||
channel: string;
|
||||
logger_options: any;
|
||||
{% endif %}
|
||||
}) {
|
||||
return new {{ ping|event_class_name }}(
|
||||
applicationId,
|
||||
appDisplayVersion,
|
||||
channel,
|
||||
logger_options
|
||||
);
|
||||
};
|
||||
{% endfor %}
|
||||
|
|
@ -86,191 +86,4 @@ pub mod {{ category.name|snake_case }} {
|
|||
{% endfor %}
|
||||
{% if metric_by_type|length > 0 %}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub(crate) mod __glean_metric_maps {
|
||||
use std::collections::HashMap;
|
||||
|
||||
use super::{id_for_extra_key, extra_keys_len};
|
||||
use crate::private::*;
|
||||
|
||||
{% for typ, metrics in metric_by_type.items() %}
|
||||
pub static {{typ.0}}: ::glean::private::__export::Lazy<HashMap<MetricId, &Lazy<{{typ.1}}>>> = ::glean::private::__export::Lazy::new(|| {
|
||||
let mut map = HashMap::with_capacity({{metrics|length}});
|
||||
{% for metric in metrics %}
|
||||
map.insert({{metric.0}}.into(), &super::{{metric.1}});
|
||||
{% endfor %}
|
||||
map
|
||||
});
|
||||
|
||||
{% endfor %}
|
||||
|
||||
/// Wrapper to record an event based on its metric ID.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `metric_id` - The metric's ID to look up
|
||||
/// * `extra` - An map of (extra key id, string) pairs.
|
||||
/// The map will be decoded into the appropriate `ExtraKeys` type.
|
||||
/// # Returns
|
||||
///
|
||||
/// Returns `Ok(())` if the event was found and `record` was called with the given `extra`,
|
||||
/// or an `EventRecordingError::InvalidId` if no event by that ID exists
|
||||
/// or an `EventRecordingError::InvalidExtraKey` if the `extra` map could not be deserialized.
|
||||
pub(crate) fn record_event_by_id(metric_id: u32, extra: HashMap<i32, String>) -> Result<(), EventRecordingError> {
|
||||
match metric_id {
|
||||
{% for metric_id, event in events_by_id.items() %}
|
||||
{{metric_id}} => {
|
||||
assert!(
|
||||
extra_keys_len(&super::{{event}}) != 0 || extra.is_empty(),
|
||||
"No extra keys allowed, but some were passed"
|
||||
);
|
||||
|
||||
super::{{event}}.record_raw(extra);
|
||||
Ok(())
|
||||
}
|
||||
{% endfor %}
|
||||
_ => Err(EventRecordingError::InvalidId),
|
||||
}
|
||||
}
|
||||
|
||||
/// Wrapper to record an event based on its metric ID, with a provided timestamp.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `metric_id` - The metric's ID to look up
|
||||
/// * `timestamp` - The time at which this event was recorded.
|
||||
/// * `extra` - An map of (extra key id, string) pairs.
|
||||
/// The map will be decoded into the appropriate `ExtraKeys` type.
|
||||
/// # Returns
|
||||
///
|
||||
/// Returns `Ok(())` if the event was found and `record` was called with the given `extra`,
|
||||
/// or an `EventRecordingError::InvalidId` if no event by that ID exists
|
||||
/// or an `EventRecordingError::InvalidExtraKey` if the event doesn't take extra pairs,
|
||||
/// but some are passed in.
|
||||
pub(crate) fn record_event_by_id_with_time(metric_id: MetricId, timestamp: u64, extra: HashMap<i32, String>) -> Result<(), EventRecordingError> {
|
||||
match metric_id {
|
||||
{% for metric_id, event in events_by_id.items() %}
|
||||
MetricId({{metric_id}}) => {
|
||||
if extra_keys_len(&super::{{event}}) == 0 && !extra.is_empty() {
|
||||
return Err(EventRecordingError::InvalidExtraKey);
|
||||
}
|
||||
|
||||
super::{{event}}.record_with_time(timestamp, extra);
|
||||
Ok(())
|
||||
}
|
||||
{% endfor %}
|
||||
_ => Err(EventRecordingError::InvalidId),
|
||||
}
|
||||
}
|
||||
|
||||
/// Wrapper to record an event based on its metric ID.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `metric_id` - The metric's ID to look up
|
||||
/// * `extra` - An map of (string, string) pairs.
|
||||
/// The map will be decoded into the appropriate `ExtraKeys` types.
|
||||
/// # Returns
|
||||
///
|
||||
/// Returns `Ok(())` if the event was found and `record` was called with the given `extra`,
|
||||
/// or an `EventRecordingError::InvalidId` if no event by that ID exists
|
||||
/// or an `EventRecordingError::InvalidExtraKey` if the `extra` map could not be deserialized.
|
||||
pub(crate) fn record_event_by_id_with_strings(metric_id: u32, extra: HashMap<String, String>) -> Result<(), EventRecordingError> {
|
||||
match metric_id {
|
||||
{% for metric_id, event in events_by_id.items() %}
|
||||
{{metric_id}} => {
|
||||
assert!(
|
||||
extra_keys_len(&super::{{event}}) != 0 || extra.is_empty(),
|
||||
"No extra keys allowed, but some were passed"
|
||||
);
|
||||
|
||||
let extra = extra
|
||||
.into_iter()
|
||||
.map(|(k, v)| id_for_extra_key(&*k, &super::{{event}}).map(|k| (k, v)))
|
||||
.collect::<Result<HashMap<_, _>, _>>()?;
|
||||
super::{{event}}.record_raw(extra);
|
||||
Ok(())
|
||||
}
|
||||
{% endfor %}
|
||||
_ => Err(EventRecordingError::InvalidId),
|
||||
}
|
||||
}
|
||||
|
||||
/// Wrapper to get the currently stored events for event metric.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `metric_id` - The metric's ID to look up
|
||||
/// * `ping_name` - (Optional) The ping name to look into.
|
||||
/// Defaults to the first value in `send_in_pings`.
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// Returns the recorded events or `None` if nothing stored.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if no event by the given metric ID could be found.
|
||||
pub(crate) fn event_test_get_value_wrapper(metric_id: u32, ping_name: Option<String>) -> Option<Vec<RecordedEvent>> {
|
||||
match metric_id {
|
||||
{% for metric_id, event in events_by_id.items() %}
|
||||
{{metric_id}} => super::{{event}}.test_get_value(ping_name.as_deref()),
|
||||
{% endfor %}
|
||||
_ => panic!("No event for metric id {}", metric_id),
|
||||
}
|
||||
}
|
||||
|
||||
/// Check the provided event for errors.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `metric_id` - The metric's ID to look up
|
||||
/// * `ping_name` - (Optional) The ping name to look into.
|
||||
/// Defaults to the first value in `send_in_pings`.
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// Returns a string for the recorded error or `None`.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if no event by the given metric ID could be found.
|
||||
#[allow(unused_variables)]
|
||||
pub(crate) fn event_test_get_error(metric_id: u32, ping_name: Option<String>) -> Option<String> {
|
||||
#[cfg(feature = "with_gecko")]
|
||||
match metric_id {
|
||||
{% for metric_id, event in events_by_id.items() %}
|
||||
{{metric_id}} => test_get_errors_string!(super::{{event}}, ping_name),
|
||||
{% endfor %}
|
||||
_ => panic!("No event for metric id {}", metric_id),
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "with_gecko"))]
|
||||
{
|
||||
return None;
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) mod submetric_maps {
|
||||
use std::sync::{
|
||||
atomic::AtomicU32,
|
||||
RwLock,
|
||||
};
|
||||
use super::*;
|
||||
|
||||
pub(crate) const MIN_LABELED_SUBMETRIC_ID: u32 = {{min_submetric_id}};
|
||||
pub(crate) static NEXT_LABELED_SUBMETRIC_ID: AtomicU32 = AtomicU32::new(MIN_LABELED_SUBMETRIC_ID);
|
||||
pub(crate) static LABELED_METRICS_TO_IDS: ::glean::private::__export::Lazy<RwLock<HashMap<(u32, String), u32>>> = ::glean::private::__export::Lazy::new(||
|
||||
RwLock::new(HashMap::new())
|
||||
);
|
||||
|
||||
{% for typ, metrics in metric_by_type.items() %}
|
||||
{% if typ.0 in ('BOOLEAN_MAP', 'COUNTER_MAP', 'STRING_MAP') %}
|
||||
pub static {{typ.0}}: ::glean::private::__export::Lazy<RwLock<HashMap<MetricId, Labeled{{typ.1}}>>> = ::glean::private::__export::Lazy::new(||
|
||||
RwLock::new(HashMap::new())
|
||||
);
|
||||
{% endif %}
|
||||
{% endfor%}
|
||||
}
|
||||
}
|
||||
{% endif %}
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ from typing import Any, Callable, Dict, Iterable, List, Optional
|
|||
from . import lint
|
||||
from . import parser
|
||||
from . import javascript
|
||||
from . import javascript_server
|
||||
from . import kotlin
|
||||
from . import markdown
|
||||
from . import metrics
|
||||
|
|
@ -54,6 +55,8 @@ class Outputter:
|
|||
OUTPUTTERS = {
|
||||
"javascript": Outputter(javascript.output_javascript, []),
|
||||
"typescript": Outputter(javascript.output_typescript, []),
|
||||
"javascript_server": Outputter(javascript_server.output_javascript, []),
|
||||
"typescript_server": Outputter(javascript_server.output_typescript, []),
|
||||
"kotlin": Outputter(kotlin.output_kotlin, ["*.kt"]),
|
||||
"markdown": Outputter(markdown.output_markdown, []),
|
||||
"swift": Outputter(swift.output_swift, ["*.swift"]),
|
||||
|
|
|
|||
8
third_party/python/poetry.lock
generated
vendored
8
third_party/python/poetry.lock
generated
vendored
|
|
@ -391,14 +391,14 @@ files = [
|
|||
|
||||
[[package]]
|
||||
name = "glean-parser"
|
||||
version = "7.2.1"
|
||||
version = "8.1.0"
|
||||
description = "Parser tools for Mozilla's Glean telemetry"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
files = [
|
||||
{file = "glean_parser-7.2.1-py3-none-any.whl", hash = "sha256:651cfee34422ea1db90bbf1cb03732bd8c598773bf95daa289a62addeaf10295"},
|
||||
{file = "glean_parser-7.2.1.tar.gz", hash = "sha256:11496ac004fe421b914c7fbdc9a1d620e4821d56e1d9f65523d3858cdb907bbd"},
|
||||
{file = "glean_parser-8.1.0-py3-none-any.whl", hash = "sha256:bcb4b04f3d5d8fbc1cba452e0ea19d4f89a0f3363b78dabd410c26618632ffa1"},
|
||||
{file = "glean_parser-8.1.0.tar.gz", hash = "sha256:b9ef84ec1afdb3a1080219fe3768411a824921b7fcd637314fc78d47b5537752"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
|
|
@ -1415,4 +1415,4 @@ testing = ["func-timeout", "jaraco.itertools", "pytest (>=4.6)", "pytest-black (
|
|||
[metadata]
|
||||
lock-version = "2.0"
|
||||
python-versions = "^3.7"
|
||||
content-hash = "c409903aba82ee97e2d690aeaf190c01fe6c26adbc472572dc2fd9fa2cb7cc8f"
|
||||
content-hash = "195fb2c45ba5de3c5c98f5d2fa44b5ce64fd3dd45c324d528477637245413d0f"
|
||||
|
|
|
|||
BIN
third_party/python/python_dateutil/dateutil/zoneinfo/dateutil-zoneinfo.tar.gz
vendored
Normal file
BIN
third_party/python/python_dateutil/dateutil/zoneinfo/dateutil-zoneinfo.tar.gz
vendored
Normal file
Binary file not shown.
2
third_party/python/requirements.in
vendored
2
third_party/python/requirements.in
vendored
|
|
@ -14,7 +14,7 @@ ecdsa==0.15
|
|||
esprima==4.0.1
|
||||
fluent.migrate==0.12.0
|
||||
fluent.syntax==0.19.0
|
||||
glean_parser==7.2.1
|
||||
glean_parser==8.1.0
|
||||
importlib-metadata==6.0.0
|
||||
jsmin==3.0.0
|
||||
json-e==2.7.0
|
||||
|
|
|
|||
6
third_party/python/requirements.txt
vendored
6
third_party/python/requirements.txt
vendored
|
|
@ -104,9 +104,9 @@ fluent-syntax==0.19.0 ; python_version >= "3.7" and python_version < "4.0" \
|
|||
giturlparse==0.10.0 ; python_version >= "3.7" and python_version < "4.0" \
|
||||
--hash=sha256:04ba1a3a099c3093fa8d24a422913c6a9b2c2cd22bcffc939cf72e3e98f672d7 \
|
||||
--hash=sha256:2595ab291d30717cda8474b874c9fd509f1b9802ad7f6968c36a45e4b13eb337
|
||||
glean-parser==7.2.1 ; python_version >= "3.7" and python_version < "4.0" \
|
||||
--hash=sha256:11496ac004fe421b914c7fbdc9a1d620e4821d56e1d9f65523d3858cdb907bbd \
|
||||
--hash=sha256:651cfee34422ea1db90bbf1cb03732bd8c598773bf95daa289a62addeaf10295
|
||||
glean-parser==8.1.0 ; python_version >= "3.7" and python_version < "4.0" \
|
||||
--hash=sha256:b9ef84ec1afdb3a1080219fe3768411a824921b7fcd637314fc78d47b5537752 \
|
||||
--hash=sha256:bcb4b04f3d5d8fbc1cba452e0ea19d4f89a0f3363b78dabd410c26618632ffa1
|
||||
idna==2.10 ; python_version >= "3.7" and python_version < "4.0" \
|
||||
--hash=sha256:b307872f855b18632ce0c21c5e45be78c0ea7ae4c15c828c20788b26921eb3f6 \
|
||||
--hash=sha256:b97d804b1e9b523befed77c48dacec60e6dcb0b5391d57af6a65a312a90648c0
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
5
third_party/rust/glean-core/Cargo.toml
vendored
5
third_party/rust/glean-core/Cargo.toml
vendored
|
|
@ -13,7 +13,7 @@
|
|||
edition = "2021"
|
||||
rust-version = "1.62"
|
||||
name = "glean-core"
|
||||
version = "53.1.0"
|
||||
version = "53.2.0"
|
||||
authors = [
|
||||
"Jan-Erik Rediger <jrediger@mozilla.com>",
|
||||
"The Glean Team <glean-team@mozilla.com>",
|
||||
|
|
@ -33,10 +33,9 @@ readme = "README.md"
|
|||
keywords = ["telemetry"]
|
||||
license = "MPL-2.0"
|
||||
repository = "https://github.com/mozilla/glean"
|
||||
resolver = "1"
|
||||
|
||||
[package.metadata.glean]
|
||||
glean-parser = "7.1.0"
|
||||
glean-parser = "8.1.0"
|
||||
|
||||
[dependencies.bincode]
|
||||
version = "1.2.1"
|
||||
|
|
|
|||
|
|
@ -1080,7 +1080,7 @@ mod test {
|
|||
let metric_id_pattern = "telemetry_test.single_metric";
|
||||
|
||||
// Write sample metrics to the database.
|
||||
let lifetimes = vec![Lifetime::User, Lifetime::Ping, Lifetime::Application];
|
||||
let lifetimes = [Lifetime::User, Lifetime::Ping, Lifetime::Application];
|
||||
|
||||
for lifetime in lifetimes.iter() {
|
||||
for value in &["retain", "delete"] {
|
||||
|
|
|
|||
|
|
@ -894,7 +894,7 @@ mod test {
|
|||
},
|
||||
execution_counter: None,
|
||||
};
|
||||
let timestamps = vec![20, 40, 200];
|
||||
let timestamps = [20, 40, 200];
|
||||
let not_glean_restarted = StoredEvent {
|
||||
event: RecordedEvent {
|
||||
timestamp: timestamps[0],
|
||||
|
|
@ -970,8 +970,8 @@ mod test {
|
|||
|
||||
// This scenario represents a run of three events followed by an hour between runs,
|
||||
// followed by one final event.
|
||||
let timestamps = vec![20, 40, 200, 12];
|
||||
let ecs = vec![0, 1];
|
||||
let timestamps = [20, 40, 200, 12];
|
||||
let ecs = [0, 1];
|
||||
let some_hour = 16;
|
||||
let startup_date = FixedOffset::east(0)
|
||||
.ymd(2022, 11, 24)
|
||||
|
|
@ -1095,8 +1095,8 @@ mod test {
|
|||
|
||||
// This scenario represents a run of two events followed by negative one hours between runs,
|
||||
// followed by two more events.
|
||||
let timestamps = vec![20, 40, 12, 200];
|
||||
let ecs = vec![0, 1];
|
||||
let timestamps = [20, 40, 12, 200];
|
||||
let ecs = [0, 1];
|
||||
let some_hour = 10;
|
||||
let startup_date = FixedOffset::east(0)
|
||||
.ymd(2022, 11, 25)
|
||||
|
|
|
|||
2
third_party/rust/glean-core/tests/event.rs
vendored
2
third_party/rust/glean-core/tests/event.rs
vendored
|
|
@ -136,7 +136,7 @@ fn snapshot_correctly_clears_the_stores() {
|
|||
let snapshot2 = glean
|
||||
.event_storage()
|
||||
.snapshot_as_json(&glean, "store2", false);
|
||||
for s in vec![snapshot, snapshot2] {
|
||||
for s in [snapshot, snapshot2] {
|
||||
assert!(s.is_some());
|
||||
let s = s.unwrap();
|
||||
assert_eq!(1, s.as_array().unwrap().len());
|
||||
|
|
|
|||
2
third_party/rust/glean/.cargo-checksum.json
vendored
2
third_party/rust/glean/.cargo-checksum.json
vendored
|
|
@ -1 +1 @@
|
|||
{"files":{"Cargo.toml":"889c822c32b84930908f4280a9e73808cd0f57fa9f6cea2f9b61da017235e664","LICENSE":"1f256ecad192880510e84ad60474eab7589218784b9a50bc7ceee34c2b91f1d5","README.md":"5627cc81e6187ab6c2b4dff061af16d559edcab64ba786bac39daa69c703c595","src/common_test.rs":"de47b53dcca37985c0a2b8c02daecbf32309aa54f5a4dd9290719c2c1fd0fa55","src/configuration.rs":"c82d1d4c32baa878e0fae566c10cbe348531f2983657aee39276fd78ea0c9b1d","src/core_metrics.rs":"dd17b482613894af08b51a2cff6dc1e84a6dbd853c14a55566e6698348941ced","src/lib.rs":"727a078a27c4985adb4022f2fc64fda647c996078f995c1fec85c208cd3337bc","src/net/http_uploader.rs":"43812a70d19a38e8d7a093c8076c2b6345372c3c861b0f3511428762700a65e0","src/net/mod.rs":"e36e170a8e53530f8705988eea694ed7c55f50bb0ce403c0facbfb75ce03ac7f","src/private/event.rs":"02bbebf545695812e5055741cc0b5f3c99eda2039e684e26fcdd5f087ed15fe3","src/private/mod.rs":"eb8fe4e588bb32a54617324db39319920c627e6fc23c23cf4da5c17c63e0afed","src/private/ping.rs":"cbdc57f41fc9d46e56b4dfff91ac683753d1f8b3ecd0aa9bc3419e3595b8b81b","src/system.rs":"6eae5b41c15eba9cad6dbd116abe3519ee3e1fe034e79bdd692b029829a8c384","src/test.rs":"356890df8f88096b4a62e396d9810f9bc20790e7b7fb446c73801109ea1c26b1","tests/common/mod.rs":"37cd4c48e140c793b852ae09fb3e812da28a4412977295015bcbffd632fcf294","tests/init_fails.rs":"28fd7726e76ca1295eb0905eca0b2ec65b0accfa28432c9ff90ec8f92616fc79","tests/never_init.rs":"1f33b8ce7ca3514b57b48cc16d98408974c85cf8aa7d13257ffc2ad878ebb295","tests/no_time_to_init.rs":"e7df75b47897fbf2c860a2e1c1c225b57598b8d1a39125ca897fe8d825bf0338","tests/overflowing_preinit.rs":"7ad4b2274dd9240b53430859a4eb1d2597cf508a5a678333f3d3abbadd2ed4a7","tests/persist_ping_lifetime.rs":"81415dc1d74743f02269f0d0dfa524003147056853f080276972e64a0b761d3c","tests/persist_ping_lifetime_nopanic.rs":"18379d3ffbf4a2c8c684c04ff7a0660b86dfbbb447db2d24dfed6073cb7ddf8f","tests/schema.rs":"1b7b19aec54a24c2bdd4738cf33c16802c19c83504c4d0e6bcfc19142877acdb","tests/simple.rs":"b099034b0599bdf4650e0fa09991a8413fc5fbf397755fc06c8963d4c7c8dfa6","tests/test-shutdown-blocking.sh":"9b16a01c190c7062474dd92182298a3d9a27928c8fa990340fdd798e6cdb7ab2","tests/upload_timing.rs":"d044fce7c783133e385671ea37d674e5a1b4120cae7b07708dcd825addfa0ee3"},"package":"0efbf048a79e634cd5ccd224f972018e3f217c72d4071bbe6ebee382037bffcb"}
|
||||
{"files":{"Cargo.toml":"6c5dc80704945076018237c096a850a6bd0d48d392e1f47e2d3437bdc673ea28","LICENSE":"1f256ecad192880510e84ad60474eab7589218784b9a50bc7ceee34c2b91f1d5","README.md":"5627cc81e6187ab6c2b4dff061af16d559edcab64ba786bac39daa69c703c595","src/common_test.rs":"de47b53dcca37985c0a2b8c02daecbf32309aa54f5a4dd9290719c2c1fd0fa55","src/configuration.rs":"5be1eaf4a2e1d1b35d9c13387f8f59b5f5d96a874b984396b7fae907e2938a8c","src/core_metrics.rs":"fef8fb4e5fa57c179836c6eb2cf59278fe3b8b036dbe57b0ff02971b4acd822f","src/lib.rs":"7bffe31c2b59d9e26b0869264af9a098be6eccb086f146e46777a288ad5e505f","src/net/http_uploader.rs":"43812a70d19a38e8d7a093c8076c2b6345372c3c861b0f3511428762700a65e0","src/net/mod.rs":"612a9f13ade0b202c8762bccc7b5dc288101cb3820e47be2755331911a221c55","src/private/event.rs":"02bbebf545695812e5055741cc0b5f3c99eda2039e684e26fcdd5f087ed15fe3","src/private/mod.rs":"eb8fe4e588bb32a54617324db39319920c627e6fc23c23cf4da5c17c63e0afed","src/private/ping.rs":"cbdc57f41fc9d46e56b4dfff91ac683753d1f8b3ecd0aa9bc3419e3595b8b81b","src/system.rs":"6eae5b41c15eba9cad6dbd116abe3519ee3e1fe034e79bdd692b029829a8c384","src/test.rs":"c877fa637e9049834818c3354f8b9b8b7a8136fb71ab3b0f9f0ea88115cbbd4b","tests/common/mod.rs":"08fb9483d9b6ed9fe873b4395245166ae8a15263be750c7a8e298c41d9604745","tests/init_fails.rs":"28fd7726e76ca1295eb0905eca0b2ec65b0accfa28432c9ff90ec8f92616fc79","tests/never_init.rs":"1f33b8ce7ca3514b57b48cc16d98408974c85cf8aa7d13257ffc2ad878ebb295","tests/no_time_to_init.rs":"e7df75b47897fbf2c860a2e1c1c225b57598b8d1a39125ca897fe8d825bf0338","tests/overflowing_preinit.rs":"7ad4b2274dd9240b53430859a4eb1d2597cf508a5a678333f3d3abbadd2ed4a7","tests/persist_ping_lifetime.rs":"81415dc1d74743f02269f0d0dfa524003147056853f080276972e64a0b761d3c","tests/persist_ping_lifetime_nopanic.rs":"18379d3ffbf4a2c8c684c04ff7a0660b86dfbbb447db2d24dfed6073cb7ddf8f","tests/schema.rs":"b1d78ac189c5f7309badbc37451fb428abce357e630a55e4ef5b0ef14d118f67","tests/simple.rs":"b099034b0599bdf4650e0fa09991a8413fc5fbf397755fc06c8963d4c7c8dfa6","tests/test-shutdown-blocking.sh":"9b16a01c190c7062474dd92182298a3d9a27928c8fa990340fdd798e6cdb7ab2","tests/test-thread-crashing.sh":"ff1bc8e5d7e4ba3a10d0d38bef222db8bfba469e7d30e45b1053d177a4084f09","tests/upload_timing.rs":"d044fce7c783133e385671ea37d674e5a1b4120cae7b07708dcd825addfa0ee3"},"package":"df470f5f41c8fc6113bd48fa18e0f1a8193e1e2b1f3942f8255b064e60db42ff"}
|
||||
8
third_party/rust/glean/Cargo.toml
vendored
8
third_party/rust/glean/Cargo.toml
vendored
|
|
@ -13,7 +13,7 @@
|
|||
edition = "2021"
|
||||
rust-version = "1.62"
|
||||
name = "glean"
|
||||
version = "53.1.0"
|
||||
version = "53.2.0"
|
||||
authors = [
|
||||
"Jan-Erik Rediger <jrediger@mozilla.com>",
|
||||
"The Glean Team <glean-team@mozilla.com>",
|
||||
|
|
@ -33,7 +33,6 @@ keywords = [
|
|||
]
|
||||
license = "MPL-2.0"
|
||||
repository = "https://github.com/mozilla/glean"
|
||||
resolver = "1"
|
||||
|
||||
[dependencies.chrono]
|
||||
version = "0.4.10"
|
||||
|
|
@ -43,7 +42,7 @@ features = ["serde"]
|
|||
version = "0.5"
|
||||
|
||||
[dependencies.glean-core]
|
||||
version = "53.1.0"
|
||||
version = "53.2.0"
|
||||
|
||||
[dependencies.inherent]
|
||||
version = "1"
|
||||
|
|
@ -88,6 +87,9 @@ version = "1.0.19"
|
|||
[dev-dependencies.jsonschema-valid]
|
||||
version = "0.5.0"
|
||||
|
||||
[dev-dependencies.libc]
|
||||
version = "0.2"
|
||||
|
||||
[dev-dependencies.tempfile]
|
||||
version = "3.1.0"
|
||||
|
||||
|
|
|
|||
4
third_party/rust/glean/src/configuration.rs
vendored
4
third_party/rust/glean/src/configuration.rs
vendored
|
|
@ -39,7 +39,7 @@ pub struct Configuration {
|
|||
/// The internal logging level.
|
||||
pub log_level: Option<LevelFilter>,
|
||||
/// The rate pings may be uploaded before they are throttled.
|
||||
pub rate_limit: Option<glean_core::PingRateLimit>,
|
||||
pub rate_limit: Option<crate::PingRateLimit>,
|
||||
}
|
||||
|
||||
/// Configuration builder.
|
||||
|
|
@ -79,7 +79,7 @@ pub struct Builder {
|
|||
pub log_level: Option<LevelFilter>,
|
||||
/// Optional: The internal ping upload rate limit.
|
||||
/// Default: `None`
|
||||
pub rate_limit: Option<glean_core::PingRateLimit>,
|
||||
pub rate_limit: Option<crate::PingRateLimit>,
|
||||
}
|
||||
|
||||
impl Builder {
|
||||
|
|
|
|||
4
third_party/rust/glean/src/core_metrics.rs
vendored
4
third_party/rust/glean/src/core_metrics.rs
vendored
|
|
@ -13,6 +13,8 @@ pub struct ClientInfoMetrics {
|
|||
pub app_display_version: String,
|
||||
/// The product-provided release channel (e.g. "beta").
|
||||
pub channel: Option<String>,
|
||||
/// The locale of the application during initialization (e.g. "es-ES").
|
||||
pub locale: Option<String>,
|
||||
}
|
||||
|
||||
impl ClientInfoMetrics {
|
||||
|
|
@ -22,6 +24,7 @@ impl ClientInfoMetrics {
|
|||
app_build: "Unknown".to_string(),
|
||||
app_display_version: "Unknown".to_string(),
|
||||
channel: None,
|
||||
locale: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -32,6 +35,7 @@ impl From<ClientInfoMetrics> for glean_core::ClientInfoMetrics {
|
|||
app_build: metrics.app_build,
|
||||
app_display_version: metrics.app_display_version,
|
||||
channel: metrics.channel,
|
||||
locale: metrics.locale,
|
||||
os_version: system::get_os_version(),
|
||||
windows_build_number: system::get_windows_build_number(),
|
||||
architecture: system::ARCH.to_string(),
|
||||
|
|
|
|||
4
third_party/rust/glean/src/lib.rs
vendored
4
third_party/rust/glean/src/lib.rs
vendored
|
|
@ -36,8 +36,8 @@ pub use configuration::{Builder as ConfigurationBuilder, Configuration};
|
|||
pub use core_metrics::ClientInfoMetrics;
|
||||
pub use glean_core::{
|
||||
metrics::{Datetime, DistributionData, MemoryUnit, Rate, RecordedEvent, TimeUnit, TimerId},
|
||||
traits, CommonMetricData, Error, ErrorType, Glean, HistogramType, Lifetime, RecordedExperiment,
|
||||
Result,
|
||||
traits, CommonMetricData, Error, ErrorType, Glean, HistogramType, Lifetime, PingRateLimit,
|
||||
RecordedExperiment, Result,
|
||||
};
|
||||
|
||||
mod configuration;
|
||||
|
|
|
|||
23
third_party/rust/glean/src/net/mod.rs
vendored
23
third_party/rust/glean/src/net/mod.rs
vendored
|
|
@ -138,9 +138,26 @@ impl UploadManager {
|
|||
Ordering::SeqCst,
|
||||
Ordering::SeqCst,
|
||||
);
|
||||
})
|
||||
.expect("Failed to spawn Glean's uploader thread");
|
||||
*handle = Some(thread);
|
||||
});
|
||||
|
||||
match thread {
|
||||
Ok(thread) => *handle = Some(thread),
|
||||
Err(err) => {
|
||||
log::warn!("Failed to spawn Glean's uploader thread. This will be retried on next upload. Error: {err}");
|
||||
// Swapping back the thread state. We're the ones setting it to `Running`, so
|
||||
// should be able to set it back.
|
||||
let state_change = self.inner.thread_running.compare_exchange(
|
||||
State::Running,
|
||||
State::Stopped,
|
||||
Ordering::SeqCst,
|
||||
Ordering::SeqCst,
|
||||
);
|
||||
|
||||
if state_change.is_err() {
|
||||
log::warn!("Failed to swap back thread state. Someone else jumped in and changed the state.");
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
pub(crate) fn shutdown(&self) {
|
||||
|
|
|
|||
2
third_party/rust/glean/src/test.rs
vendored
2
third_party/rust/glean/src/test.rs
vendored
|
|
@ -1319,7 +1319,7 @@ fn configure_ping_throttling() {
|
|||
})
|
||||
.build();
|
||||
let pings_per_interval = 10;
|
||||
cfg.rate_limit = Some(glean_core::PingRateLimit {
|
||||
cfg.rate_limit = Some(crate::PingRateLimit {
|
||||
seconds_per_interval: 1,
|
||||
pings_per_interval,
|
||||
});
|
||||
|
|
|
|||
1
third_party/rust/glean/tests/common/mod.rs
vendored
1
third_party/rust/glean/tests/common/mod.rs
vendored
|
|
@ -45,6 +45,7 @@ pub fn initialize(cfg: Configuration) {
|
|||
app_build: "1.0.0".to_string(),
|
||||
app_display_version: "1.0.0".to_string(),
|
||||
channel: Some("testing".to_string()),
|
||||
locale: Some("xx-XX".to_string()),
|
||||
};
|
||||
|
||||
glean::initialize(cfg, client_info);
|
||||
|
|
|
|||
1
third_party/rust/glean/tests/schema.rs
vendored
1
third_party/rust/glean/tests/schema.rs
vendored
|
|
@ -84,6 +84,7 @@ fn validate_against_schema() {
|
|||
app_build: env!("CARGO_PKG_VERSION").to_string(),
|
||||
app_display_version: env!("CARGO_PKG_VERSION").to_string(),
|
||||
channel: Some("testing".to_string()),
|
||||
locale: Some("xx-XX".to_string()),
|
||||
};
|
||||
|
||||
glean::initialize(cfg, client_info);
|
||||
|
|
|
|||
32
third_party/rust/glean/tests/test-thread-crashing.sh
vendored
Executable file
32
third_party/rust/glean/tests/test-thread-crashing.sh
vendored
Executable file
|
|
@ -0,0 +1,32 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Test harness for testing the RLB processes from the outside.
|
||||
#
|
||||
# Some behavior can only be observed when properly exiting the process running Glean,
|
||||
# e.g. when an uploader runs in another thread.
|
||||
# On exit the threads will be killed, regardless of their state.
|
||||
|
||||
# Remove the temporary data path on all exit conditions
|
||||
cleanup() {
|
||||
if [ -n "$datapath" ]; then
|
||||
rm -r "$datapath"
|
||||
fi
|
||||
}
|
||||
trap cleanup INT ABRT TERM EXIT
|
||||
|
||||
tmp="${TMPDIR:-/tmp}"
|
||||
datapath=$(mktemp -d "${tmp}/glean_long_running.XXXX")
|
||||
|
||||
RUSTFLAGS="-C panic=abort" \
|
||||
RUST_LOG=debug \
|
||||
cargo run --example crashing-threads -- "$datapath"
|
||||
ret=$?
|
||||
count=$(ls -1q "$datapath/pending_pings" | wc -l)
|
||||
|
||||
if [[ $ret -eq 0 ]] && [[ "$count" -eq 1 ]]; then
|
||||
echo "test result: ok."
|
||||
exit 0
|
||||
else
|
||||
echo "test result: FAILED."
|
||||
exit 101
|
||||
fi
|
||||
|
|
@ -6,7 +6,7 @@ edition = "2018"
|
|||
license = "MPL-2.0"
|
||||
|
||||
[dependencies]
|
||||
glean = "53.1.0"
|
||||
glean = "53.2.0"
|
||||
log = "0.4"
|
||||
nserror = { path = "../../../xpcom/rust/nserror" }
|
||||
nsstring = { path = "../../../xpcom/rust/nsstring" }
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ license = "MPL-2.0"
|
|||
[dependencies]
|
||||
bincode = "1.0"
|
||||
chrono = "0.4.10"
|
||||
glean = "53.1.0"
|
||||
glean = "53.2.0"
|
||||
inherent = "1.0.0"
|
||||
log = "0.4"
|
||||
nsstring = { path = "../../../../xpcom/rust/nsstring", optional = true }
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ fn setup_glean(tempdir: Option<tempfile::TempDir>) -> tempfile::TempDir {
|
|||
app_build: "test-build".into(),
|
||||
app_display_version: "1.2.3".into(),
|
||||
channel: None,
|
||||
locale: None,
|
||||
};
|
||||
|
||||
glean::test_reset_glean(cfg, client_info, true);
|
||||
|
|
|
|||
|
|
@ -10,7 +10,9 @@ use std::path::PathBuf;
|
|||
use firefox_on_glean::{metrics, pings};
|
||||
use nserror::{nsresult, NS_ERROR_FAILURE};
|
||||
use nsstring::{nsACString, nsCString, nsString};
|
||||
use xpcom::interfaces::{nsIFile, nsIPrefService, nsIProperties, nsIXULAppInfo, nsIXULRuntime};
|
||||
use xpcom::interfaces::{
|
||||
mozILocaleService, nsIFile, nsIPrefService, nsIProperties, nsIXULAppInfo, nsIXULRuntime,
|
||||
};
|
||||
use xpcom::{RefPtr, XpCom};
|
||||
|
||||
use glean::{ClientInfoMetrics, Configuration};
|
||||
|
|
@ -127,12 +129,13 @@ fn build_configuration(
|
|||
};
|
||||
let data_path = PathBuf::from(&data_path_str);
|
||||
|
||||
let (app_build, app_display_version, channel) = get_app_info()?;
|
||||
let (app_build, app_display_version, channel, locale) = get_app_info()?;
|
||||
|
||||
let client_info = ClientInfoMetrics {
|
||||
app_build,
|
||||
app_display_version,
|
||||
channel: Some(channel),
|
||||
locale: Some(locale),
|
||||
};
|
||||
log::debug!("Client Info: {:#?}", client_info);
|
||||
|
||||
|
|
@ -220,16 +223,18 @@ fn get_data_path() -> Result<String, nsresult> {
|
|||
Ok(data_path)
|
||||
}
|
||||
|
||||
/// Return a tuple of the build_id, app version, and build channel.
|
||||
/// Return a tuple of the build_id, app version, build channel, and locale.
|
||||
/// If the XUL Runtime isn't a XULAppInfo (e.g. in xpcshell),
|
||||
/// build_id ad app_version will be "unknown".
|
||||
/// Other problems result in an error being returned instead.
|
||||
fn get_app_info() -> Result<(String, String, String), nsresult> {
|
||||
fn get_app_info() -> Result<(String, String, String, String), nsresult> {
|
||||
let xul: RefPtr<nsIXULRuntime> =
|
||||
xpcom::components::XULRuntime::service().map_err(|_| NS_ERROR_FAILURE)?;
|
||||
|
||||
let pref_service: RefPtr<nsIPrefService> =
|
||||
xpcom::components::Preferences::service().map_err(|_| NS_ERROR_FAILURE)?;
|
||||
let locale_service: RefPtr<mozILocaleService> =
|
||||
xpcom::components::Locale::service().map_err(|_| NS_ERROR_FAILURE)?;
|
||||
let branch = xpcom::getter_addrefs(|p| {
|
||||
// Safe because:
|
||||
// * `null` is explicitly allowed per documentation
|
||||
|
|
@ -261,6 +266,7 @@ fn get_app_info() -> Result<(String, String, String), nsresult> {
|
|||
"unknown".to_owned(),
|
||||
"unknown".to_owned(),
|
||||
channel.to_string(),
|
||||
"unknown".to_owned(),
|
||||
))
|
||||
}
|
||||
};
|
||||
|
|
@ -275,10 +281,18 @@ fn get_app_info() -> Result<(String, String, String), nsresult> {
|
|||
app_info.GetVersion(&mut *version).to_result()?;
|
||||
}
|
||||
|
||||
let mut locale = nsCString::new();
|
||||
unsafe {
|
||||
locale_service
|
||||
.GetAppLocaleAsBCP47(&mut *locale)
|
||||
.to_result()?;
|
||||
}
|
||||
|
||||
Ok((
|
||||
build_id.to_string(),
|
||||
version.to_string(),
|
||||
channel.to_string(),
|
||||
locale.to_string(),
|
||||
))
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue