165 lines
5.1 KiB
Python
165 lines
5.1 KiB
Python
# Copyright 2018, The Android Open Source Project
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
# you may not use this file except in compliance with the License.
|
|
# You may obtain a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
# See the License for the specific language governing permissions and
|
|
# limitations under the License.
|
|
|
|
"""
|
|
Utility functions for metrics.
|
|
"""
|
|
|
|
import os
|
|
import platform
|
|
import sys
|
|
import time
|
|
import traceback
|
|
|
|
from atest.metrics import metrics
|
|
from atest.metrics import metrics_base
|
|
|
|
CONTENT_LICENSES_URL = 'https://source.android.com/setup/start/licenses'
|
|
CONTRIBUTOR_AGREEMENT_URL = {
|
|
'INTERNAL': 'https://cla.developers.google.com/',
|
|
'EXTERNAL': 'https://opensource.google.com/docs/cla/'
|
|
}
|
|
PRIVACY_POLICY_URL = 'https://policies.google.com/privacy'
|
|
TERMS_SERVICE_URL = 'https://policies.google.com/terms'
|
|
|
|
|
|
def static_var(varname, value):
|
|
"""Decorator to cache static variable."""
|
|
def fun_var_decorate(func):
|
|
"""Set the static variable in a function."""
|
|
setattr(func, varname, value)
|
|
return func
|
|
return fun_var_decorate
|
|
|
|
|
|
@static_var("start_time", [])
|
|
def get_start_time():
|
|
"""Get start time.
|
|
|
|
Return:
|
|
start_time: Start time in seconds. Return cached start_time if exists,
|
|
time.time() otherwise.
|
|
"""
|
|
if not get_start_time.start_time:
|
|
get_start_time.start_time = time.time()
|
|
return get_start_time.start_time
|
|
|
|
|
|
def convert_duration(diff_time_sec):
|
|
"""Compute duration from time difference.
|
|
|
|
A Duration represents a signed, fixed-length span of time represented
|
|
as a count of seconds and fractions of seconds at nanosecond
|
|
resolution.
|
|
|
|
Args:
|
|
diff_time_sec: The time in seconds as a floating point number.
|
|
|
|
Returns:
|
|
A dict of Duration.
|
|
"""
|
|
seconds = int(diff_time_sec)
|
|
nanos = int((diff_time_sec - seconds)*10**9)
|
|
return {'seconds': seconds, 'nanos': nanos}
|
|
|
|
|
|
# pylint: disable=broad-except
|
|
def handle_exc_and_send_exit_event(exit_code):
|
|
"""handle exceptions and send exit event.
|
|
|
|
Args:
|
|
exit_code: An integer of exit code.
|
|
"""
|
|
stacktrace = logs = ''
|
|
try:
|
|
exc_type, exc_msg, _ = sys.exc_info()
|
|
stacktrace = traceback.format_exc()
|
|
if exc_type:
|
|
logs = '{etype}: {value}'.format(etype=exc_type.__name__,
|
|
value=exc_msg)
|
|
except Exception:
|
|
pass
|
|
send_exit_event(exit_code, stacktrace=stacktrace, logs=logs)
|
|
|
|
|
|
def send_exit_event(exit_code, stacktrace='', logs=''):
|
|
"""Log exit event and flush all events to clearcut.
|
|
|
|
Args:
|
|
exit_code: An integer of exit code.
|
|
stacktrace: A string of stacktrace.
|
|
logs: A string of logs.
|
|
"""
|
|
clearcut = metrics.AtestExitEvent(
|
|
duration=convert_duration(time.time()-get_start_time()),
|
|
exit_code=exit_code,
|
|
stacktrace=stacktrace,
|
|
logs=str(logs))
|
|
# pylint: disable=no-member
|
|
if clearcut:
|
|
clearcut.flush_events()
|
|
|
|
|
|
def send_start_event(tool_name, command_line='', test_references='',
|
|
cwd=None, operating_system=None):
|
|
"""Log start event of clearcut.
|
|
|
|
Args:
|
|
tool_name: A string of the asuite product name.
|
|
command_line: A string of the user input command.
|
|
test_references: A string of the input tests.
|
|
cwd: A string of current path.
|
|
operating_system: A string of user's operating system.
|
|
"""
|
|
if not cwd:
|
|
cwd = os.getcwd()
|
|
if not operating_system:
|
|
operating_system = platform.platform()
|
|
# Without tool_name information, asuite's clearcut client will not send
|
|
# event to server.
|
|
metrics_base.MetricsBase.tool_name = tool_name
|
|
get_start_time()
|
|
metrics.AtestStartEvent(command_line=command_line,
|
|
test_references=test_references,
|
|
cwd=cwd,
|
|
os=operating_system)
|
|
|
|
|
|
def print_data_collection_notice(colorful=True):
|
|
"""Print the data collection notice."""
|
|
red = '31m'
|
|
green = '32m'
|
|
start = '\033[1;'
|
|
end = '\033[0m'
|
|
delimiter = '=' * 18
|
|
anonymous = ''
|
|
user_type = 'INTERNAL'
|
|
if metrics_base.get_user_type() == metrics_base.EXTERNAL_USER:
|
|
anonymous = ' anonymous'
|
|
user_type = 'EXTERNAL'
|
|
notice = (' We collect%s usage statistics in accordance with our Content '
|
|
'Licenses (%s), Contributor License Agreement (%s), Privacy '
|
|
'Policy (%s) and Terms of Service (%s).'
|
|
) % (anonymous,
|
|
CONTENT_LICENSES_URL,
|
|
CONTRIBUTOR_AGREEMENT_URL[user_type],
|
|
PRIVACY_POLICY_URL,
|
|
TERMS_SERVICE_URL)
|
|
if colorful:
|
|
print(f'\n{delimiter}\n{start}{red}Notice:{end}')
|
|
print(f'{start}{green} {notice}{end}\n{delimiter}\n')
|
|
else:
|
|
print(f'\n{delimiter}\nNotice:')
|
|
print(f' {notice}\n{delimiter}\n')
|