Kevin Cheng | 5d6e157 | 2018-10-23 11:43:42 -0700 | [diff] [blame] | 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 | |
| 17 | import json |
| 18 | import logging |
| 19 | import os |
Kevin Cheng | 5d6e157 | 2018-10-23 11:43:42 -0700 | [diff] [blame] | 20 | import uuid |
| 21 | |
kellyhung | 5161d93 | 2019-04-23 16:23:59 +0800 | [diff] [blame] | 22 | try: |
| 23 | # PYTHON2 |
| 24 | from urllib2 import Request |
| 25 | from urllib2 import urlopen |
| 26 | except ImportError: |
| 27 | # PYTHON3 |
| 28 | from urllib.request import Request |
| 29 | from urllib.request import urlopen |
| 30 | |
kellyhung | 0bd5a16 | 2019-03-14 15:32:03 +0800 | [diff] [blame] | 31 | |
Kevin Cheng | 5d6e157 | 2018-10-23 11:43:42 -0700 | [diff] [blame] | 32 | _JSON_HEADERS = {'Content-Type': 'application/json'} |
| 33 | _METRICS_RESPONSE = 'done' |
Kevin Cheng | 5d6e157 | 2018-10-23 11:43:42 -0700 | [diff] [blame] | 34 | _METRICS_TIMEOUT = 2 #seconds |
| 35 | _META_FILE = os.path.join(os.path.expanduser('~'), |
| 36 | '.config', 'asuite', '.metadata') |
| 37 | _ANDROID_BUILD_TOP = 'ANDROID_BUILD_TOP' |
| 38 | |
Kevin Cheng | 31e976f | 2019-05-06 12:38:38 -0700 | [diff] [blame] | 39 | DUMMY_UUID = '00000000-0000-4000-8000-000000000000' |
| 40 | |
Kevin Cheng | 5d6e157 | 2018-10-23 11:43:42 -0700 | [diff] [blame] | 41 | |
| 42 | #pylint: disable=broad-except |
| 43 | def log_event(metrics_url, dummy_key_fallback=True, **kwargs): |
| 44 | """Base log event function for asuite backend. |
| 45 | |
| 46 | Args: |
| 47 | metrics_url: String, URL to report metrics to. |
| 48 | dummy_key_fallback: Boolean, If True and unable to get grouping key, |
| 49 | use a dummy key otherwise return out. Sometimes we |
| 50 | don't want to return metrics for users we are |
| 51 | unable to identify. Default True. |
| 52 | kwargs: Dict, additional fields we want to return metrics for. |
| 53 | """ |
| 54 | try: |
| 55 | try: |
| 56 | key = str(_get_grouping_key()) |
| 57 | except Exception: |
| 58 | if not dummy_key_fallback: |
| 59 | return |
Kevin Cheng | 31e976f | 2019-05-06 12:38:38 -0700 | [diff] [blame] | 60 | key = DUMMY_UUID |
Kevin Cheng | 5d6e157 | 2018-10-23 11:43:42 -0700 | [diff] [blame] | 61 | data = {'grouping_key': key, |
| 62 | 'run_id': str(uuid.uuid4())} |
| 63 | if kwargs: |
| 64 | data.update(kwargs) |
| 65 | data = json.dumps(data) |
kellyhung | 5161d93 | 2019-04-23 16:23:59 +0800 | [diff] [blame] | 66 | request = Request(metrics_url, data=data, |
| 67 | headers=_JSON_HEADERS) |
| 68 | response = urlopen(request, timeout=_METRICS_TIMEOUT) |
Kevin Cheng | 5d6e157 | 2018-10-23 11:43:42 -0700 | [diff] [blame] | 69 | content = response.read() |
| 70 | if content != _METRICS_RESPONSE: |
| 71 | raise Exception('Unexpected metrics response: %s' % content) |
| 72 | except Exception as e: |
| 73 | logging.debug('Exception sending metrics: %s', e) |
| 74 | |
| 75 | |
| 76 | def _get_grouping_key(): |
| 77 | """Get grouping key. Returns UUID.uuid4.""" |
| 78 | if os.path.isfile(_META_FILE): |
| 79 | with open(_META_FILE) as f: |
| 80 | try: |
| 81 | return uuid.UUID(f.read(), version=4) |
| 82 | except ValueError: |
| 83 | logging.debug('malformed group_key in file, rewriting') |
| 84 | # TODO: Delete get_old_key() on 11/17/2018 |
| 85 | key = _get_old_key() or uuid.uuid4() |
| 86 | dir_path = os.path.dirname(_META_FILE) |
| 87 | if os.path.isfile(dir_path): |
| 88 | os.remove(dir_path) |
| 89 | try: |
| 90 | os.makedirs(dir_path) |
| 91 | except OSError as e: |
| 92 | if not os.path.isdir(dir_path): |
| 93 | raise e |
| 94 | with open(_META_FILE, 'w+') as f: |
| 95 | f.write(str(key)) |
| 96 | return key |
| 97 | |
| 98 | |
| 99 | def _get_old_key(): |
| 100 | """Get key from old meta data file if exists, else return None.""" |
| 101 | old_file = os.path.join(os.environ[_ANDROID_BUILD_TOP], |
| 102 | 'tools/tradefederation/core/atest', '.metadata') |
| 103 | key = None |
| 104 | if os.path.isfile(old_file): |
| 105 | with open(old_file) as f: |
| 106 | try: |
| 107 | key = uuid.UUID(f.read(), version=4) |
| 108 | except ValueError: |
| 109 | logging.debug('error reading old key') |
| 110 | os.remove(old_file) |
| 111 | return key |