Example #1
0
def generate_dashboard():
    """
    Generate the static html dashboard
    :return:
    """
    _now = datetime.datetime.now()
    _file = f'{system.config["export_path"]}index.html'
    output.println(f'{output.Subject.INFO} Generating dashboard {output.CliFormat.BLACK}{_file}{output.CliFormat.ENDC}')

    html = open(_file, "w")

    _rendered_html = render_template('index.html.j2',
                                     logo=render_logo(),
                                     date=_now.strftime("%Y-%m-%dT%H:%M:%SZ"),
                                     assets_css=render_assets(ASSETS_CSS, TAG_CSS),
                                     assets_js=render_assets(ASSETS_JS, TAG_JS),
                                     items=render_items(),
                                     title=system.config['title'],
                                     description=system.config['description'],
                                     version=info.__version__,
                                     homepage=info.__homepage__,
                                     lighthouse_version=system.config['lighthouse']['version']
                                     )
    html.write(_rendered_html)
    html.close()
Example #2
0
def run_command(command, return_output=False, allow_fail=False):
    """
    Run local command
    :param command: String Shell command
    :param return_output: Boolean Return shell command output
    :param allow_fail: Boolean
    :return:
    """
    output.println(
        f'{output.Subject.DEBUG}{output.Subject.CMD} {output.CliFormat.BLACK}{command}{output.CliFormat.ENDC}', verbose_only=True)

    res = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)

    out, err = res.communicate()

    if res.wait() != 0 and err.decode() != '':
        _error_message = f'{output.Subject.ERROR} {err.decode()}'
        if allow_fail:
            output.println(_error_message)
            return False
        else:
            sys.exit(_error_message)

    if return_output:
        return out.decode()

    return True
Example #3
0
def print_footer():
    """
    Printing console footer
    :return:
    """
    if 'errors' in system.config:
        output.println(f'{output.Subject.WARNING} Errors occurred during execution, see console output for more information')
    else:
        output.println(f'{output.Subject.OK} Successfully fetched lighthouse data')
Example #4
0
def clear_data():
    """
    Clear the performance data and the lighthouse garden dashboard
    :return:
    """
    output.println(f'{output.Subject.INFO} Clear data')
    _file_path = f'{config["export_path"]}index.html'
    _dir_path = utility.get_data_dir()

    if os.path.isfile(_file_path):
        os.remove(_file_path)

    shutil.rmtree(_dir_path)
Example #5
0
def check_lighthouse_version():
    """
    Check sshpass version
    :return:
    """
    _version = run_command('lighthouse --version', return_output=True)

    if _version:
        output.println(
            f'{output.Subject.INFO} lighthouse version {_version}',
            verbose_only=True
        )
        config['lighthouse']['version'] = _version
Example #6
0
def add_value_to_history(target, result):
    """
    Adding a new result value to the history data of a specific target
    :param target: Dict
    :param result: Dict
    :return:
    """
    _data = get_data(target, '.history')
    while len(_data) > system.config['keep_history']:
        output.println(f'{output.Subject.INFO} Cleaning history value', verbose_only=True)
        utility.remove_file(f'{utility.get_export_dir()}{_data[0]["report"]}')
        del _data[0]
    _data.append(result)
    set_data(target, _data, '.history')
Example #7
0
def lighthouse(target):
    """
    Fetch the lighthouse data of a specific target
    :param target: Dict
    :return:
    """
    output.println(f'{output.Subject.INFO} Fetching performance data for {info.get_target_name(target)}', verbose_only=True)

    _output_name = generate_output_name(target)
    _result = system.run_command(
        f'lighthouse {target["url"]} {build_options(_output_name)}', allow_fail=True
    )

    if not _result:
        output.println(f'{output.Subject.ERROR} > {info.get_target_name(target)} ...')
        system.config['errors'] = True

    return _output_name
Example #8
0
def extend_html_report_with_info(result, file_name):
    """
    Extend the existing lighthouse html report with an additional info box
    :param result: Dict
    :param file_name: String
    :return:
    """
    if os.path.isfile(file_name):
        with open(file_name, "r") as read_file:
            _html = read_file.readlines()
            _info = render.render_template('partials/info.html.j2',
                                           title=result['title'],
                                           url=result['url'],
                                           date=result['date'],
                                           logo=render.render_logo()
                                           )
            _html[-2] = f'{_info}\n</body>\n</html>'
            del(_html[-1])

        with open(file_name, 'w') as file:
            output.println(f'{output.Subject.INFO} Extend html report with info box', verbose_only=True)
            file.writelines(_html)
Example #9
0
def check_config(additional_config={}):
    """
    Checking configuration information by file or dictionary
    :param additional_config: Dictionary
    :return:
    """
    global config

    if config['config_file_path'] is None and additional_config == {}:
        sys.exit(f'{output.Subject.ERROR} Configuration is missing')

    if additional_config:
        config.update(additional_config)

    _config_file_path = config['config_file_path']
    if not _config_file_path is None:
        if os.path.isfile(_config_file_path):
            with open(_config_file_path, 'r') as read_file:
                config.update(json.load(read_file))
                output.println(
                    f'{output.Subject.INFO} Loading host configuration {output.CliFormat.BLACK}{_config_file_path}{output.CliFormat.ENDC}', verbose_only=True)
        else:
            sys.exit(f'{output.Subject.ERROR} Local configuration not found: {config["config_file_path"]}')
