| # Copyright 2017 The Chromium Authors |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| |
| """Functions for populating enums with ukm events.""" |
| |
| from collections import namedtuple |
| import os |
| import sys |
| import xml.dom.minidom |
| |
| import extract_histograms |
| |
| sys.path.append(os.path.join(os.path.dirname(__file__), '..', 'ukm')) |
| import codegen |
| |
| |
| EventDetails = namedtuple("EventDetails", "name hash is_obsolete") |
| |
| |
| def _GetEventDetails(event): |
| """Returns a simple struct containing the event details. |
| |
| Args: |
| event: An event description as defined in ukm.xml. |
| |
| Returns: |
| A struct containing the event name, truncated hash, and whether the event is |
| considered obsolete. |
| """ |
| name = event.getAttribute('name') |
| # The value is UKM event name hash truncated to 31 bits. This is recorded in |
| # https://cs.chromium.org/chromium/src/components/ukm/ukm_recorder_impl.cc?q=LogEventHashasUmaHistogram |
| hash = codegen.HashName(name) & 0x7fffffff |
| |
| def _HasDirectObsoleteTag(node): |
| return any( |
| isinstance(child, xml.dom.minidom.Element) |
| and child.tagName == 'obsolete' for child in node.childNodes) |
| |
| # The UKM event is considered obsolete if the event itself is marked as |
| # obsolete with a tag or all of its metrics are marked as obsolete. |
| is_event_obsolete = _HasDirectObsoleteTag(event) |
| are_all_metrics_obsolete = all( |
| _HasDirectObsoleteTag(metric) |
| for metric in event.getElementsByTagName('metric')) |
| |
| return EventDetails(name=name, |
| hash=hash, |
| is_obsolete=is_event_obsolete or are_all_metrics_obsolete) |
| |
| |
| def PopulateEnumWithUkmEvents(doc, enum, ukm_events): |
| """Populates the enum node with a list of ukm events. |
| |
| Args: |
| doc: The document to create the node in. |
| enum: The enum node needed to be populated. |
| ukm_events: A list of ukm event nodes. |
| """ |
| event_details = [_GetEventDetails(event) for event in ukm_events] |
| event_details.sort(key=lambda event: event.hash) |
| |
| for event in event_details: |
| node = doc.createElement('int') |
| node.attributes['value'] = str(event.hash) |
| label = event.name |
| # If the event is obsolete, mark it in the int's label. |
| if event.is_obsolete: |
| label += ' (Obsolete)' |
| node.attributes['label'] = label |
| enum.appendChild(node) |
| |
| |
| def PopulateEnumsWithUkmEvents(doc, enums, ukm_events): |
| """Populates enum nodes in the enums with a list of ukm events |
| |
| Args: |
| doc: The document to create the node in. |
| enums: The enums node to be iterated. |
| ukm_events: A list of ukm event nodes. |
| """ |
| for enum in extract_histograms.IterElementsWithTag(enums, 'enum', 1): |
| # We only special case 'UkmEventNameHash' currently. |
| if enum.getAttribute('name') == 'UkmEventNameHash': |
| PopulateEnumWithUkmEvents(doc, enum, ukm_events) |