1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147
|
# 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/.
# Write out a C++ enum definition whose members are the names of
# histograms as well as the following other members:
#
# - HistogramCount
# - HistogramFirstUseCounter
# - HistogramLastUseCounter
# - HistogramUseCounterCount
#
# The histograms are defined in files provided as command-line arguments.
import itertools
import sys
import buildconfig
from mozparsers import parse_histograms
from mozparsers.shared_telemetry_utils import ParserError
banner = """/* This file is auto-generated, see gen_histogram_enum.py. */
"""
header = """
#ifndef mozilla_TelemetryHistogramEnums_h
#define mozilla_TelemetryHistogramEnums_h
#include <cstdint>
#include <type_traits>
namespace mozilla {
namespace Telemetry {
"""
footer = """
} // namespace mozilla
} // namespace Telemetry
#endif // mozilla_TelemetryHistogramEnums_h"""
def get_histogram_typename(histogram):
name = histogram.name()
if name.startswith("USE_COUNTER2_"):
return "UseCounterWorker" if name.endswith("_WORKER") else "UseCounter"
return None
def main(output, *filenames):
# Print header.
print(banner, file=output)
print(header, file=output)
# Load the histograms.
try:
all_histograms = list(parse_histograms.from_files(filenames))
except ParserError as ex:
print("\nError processing histograms:\n" + str(ex) + "\n")
sys.exit(1)
groups = itertools.groupby(all_histograms, get_histogram_typename)
# Print the histogram enums.
# Note that parse_histograms.py guarantees that all of the
# USE_COUNTER2_*_WORKER and USE_COUNTER2_* histograms are both defined in a
# contiguous block.
print("enum HistogramID : uint32_t {", file=output)
seen_group_types = {"UseCounter": False, "UseCounterWorker": False}
for (group_type, histograms) in groups:
if group_type is not None:
assert isinstance(group_type, str)
assert group_type in seen_group_types.keys()
assert not seen_group_types[group_type]
seen_group_types[group_type] = True
# The Histogram*DUMMY enum variables are used to make the computation
# of Histogram{First,Last}* easier. Otherwise, we'd have to special
# case the first and last histogram in the group.
print(" HistogramFirst%s," % group_type, file=output)
print(
" Histogram{0}DUMMY1 = HistogramFirst{0} - 1,".format(group_type),
file=output,
)
for histogram in histograms:
if histogram.record_on_os(buildconfig.substs["OS_TARGET"]):
print(" %s," % histogram.name(), file=output)
if group_type is not None:
assert isinstance(group_type, str)
print(" Histogram%sDUMMY2," % group_type, file=output)
print(
" HistogramLast{0} = Histogram{0}DUMMY2 - 1,".format(group_type),
file=output,
)
print(" HistogramCount,", file=output)
for (key, value) in sorted(seen_group_types.items()):
if value:
print(
" Histogram{0}Count = HistogramLast{0} - HistogramFirst{0} + 1,".format(
key
),
file=output,
)
else:
print(" HistogramFirst%s = 0," % key, file=output)
print(" HistogramLast%s = 0," % key, file=output)
print(" Histogram%sCount = 0," % key, file=output)
print("};", file=output)
# Write categorical label enums.
categorical = filter(lambda h: h.kind() == "categorical", all_histograms)
categorical = filter(
lambda h: h.record_on_os(buildconfig.substs["OS_TARGET"]), categorical
)
enums = [("LABELS_" + h.name(), h.labels(), h.name()) for h in categorical]
for name, labels, _ in enums:
print("\nenum class %s : uint32_t {" % name, file=output)
print(" %s" % ",\n ".join(labels), file=output)
print("};", file=output)
print(
"\ntemplate<class T> struct IsCategoricalLabelEnum : std::false_type {};",
file=output,
)
for name, _, _ in enums:
print(
"template<> struct IsCategoricalLabelEnum<%s> : std::true_type {};" % name,
file=output,
)
print("\ntemplate<class T> struct CategoricalLabelId {};", file=output)
for name, _, id in enums:
print(
"template<> struct CategoricalLabelId<%s> : "
"std::integral_constant<uint32_t, %s> {};" % (name, id),
file=output,
)
# Footer.
print(footer, file=output)
if __name__ == "__main__":
main(sys.stdout, *sys.argv[1:])
|