Example #10
0
def generate_badges(target):
    """
    Generate the badges for the various metrics of a specific target
    :param target: Dict
    :return:
    """
    output.println(f'{output.Subject.INFO} Generating badges', verbose_only=True)
    badges = {
        'performance': {
            'label': 'performance',
            'value': database.get_data(target)['performance'],
         },
        'accessibility': {
            'label': 'accessibility',
            'value': database.get_data(target)['accessibility'],
        },
        'best-practices': {
            'label': 'best-practices',
            'value': database.get_data(target)['best-practices'],
        },
        'seo': {
            'label': 'seo',
            'value': database.get_data(target)['seo'],
        },
        'average': {
            'label': 'performance',
            'value': database.get_data(target)['average']['value']
        }
    }

    for key, value in badges.items():
        generate_badge(
            target=target,
            layout=value,
            attribute=key
        )
Example #11
0
def fetch_data():
    """
    Fetch the lighthouse data of all given targets
    :return:
    """
    output.println(f'{output.Subject.INFO} Checking export path', verbose_only=True)
    system.check_path(f'{system.config["export_path"]}/{system.config["data_dir"]}')

    output.println(f'{output.Subject.INFO} Starting to process targets')
    for target in system.config['targets']:
        _output_name = lighthouse(target)
        _result = interpreter.get_result_by_report_file(target, _output_name)
        if _result:
            database.set_data(target, _result)
            output.println(f'{output.Subject.OK} > {info.get_target_name(target)} ... {_result["performance"]}')
            utility.extend_html_report_with_info(_result, f'{utility.get_data_dir()}{_output_name}.report.html')
            generate_badges(target)
        else:
            utility.remove_file(f'{utility.get_data_dir()}{_output_name}.report.html')
        utility.remove_file(f'{utility.get_data_dir()}{_output_name}.report.json')
Example #12
0
def get_result_by_report_file(target, file_name):
    """
    Generate the result by a given lighthouse report file
    :param target: Dict
    :param file_name: String
    :return:
    """
    output.println(f'{output.Subject.INFO} Processing result of report', verbose_only=True)
    _report_path = f'{utility.get_data_dir()}{file_name}.report.json'
    _report = None

    if os.path.isfile(_report_path):
        with open(_report_path, 'r') as read_file:
            _report = json.load(read_file)
    else:
        sys.exit(f'{output.Subject.ERROR} Report file not found: {_report_path}')

    if not isinstance(_report, dict):
        sys.exit(f'{output.Subject.ERROR} Report not readable')

    if _report['categories']['performance']['score']:
        _performance = int(round(_report['categories']['performance']['score'] * 100))
    else:
        output.println(f'{output.Subject.ERROR} Missing performance score', verbose_only=True)
        return None

    _result = defaultdict(lambda: defaultdict(dict))
    _result = {
        'title': target['title'],
        'url': target['url'],
        'performance': _performance,
        'report': f'{utility.get_data_dir(absolute_path=False)}{file_name}.report.html',
        'link': f'#{target["identifier"]}',
        'date': '{:%Y-%m-%d %H:%M:%S}'.format(datetime.datetime.now())
    }

    # additional metrics
    if 'accessibility' in _report['categories'] and _report['categories']['accessibility']['score']:
        _result['accessibility'] = int(round(_report['categories']['accessibility']['score'] * 100))

    if 'best-practices' in _report['categories'] and _report['categories']['best-practices']['score']:
        _result['best-practices'] = int(round(_report['categories']['best-practices']['score'] * 100))

    if 'seo' in _report['categories'] and _report['categories']['seo']['score']:
        _result['seo'] = int(round(_report['categories']['seo']['score'] * 100))

    database.add_value_to_history(target, _result)

    # audits
    _result['audits'] = {}
    if _report['audits']['first-contentful-paint']:
        _result['audits']['first-contentful-paint'] = _report['audits']['first-contentful-paint']['displayValue']

    if _report['audits']['largest-contentful-paint']:
        _result['audits']['largest-contentful-paint'] = _report['audits']['largest-contentful-paint'][
            'displayValue']

    if _report['audits']['speed-index']:
        _result['audits']['speed-index'] = _report['audits']['speed-index']['displayValue']

    if _report['audits']['total-blocking-time']:
        _result['audits']['total-blocking-time'] = _report['audits']['total-blocking-time']['displayValue']

    if _report['audits']['interactive']:
        _result['audits']['interactive'] = _report['audits']['interactive']['displayValue']

    if _report['audits']['cumulative-layout-shift']:
        _result['audits']['cumulative-layout-shift'] = _report['audits']['cumulative-layout-shift']['displayValue']

    # average
    _result['average'] = {
        'value': database.get_average_by_attribute(target, 'performance'),
        'min': database.get_average_peak(target, 'performance', True),
        'max': database.get_average_peak(target, 'performance', False),
        'trend': get_trend(target, 'performance')
    }

    return _result