"""Metrics reporting module for Blueberry using protobuf. Internal reference """ from __future__ import absolute_import from __future__ import division from __future__ import print_function import base64 import logging import time # Internal import class BluetoothMetricLogger(object): """A class used for gathering metrics from tests and devices. This class provides methods to allow test writers to easily export metrics from their tests as protobuf messages. Attributes: _metrics: The Bluetooth test proto message to add metrics to. """ def __init__(self, bluetooth_test_proto_message): self._metrics = bluetooth_test_proto_message self._start_time = int(time.time()) def add_primary_device_metrics(self, device): """Adds primary device metrics to the test proto message. Args: device: The Bluetooth device object to gather device metrics from. """ device_message = self._metrics.configuration_data.primary_device message_fields = device_message.DESCRIPTOR.fields_by_name.keys() try: device_metrics_dict = device.get_device_info() except AttributeError: logging.info( 'Must implement get_device_info method for this controller in order to upload device metrics.' ) return for metric in device_metrics_dict: if metric in message_fields: setattr(device_message, metric, device_metrics_dict[metric]) else: logging.info('%s is not a valid metric field.', metric) def add_connected_device_metrics(self, device): """Adds connected device metrics to the test proto message. Args: device: The Bluetooth device object to gather device metrics from. """ device_message = self._metrics.configuration_data.connected_device message_fields = device_message.DESCRIPTOR.fields_by_name.keys() try: device_metrics_dict = device.get_device_info() except AttributeError: logging.info( 'Must implement get_device_info method for this controller in order to upload device metrics.' ) return for metric in device_metrics_dict: if metric in message_fields: setattr(device_message, metric, device_metrics_dict[metric]) else: logging.warning('%s is not a valid metric field.', metric) def add_test_metrics(self, test_metrics_dict): """Adds test metrics to the test proto message. Args: test_metrics_dict: A dictionary of metrics to add to the test proto message. Metric will only be added if the key exists as a field in the test proto message. """ if hasattr(self._metrics, 'configuration_data'): self._metrics.configuration_data.test_date_time = self._start_time message_fields = self._metrics.DESCRIPTOR.fields_by_name.keys() for metric in test_metrics_dict: if metric in message_fields: metric_value = test_metrics_dict[metric] if isinstance(metric_value, (list, tuple)): getattr(self._metrics, metric).extend(metric_value) else: setattr(self._metrics, metric, metric_value) else: logging.warning('%s is not a valid metric field.', metric) def proto_message_to_base64(self): """Converts a proto message to a base64 string. Returns: string, Message formatted as a base64 string. """ return base64.b64encode(self._metrics.SerializeToString()).decode('utf-8') def proto_message_to_ascii(self): """Converts a proto message to an ASCII string. Returns: string, Message formatted as an ASCII string. Useful for debugging. """ return text_format.MessageToString(self._metrics)