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 # Write out event information for C++. The events are defined
6 # in a file provided as a command-line argument.
11 from collections
import OrderedDict
14 from mozparsers
import parse_events
15 from mozparsers
.shared_telemetry_utils
import ParserError
, static_assert
17 COMPONENTS_PATH
= path
.abspath(
18 path
.join(path
.dirname(__file__
), path
.pardir
, path
.pardir
)
21 path
.join(COMPONENTS_PATH
, "glean", "build_scripts", "glean_parser_ext")
23 from string_table
import StringTable
25 # The banner/text at the top of the generated file.
26 banner
= """/* This file is auto-generated, only for internal use in TelemetryEvent.h,
27 see gen_event_data.py. */
31 #ifndef mozilla_TelemetryEventData_h
32 #define mozilla_TelemetryEventData_h
33 #include "core/EventInfo.h"
34 #include "nsITelemetry.h"
40 #endif // mozilla_TelemetryEventData_h
44 def write_extra_table(events
, output
, string_table
):
45 table_name
= "gExtraKeysTable"
49 print("#if defined(_MSC_VER) && !defined(__clang__)", file=output
)
50 print("const uint32_t %s[] = {" % table_name
, file=output
)
51 print("#else", file=output
)
52 print("constexpr uint32_t %s[] = {" % table_name
, file=output
)
53 print("#endif", file=output
)
57 extra_keys
= e
.extra_keys
58 if len(extra_keys
) > 0:
59 extra_index
= extra_count
60 extra_count
+= len(extra_keys
)
61 indexes
= string_table
.stringIndexes(extra_keys
)
65 % (e
.category
, ", ".join(e
.methods
), ", ".join(e
.objects
)),
68 print(" // extra_keys: %s" % ", ".join(extra_keys
), file=output
)
69 print(" %s," % ", ".join(map(str, indexes
)), file=output
)
71 extra_table
.append((extra_index
, len(extra_keys
)))
73 print("};", file=output
)
74 static_assert(output
, "sizeof(%s) <= UINT32_MAX" % table_name
, "index overflow")
79 def write_common_event_table(events
, output
, string_table
, extra_table
):
80 table_name
= "gCommonEventInfo"
82 print("#if defined(_MSC_VER) && !defined(__clang__)", file=output
)
83 print("const CommonEventInfo %s[] = {" % table_name
, file=output
)
84 print("#else", file=output
)
85 print("constexpr CommonEventInfo %s[] = {" % table_name
, file=output
)
86 print("#endif", file=output
)
88 for e
, extras
in zip(events
, extra_table
):
89 # Write a comment to make the file human-readable.
90 print(" // category: %s" % e
.category
, file=output
)
91 print(" // methods: [%s]" % ", ".join(e
.methods
), file=output
)
92 print(" // objects: [%s]" % ", ".join(e
.objects
), file=output
)
94 # Write the common info structure
96 " {%d, %d, %d, %d, %s, %s, %s },"
98 string_table
.stringIndex(e
.category
),
99 string_table
.stringIndex(e
.expiry_version
),
100 extras
[0], # extra keys index
101 extras
[1], # extra keys count
103 " | ".join(e
.record_in_processes_enum
),
104 " | ".join(e
.products_enum
),
109 print("};", file=output
)
110 static_assert(output
, "sizeof(%s) <= UINT32_MAX" % table_name
, "index overflow")
113 def write_event_table(events
, output
, string_table
):
114 table_name
= "gEventInfo"
116 print("#if defined(_MSC_VER) && !defined(__clang__)", file=output
)
117 print("const EventInfo %s[] = {" % table_name
, file=output
)
118 print("#else", file=output
)
119 print("constexpr EventInfo %s[] = {" % table_name
, file=output
)
120 print("#endif", file=output
)
122 for common_info_index
, e
in enumerate(events
):
123 for method_name
, object_name
in itertools
.product(e
.methods
, e
.objects
):
125 " // category: %s, method: %s, object: %s"
126 % (e
.category
, method_name
, object_name
),
131 " {gCommonEventInfo[%d], %d, %d},"
134 string_table
.stringIndex(method_name
),
135 string_table
.stringIndex(object_name
),
140 print("};", file=output
)
141 static_assert(output
, "sizeof(%s) <= UINT32_MAX" % table_name
, "index overflow")
144 def generate_JSON_definitions(output
, *filenames
):
145 """Write the event definitions to a JSON file.
147 :param output: the file to write the content to.
148 :param filenames: a list of filenames provided by the build system.
149 We only support a single file.
151 # Load the event data.
153 for filename
in filenames
:
155 batch
= parse_events
.load_events(filename
, True)
157 except ParserError
as ex
:
158 print("\nError processing %s:\n%s\n" % (filename
, str(ex
)), file=sys
.stderr
)
161 event_definitions
= OrderedDict()
163 category
= event
.category
165 if category
not in event_definitions
:
166 event_definitions
[category
] = OrderedDict()
168 event_definitions
[category
][event
.name
] = OrderedDict(
170 "methods": event
.methods
,
171 "objects": event
.objects
,
172 "extra_keys": event
.extra_keys
,
173 "record_on_release": (
174 True if event
.dataset_short
== "opt-out" else False
176 # We don't expire dynamic-builtin scalars: they're only meant for
177 # use in local developer builds anyway. They will expire when rebuilding.
178 "expires": event
.expiry_version
,
180 "products": event
.products
,
184 json
.dump(event_definitions
, output
, sort_keys
=True)
187 def main(output
, *filenames
):
188 # Load the event data.
190 for filename
in filenames
:
192 batch
= parse_events
.load_events(filename
, True)
194 except ParserError
as ex
:
195 print("\nError processing %s:\n%s\n" % (filename
, str(ex
)), file=sys
.stderr
)
198 # Write the scalar data file.
199 print(banner
, file=output
)
200 print(file_header
, file=output
)
202 # Write the extra keys table.
203 string_table
= StringTable()
204 extra_table
= write_extra_table(events
, output
, string_table
)
205 print("", file=output
)
207 # Write a table with the common event data.
208 write_common_event_table(events
, output
, string_table
, extra_table
)
209 print("", file=output
)
211 # Write the data for individual events.
212 write_event_table(events
, output
, string_table
)
213 print("", file=output
)
215 # Write the string table.
216 string_table_name
= "gEventsStringTable"
217 string_table
.writeDefinition(output
, string_table_name
)
219 output
, "sizeof(%s) <= UINT32_MAX" % string_table_name
, "index overflow"
221 print("", file=output
)
223 print(file_footer
, file=output
)
226 if __name__
== "__main__":
227 main(sys
.stdout
, *sys
.argv
[1:])