Refactor analytics collectors.

- Only have one registration class
- Add description fields
- Add automation collector information to /api/v2/config
This commit is contained in:
Bill Nottingham
2020-09-09 17:10:14 -04:00
parent dff7667532
commit 1c4b06fe1e
6 changed files with 87 additions and 66 deletions

View File

@@ -18,7 +18,7 @@ from awx.main.models.ha import TowerAnalyticsState
from awx.main.utils import get_awx_http_client_headers, set_environ
__all__ = ['register', 'gather', 'ship', 'table_version']
__all__ = ['register', 'gather', 'ship']
logger = logging.getLogger('awx.main.analytics')
@@ -37,11 +37,27 @@ def _valid_license():
return True
def register(key, version):
def all_collectors():
from awx.main.analytics import collectors
collector_dict = {}
module = collectors
for name, func in inspect.getmembers(module):
if inspect.isfunction(func) and hasattr(func, '__awx_analytics_key__'):
key = func.__awx_analytics_key__
desc = func.__awx_analytics_description__ or ''
version = func.__awx_analytics_version__
collector_dict[key] = { 'name': key, 'version': version, 'description': desc}
return collector_dict
def register(key, version, description=None, format='json'):
"""
A decorator used to register a function as a metric collector.
Decorated functions should return JSON-serializable objects.
Decorated functions should do the following based on format:
- json: return JSON-serializable objects.
- csv: write CSV data to a filename named 'key'
@register('projects_by_scm_type', 1)
def projects_by_scm_type():
@@ -51,28 +67,19 @@ def register(key, version):
def decorate(f):
f.__awx_analytics_key__ = key
f.__awx_analytics_version__ = version
f.__awx_analytics_description__ = description
f.__awx_analytics_type__ = format
return f
return decorate
def table_version(file_name, version):
global manifest
manifest[file_name] = version
def decorate(f):
return f
return decorate
def gather(dest=None, module=None, collection_type='scheduled'):
def gather(dest=None, module=None, subset = None, collection_type='scheduled'):
"""
Gather all defined metrics and write them as JSON files in a .tgz
:param dest: the (optional) absolute path to write a compressed tarball
:pararm module: the module to search for registered analytic collector
:param module: the module to search for registered analytic collector
functions; defaults to awx.main.analytics.collectors
"""
@@ -93,14 +100,21 @@ def gather(dest=None, module=None, collection_type='scheduled'):
logger.error("Automation Analytics not enabled. Use --dry-run to gather locally without sending.")
return
collector_list = []
if module is None:
from awx.main.analytics import collectors
module = collectors
for name, func in inspect.getmembers(module):
if (
inspect.isfunction(func) and
hasattr(func, '__awx_analytics_key__') and
(not subset or name in subset)
):
collector_list.append((name, func))
dest = dest or tempfile.mkdtemp(prefix='awx_analytics')
for name, func in inspect.getmembers(module):
if inspect.isfunction(func) and hasattr(func, '__awx_analytics_key__'):
for name, func in collector_list:
if func.__awx_analytics_type__ == 'json':
key = func.__awx_analytics_key__
manifest['{}.json'.format(key)] = func.__awx_analytics_version__
path = '{}.json'.format(os.path.join(dest, key))
@@ -114,7 +128,14 @@ def gather(dest=None, module=None, collection_type='scheduled'):
logger.exception("Could not generate metric {}.json".format(key))
f.close()
os.remove(f.name)
elif func.__awx_analytics_type__ == 'csv':
key = func.__awx_analytics_key__
manifest['{}.csv'.format(key)] = func.__awx_analytics_version__
try:
func(last_run, full_path=dest)
except Exception:
logger.exception("Could not generate metric {}.csv".format(key))
path = os.path.join(dest, 'manifest.json')
with open(path, 'w', encoding='utf-8') as f:
try:
@@ -124,11 +145,6 @@ def gather(dest=None, module=None, collection_type='scheduled'):
f.close()
os.remove(f.name)
try:
collectors.copy_tables(since=last_run, full_path=dest)
except Exception:
logger.exception("Could not copy tables")
# can't use isoformat() since it has colons, which GNU tar doesn't like
tarname = '_'.join([
settings.SYSTEM_UUID,