1# Copyright 2018, The Android Open Source Project
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7#     http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14
15"""Asuite simple Metrics Functions"""
16
17import json
18import logging
19import os
20import uuid
21
22from urllib.request import Request
23from urllib.request import urlopen
24
25
26_JSON_HEADERS = {'Content-Type': 'application/json'}
27_METRICS_RESPONSE = 'done'
28_METRICS_TIMEOUT = 2 #seconds
29_META_FILE = os.path.join(os.path.expanduser('~'),
30                          '.config', 'asuite', '.metadata')
31_ANDROID_BUILD_TOP = 'ANDROID_BUILD_TOP'
32
33UNUSED_UUID = '00000000-0000-4000-8000-000000000000'
34
35
36#pylint: disable=broad-except
37def log_event(metrics_url, unused_key_fallback=True, **kwargs):
38    """Base log event function for asuite backend.
39
40    Args:
41        metrics_url: String, URL to report metrics to.
42        unused_key_fallback: Boolean, If True and unable to get grouping key,
43                            use a unused key otherwise return out. Sometimes we
44                            don't want to return metrics for users we are
45                            unable to identify. Default True.
46        kwargs: Dict, additional fields we want to return metrics for.
47    """
48    try:
49        try:
50            key = str(_get_grouping_key())
51        except Exception:
52            if not unused_key_fallback:
53                return
54            key = UNUSED_UUID
55        data = {'grouping_key': key,
56                'run_id': str(uuid.uuid4())}
57        if kwargs:
58            data.update(kwargs)
59        data = json.dumps(data)
60        request = Request(metrics_url, data=data,
61                          headers=_JSON_HEADERS)
62        response = urlopen(request, timeout=_METRICS_TIMEOUT)
63        content = response.read()
64        if content != _METRICS_RESPONSE:
65            raise Exception('Unexpected metrics response: %s' % content)
66    except Exception as e:
67        logging.debug('Exception sending metrics: %s', e)
68
69
70def _get_grouping_key():
71    """Get grouping key. Returns UUID.uuid4."""
72    if os.path.isfile(_META_FILE):
73        with open(_META_FILE) as f:
74            try:
75                return uuid.UUID(f.read(), version=4)
76            except ValueError:
77                logging.debug('malformed group_key in file, rewriting')
78    # TODO: Delete get_old_key() on 11/17/2018
79    key = _get_old_key() or uuid.uuid4()
80    dir_path = os.path.dirname(_META_FILE)
81    if os.path.isfile(dir_path):
82        os.remove(dir_path)
83    try:
84        os.makedirs(dir_path)
85    except OSError as e:
86        if not os.path.isdir(dir_path):
87            raise e
88    with open(_META_FILE, 'w+') as f:
89        f.write(str(key))
90    return key
91
92
93def _get_old_key():
94    """Get key from old meta data file if exists, else return None."""
95    old_file = os.path.join(os.environ[_ANDROID_BUILD_TOP],
96                            'tools/tradefederation/core/atest', '.metadata')
97    key = None
98    if os.path.isfile(old_file):
99        with open(old_file) as f:
100            try:
101                key = uuid.UUID(f.read(), version=4)
102            except ValueError:
103                logging.debug('error reading old key')
104        os.remove(old_file)
105    return key
106