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