Bug 1941046 - Part 4: Send a callback request for impression and clicks of MARS Top...
[gecko.git] / toolkit / components / telemetry / build_scripts / mozparsers / shared_telemetry_utils.py
blob80ae685c45a61b808b6848627cb806f7d43d4b73
1 # This Source Code Form is subject to the terms of the Mozilla Public
2 # License, v. 2.0. If a copy of the MPL was not distributed with this
3 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
5 # This file contains utility functions shared by the scalars and the histogram generation
6 # scripts.
8 import os
9 import re
10 import sys
12 import yaml
14 # This is a list of flags that determine which process a measurement is allowed
15 # to record from.
16 KNOWN_PROCESS_FLAGS = {
17 "all": "All",
18 "all_children": "AllChildren",
19 "main": "Main",
20 "content": "Content",
21 "gpu": "Gpu",
22 "rdd": "Rdd",
23 "socket": "Socket",
24 "utility": "Utility",
25 # Historical Values
26 "all_childs": "AllChildren", # Supporting files from before bug 1363725
29 SUPPORTED_PRODUCTS = {
30 "firefox": "Firefox",
31 "fennec": "Fennec",
32 "thunderbird": "Thunderbird",
33 # Historical, deprecated values:
34 # 'geckoview': 'Geckoview',
35 # "geckoview_streaming": "GeckoviewStreaming",
38 SUPPORTED_OPERATING_SYSTEMS = [
39 "mac",
40 "linux",
41 "windows",
42 "android",
43 "unix",
44 "all",
47 # mozinfo identifies linux, BSD variants, Solaris and SunOS as unix
48 # Solaris and SunOS are identified as "unix" OS.
49 UNIX_LIKE_OS = [
50 "unix",
51 "linux",
52 "bsd",
55 CANONICAL_OPERATING_SYSTEMS = {
56 "darwin": "mac",
57 "linux": "linux",
58 "winnt": "windows",
59 "android": "android",
60 # for simplicity we treat all BSD and Solaris systems as unix
61 "gnu/kfreebsd": "unix",
62 "sunos": "unix",
63 "dragonfly": "unix",
64 "freeunix": "unix",
65 "netunix": "unix",
66 "openunix": "unix",
69 PROCESS_ENUM_PREFIX = "mozilla::Telemetry::Common::RecordedProcessType::"
70 PRODUCT_ENUM_PREFIX = "mozilla::Telemetry::Common::SupportedProduct::"
73 class ParserError(Exception):
74 """Thrown by different probe parsers. Errors are partitioned into
75 'immediately fatal' and 'eventually fatal' so that the parser can print
76 multiple error messages at a time. See bug 1401612 ."""
78 eventual_errors = []
80 def __init__(self, *args):
81 Exception.__init__(self, *args)
83 def handle_later(self):
84 ParserError.eventual_errors.append(self)
86 def handle_now(self):
87 ParserError.print_eventuals()
88 print(str(self), file=sys.stderr)
89 sys.stderr.flush()
90 os._exit(1)
92 @classmethod
93 def print_eventuals(cls):
94 while cls.eventual_errors:
95 print(str(cls.eventual_errors.pop(0)), file=sys.stderr)
97 @classmethod
98 def exit_func(cls):
99 if cls.eventual_errors:
100 cls("Some errors occurred").handle_now()
103 def is_valid_process_name(name):
104 return name in KNOWN_PROCESS_FLAGS
107 def process_name_to_enum(name):
108 return PROCESS_ENUM_PREFIX + KNOWN_PROCESS_FLAGS.get(name)
111 def is_valid_product(name):
112 return name in SUPPORTED_PRODUCTS
115 def is_valid_os(name):
116 return name in SUPPORTED_OPERATING_SYSTEMS
119 def canonical_os(os):
120 """Translate possible OS_TARGET names to their canonical value."""
122 return CANONICAL_OPERATING_SYSTEMS.get(os.lower()) or "unknown"
125 def product_name_to_enum(product):
126 if not is_valid_product(product):
127 raise ParserError("Invalid product {}".format(product))
128 return PRODUCT_ENUM_PREFIX + SUPPORTED_PRODUCTS.get(product)
131 def static_assert(output, expression, message):
132 """Writes a C++ compile-time assertion expression to a file.
133 :param output: the output stream.
134 :param expression: the expression to check.
135 :param message: the string literal that will appear if the expression evaluates to
136 false.
138 print('static_assert(%s, "%s");' % (expression, message), file=output)
141 def validate_expiration_version(expiration):
142 """Makes sure the expiration version has the expected format.
144 Allowed examples: "10", "20", "60", "never"
145 Disallowed examples: "Never", "asd", "4000000", "60a1", "30.5a1"
147 :param expiration: the expiration version string.
148 :return: True if the expiration validates correctly, False otherwise.
150 if expiration != "never" and not re.match(r"^\d{1,3}$", expiration):
151 return False
153 return True
156 def add_expiration_postfix(expiration):
157 """Formats the expiration version and adds a version postfix if needed.
159 :param expiration: the expiration version string.
160 :return: the modified expiration string.
162 if re.match(r"^[1-9][0-9]*$", expiration):
163 return expiration + ".0a1"
165 if re.match(r"^[1-9][0-9]*\.0$", expiration):
166 return expiration + "a1"
168 return expiration
171 def load_yaml_file(filename):
172 """Load a YAML file from disk, throw a ParserError on failure."""
173 try:
174 with open(filename, "r") as f:
175 return yaml.safe_load(f)
176 except IOError as e:
177 raise ParserError("Error opening " + filename + ": " + str(e))
178 except ValueError as e:
179 raise ParserError("Error parsing processes in {}: {}".format(filename, e))