blob: b62b9e921c2f8609069382b3166c0759281ee52d [file] [log] [blame]
"""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)