def main(): """Prints the owners of histograms in a specific file or of all histograms. Args: argv[1]: Optional argument that is the relative path to a specific histograms.xml. Example usage to print owners of metadata/Accessibility/histograms.xml: python histogram_ownership.py metadata/Accessibility/histograms.xml Example usage to print owners of all histograms: python histogram_ownership.py """ if len(sys.argv) == 1: merged_xml_string = merge_xml.MergeFiles( histogram_paths.ALL_XMLS, should_expand_owners=True).toxml() root = ET.fromstring(merged_xml_string) else: rel_path = path_util.GetInputFile( os.path.join('tools', 'metrics', 'histograms', sys.argv[1])) if not os.path.exists(rel_path): raise ValueError("A histograms.xml file does not exist in %s" % rel_path) tree = ET.parse(rel_path) root = tree.getroot() PrintOwners(root)
def _GenerateFile(arguments): """Generates header file containing array with hashes of expired histograms. Args: arguments: An object with the following attributes: arguments.inputs: A list of xml files with histogram descriptions. arguments.header_filename: A filename of the generated header file. arguments.namespace: A namespace to contain generated array. arguments.output_dir: A directory to put the generated file. arguments.major_branch_date_filepath: File path for base date. arguments.milestone_filepath: File path for milestone information. """ # Assert that the |--inputs| is the same as |histogram_paths.ALL_XMLS| to make # sure we have the most updated list of histogram descriptions. Otherwise, # inform the cl owner to update the --inputs. to_add, to_remove = CheckUnsyncedHistograms(arguments.inputs) assert len(to_add) == 0 and len(to_remove) == 0, ( "The --inputs is not in sync with the most updated list of xmls. Please " "update the inputs in " "components/metrics/generate_expired_histograms_array.gni.\n" " add: %s\n remove: %s" % (', '.join(to_add), ', '.join(to_remove))) descriptions = merge_xml.MergeFiles(arguments.inputs) with open(arguments.major_branch_date_filepath, "r") as date_file: branch_file_content = date_file.read() with open(arguments.milestone_filepath, "r") as milestone_file: mstone_file_content = milestone_file.read() header_file_content = _GenerateFileContent( descriptions, branch_file_content, mstone_file_content, arguments.header_filename, arguments.namespace) with open(os.path.join(arguments.output_dir, arguments.header_filename), "w") as generated_file: generated_file.write(header_file_content)
def _GenerateFile(arguments): """Generates header file containing array with hashes of expired histograms. Args: arguments: An object with the following attributes: arguments.inputs: A list of xml files with histogram descriptions. arguments.header_filename: A filename of the generated header file. arguments.namespace: A namespace to contain generated array. arguments.hash_datatype: Datatype of histogram names' hash. arguments.output_dir: A directory to put the generated file. Raises: Error if there is an error in input xml files. """ descriptions = merge_xml.MergeFiles(arguments.inputs) histograms, had_errors = ( extract_histograms.ExtractHistogramsFromDom(descriptions)) if had_errors: raise Error("Error parsing inputs.") with open(arguments.major_branch_date_filepath, "r") as date_file: file_content = date_file.read() base_date = _GetBaseDate(file_content, _DATE_FILE_PATTERN) expired_histograms_names = _GetExpiredHistograms(histograms, base_date) expired_histograms_map = _GetHashToNameMap(expired_histograms_names) header_file_content = _GenerateHeaderFileContent(arguments.header_filename, arguments.namespace, expired_histograms_map) with open(os.path.join(arguments.output_dir, arguments.header_filename), "w") as generated_file: generated_file.write(header_file_content)
def _GenerateFile(arguments): """Generates header file containing array with hashes of expired histograms. Args: arguments: An object with the following attributes: arguments.inputs: A list of xml files with histogram descriptions. arguments.header_filename: A filename of the generated header file. arguments.namespace: A namespace to contain generated array. arguments.output_dir: A directory to put the generated file. arguments.major_branch_date_filepath: File path for base date. arguments.milestone_filepath: File path for milestone information. """ descriptions = merge_xml.MergeFiles(arguments.inputs) with open(arguments.major_branch_date_filepath, "r") as date_file: branch_file_content = date_file.read() with open(arguments.milestone_filepath, "r") as milestone_file: mstone_file_content = milestone_file.read() header_file_content = _GenerateFileContent(descriptions, branch_file_content, mstone_file_content, arguments.header_filename, arguments.namespace) with open(os.path.join(arguments.output_dir, arguments.header_filename), "w") as generated_file: generated_file.write(header_file_content)
def checkMetricTypeIsSpecified(self): """Check each metric is either specified with an enum or a unit.""" errors = [] warnings = [] enum_tree = merge_xml.MergeFiles([histogram_paths.ENUMS_XML]) enums, _ = extract_histograms.ExtractEnumsFromXmlTree(enum_tree) for event_node in self.config.getElementsByTagName('event'): for metric_node in event_node.getElementsByTagName('metric'): if metric_node.hasAttribute('enum'): enum_name = metric_node.getAttribute('enum') # Check if the enum is defined in enums.xml. if enum_name not in enums: errors.append( "Unknown enum %s in ukm metric %s:%s." % (enum_name, event_node.getAttribute('name'), metric_node.getAttribute('name'))) elif not metric_node.hasAttribute('unit'): warnings.append( "Warning: Neither \'enum\' or \'unit\' is specified " "for ukm metric %s:%s." % (event_node.getAttribute('name'), metric_node.getAttribute('name'))) isSuccess = not errors return (isSuccess, errors, warnings)
def main(): doc = merge_xml.MergeFiles(histogram_paths.ALL_XMLS) histograms, had_errors = extract_histograms.ExtractHistogramsFromDom(doc) if had_errors: raise Error("Error parsing inputs.") names = extract_histograms.ExtractNames(histograms) for name in names: print name
def readAllXmlHistograms(): """Parses all histogram names defined in |histogram_paths.ALL_XMLS|. Returns: A set containing the parsed histogram names. """ merged = merge_xml.MergeFiles(histogram_paths.ALL_XMLS) histograms, _ = extract_histograms.ExtractHistogramsFromDom(merged) return set(extract_histograms.ExtractNames(histograms))
def _ParseMergedXML(): """Parses merged xml into different types of nodes""" merged_histograms = merge_xml.MergeFiles(histogram_paths.HISTOGRAMS_XMLS + [histogram_paths.OBSOLETE_XML]) histogram_nodes = merged_histograms.getElementsByTagName('histogram') variants_nodes = merged_histograms.getElementsByTagName('variants') histogram_suffixes_nodes = merged_histograms.getElementsByTagName( 'histogram_suffixes') return histogram_nodes, variants_nodes, histogram_suffixes_nodes
def get_names(xml_files): """Returns all histogram names generated from a list of xml files. Args: xml_files: A list of open file objects containing histogram definitions. Returns: A tuple of (names, obsolete names), where the obsolete names is a subset of all names. """ doc = merge_xml.MergeFiles(files=xml_files) histograms, had_errors = extract_histograms.ExtractHistogramsFromDom(doc) if had_errors: raise ValueError("Error parsing inputs.") names = set(extract_histograms.ExtractNames(histograms)) obsolete_names = set(extract_histograms.ExtractObsoleteNames(histograms)) return (names, obsolete_names)
def main(args): # Extract all histograms into a dict. doc = merge_xml.MergeFiles(filenames=histogram_paths.ALL_XMLS, should_expand_owners=True) histograms, had_errors = extract_histograms.ExtractHistogramsFromDom(doc) if had_errors: raise ValueError("Error parsing inputs.") # Construct a dom tree that is similar to the normal histograms.xml so that # we can use histogram_configuration_model to pretty print it. doc = xml.dom.minidom.Document() configuration = doc.createElement('histogram-configuration') histograms_node = doc.createElement('histograms') for name, histogram in histograms.items(): if re.match(args.pattern, name): histograms_node.appendChild( ConstructHistogram(doc, name, histogram)) configuration.appendChild(histograms_node) doc.appendChild(configuration) print(histogram_configuration_model.PrettifyTree(doc))
def main(): doc = merge_xml.MergeFiles(histogram_paths.ALL_XMLS) _, errors = extract_histograms.ExtractHistogramsFromDom(doc) sys.exit(errors)
def testMergeFiles_WithXmlEvents(self): """Checks that the UkmEventNameHash enum is populated correctly. If ukm.xml is provided, populate a list of ints to the UkmEventNameHash enum where where each value is a xml event name hash truncated to 31 bits and each label is the corresponding event name. """ merged = merge_xml.MergeFiles(histogram_paths.ALL_TEST_XMLS) expected_merged = xml.dom.minidom.parseString(""" <histogram-configuration><enums> <enum name="Enum1"> <int label="Value0" value="0"/> <int label="Value1" value="1"/> </enum> <enum name="TestEnum"> <int label="Value0" value="0"/> <int label="Value1" value="1"/> </enum> <enum name="UkmEventNameHash"> <!-- Placeholder enum. The values are UKM event name hashes truncated to 31 bits. This gets populated by the GetEnumsNodes function in merge_xml.py when producing the merged XML file. --> <int label="AbusiveExperienceHeuristic.TabUnder" value="1621538456"/>\ <int label="Autofill.SelectedMaskedServerCard (Obsolete)" value="1913876024"/>\ </enum> </enums><histograms> <histogram name="Foo.Bar" units="xxxxxxxxxxxxxxxxxxyyyyyyyyyyyyyyyyyyyyyyzzzz"> <summary>Foo</summary> <owner>[email protected]</owner> <component>Component</component> </histogram> <histogram name="Test.Histogram" units="microseconds"> <obsolete> Removed 6/2020. </obsolete> <owner>[email protected]</owner> <summary> Summary 2 </summary> </histogram> <histogram name="Test.EnumHistogram" enum="TestEnum" expires_after="M81"> <owner>[email protected]</owner> <obsolete> Obsolete message </obsolete> <summary> A enum histogram. </summary> </histogram> </histograms><histogram_suffixes_list> <histogram_suffixes name="Test.HistogramSuffixes" separator="."> <suffix label="A histogram_suffixes" name="TestSuffix"/> <affected-histogram name="Test.Histogram"/> </histogram_suffixes> </histogram_suffixes_list></histogram-configuration> """) self.maxDiff = None self.assertEqual(expected_merged.toxml(), merged.toxml())
def testMergeFiles(self): """Checks that enums.xml and histograms.xml can merge successfully.""" merged = merge_xml.MergeFiles([ histogram_paths.TEST_ENUMS_XML, histogram_paths.TEST_HISTOGRAMS_XML ]) # If ukm.xml is not provided, there is no need to populate the # UkmEventNameHash enum. expected_merged = xml.dom.minidom.parseString(""" <histogram-configuration><enums> <enum name="Enum1"> <int label="Value0" value="0"/> <int label="Value1" value="1"/> </enum> <enum name="TestEnum"> <int label="Value0" value="0"/> <int label="Value1" value="1"/> </enum> <enum name="UkmEventNameHash"> <!-- Placeholder enum. The values are UKM event name hashes truncated to 31 bits. This gets populated by the GetEnumsNodes function in merge_xml.py when producing the merged XML file. --> </enum> </enums><histograms> <histogram name="Foo.Bar" units="xxxxxxxxxxxxxxxxxxyyyyyyyyyyyyyyyyyyyyyyzzzz"> <summary>Foo</summary> <owner>[email protected]</owner> <component>Component</component> </histogram> <histogram name="Test.Histogram" units="microseconds"> <obsolete> Removed 6/2020. </obsolete> <owner>[email protected]</owner> <summary> Summary 2 </summary> </histogram> <histogram name="Test.EnumHistogram" enum="TestEnum" expires_after="M81"> <owner>[email protected]</owner> <obsolete> Obsolete message </obsolete> <summary> A enum histogram. </summary> </histogram> </histograms><histogram_suffixes_list> <histogram_suffixes name="Test.HistogramSuffixes" separator="."> <suffix label="A histogram_suffixes" name="TestSuffix"/> <affected-histogram name="Test.Histogram"/> </histogram_suffixes> </histogram_suffixes_list></histogram-configuration> """) self.maxDiff = None self.assertEqual(expected_merged.toxml(), merged.toxml())
def main(): doc = merge_xml.MergeFiles(histogram_paths.ALL_XMLS, should_expand_owners=True) _, errors = extract_histograms.ExtractHistogramsFromDom(doc) sys.exit(errors)
def get_names(xml_files): doc = merge_xml.MergeFiles(files=xml_files) histograms, had_errors = extract_histograms.ExtractHistogramsFromDom(doc) if had_errors: raise Error("Error parsing inputs.") return extract_histograms.ExtractNames(histograms)