blob: a43b8f690538b8bc221d428caf958e4174b8a9b1 [file] [log] [blame]
# 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 . import metrics
from . import metrics_base
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:
dur_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=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)