from optparse import OptionParser
from queue import LifoQueue
from typing import Iterator, List

import requests
from logger import logger

BASE_URL = 'http://showfast.sc.couchbase.com'


def get_menu() -> dict:
    return requests.get(url=BASE_URL + '/static/menu.json').json()


def get_benchmarks(component: str, category: str) -> List[dict]:
    api = '/api/v1/benchmarks/{}/{}'.format(component, category)
    return requests.get(url=BASE_URL + api).json() or []


def hide_benchmark(benchmark_id: str):
    api = '/api/v1/benchmarks/{}'.format(benchmark_id)
    requests.patch(url=BASE_URL + api)


def showfast_iterator(components: List[str]) -> Iterator:
    for component, meta in get_menu()['components'].items():
        if component in components:
            for category in meta['categories']:
                yield component, category['id']


def parse_release(build: str) -> str:
    return build.split('-')[0]


def benchmark_iterator(components: List[str], max_builds: int) -> Iterator:
    for component, category in showfast_iterator(components=components):
        curr_metric, curr_release = None, None
        queue = LifoQueue(maxsize=max_builds)

        for benchmark in get_benchmarks(component, category):
            if not benchmark['hidden']:
                release = parse_release(benchmark['build'])

                if curr_metric != benchmark['metric']:
                    curr_metric, curr_release = benchmark['metric'], release
                    queue.queue.clear()

                if release != curr_release:
                    curr_release = release
                    queue.queue.clear()

                if queue.full():
                    yield benchmark
                else:
                    queue.put(benchmark)


def hide(components: List[str], max_builds: int):
    for b in benchmark_iterator(components=components, max_builds=max_builds):
        logger.info('Hiding: build={build}, metric={metric}'.format(**b))
        hide_benchmark(b['id'])


def main():
    parser = OptionParser()

    parser.add_option('-c', '--components', dest='components', default=[],
                      type='str', help='comma separated list of components')
    parser.add_option('-m', '--max-builds', dest='max_builds', default=8,
                      type='int', help='maximum number of builds per release')

    options, args = parser.parse_args()

    hide(components=options.components.split(','),
         max_builds=options.max_builds)


if __name__ == '__main__':
    main()

Add a script for hiding old ShowFast results
Add a script for hiding old ShowFast results

The script keeps the specified number of the most recent results
per release and hides everything else. It is helpful for keeping
ShowFast clean and normalized.

Here is an example of hiding Spock results for XDCR and Views:

$ env/bin/python scripts/hideslow.py --components xdcr,views --max-builds 7
[28/Mar/2017 08:30:17] INFO - Hiding: build=5.0.0-1885, metric=index_20M_initial_leto
[28/Mar/2017 08:30:17] INFO - Hiding: build=5.0.0-1885, metric=index_50M_dgm_initial_leto
[28/Mar/2017 08:30:18] INFO - Hiding: build=5.0.0-1885, metric=index_20M_incremental_leto
[28/Mar/2017 08:30:18] INFO - Hiding: build=5.0.0-1885, metric=index_50M_dgm_incremental_leto
[28/Mar/2017 08:30:18] INFO - Hiding: build=5.0.0-1885, metric=query_lat_100M_dgm_leto
[28/Mar/2017 08:30:18] INFO - Hiding: build=5.0.0-1885, metric=query_lat_20M_index_95th_leto
[28/Mar/2017 08:30:18] INFO - Hiding: build=5.0.0-1885, metric=query_lat_20M_leto
[28/Mar/2017 08:30:19] INFO - Hiding: build=5.0.0-1885, metric=query_lat_20M_basic_leto
[28/Mar/2017 08:30:19] INFO - Hiding: build=5.0.0-1885, metric=query_lat_20M_body_leto
[28/Mar/2017 08:30:19] INFO - Hiding: build=5.0.0-1885, metric=query_lat_20M_compute_leto
[28/Mar/2017 08:30:19] INFO - Hiding: build=5.0.0-1885, metric=query_lat_20M_group_by_leto
[28/Mar/2017 08:30:19] INFO - Hiding: build=5.0.0-1885, metric=query_lat_20M_multi_emits_leto
[28/Mar/2017 08:30:19] INFO - Hiding: build=5.0.0-1885, metric=query_lat_20M_range_leto
[28/Mar/2017 08:30:19] INFO - Hiding: build=5.0.0-1885, metric=query_thr_20M_leto
[28/Mar/2017 08:30:20] INFO - Hiding: build=5.0.0-2110, metric=xdcr_init_1x1_unidir_100M_fe_titan_5x5
[28/Mar/2017 08:30:20] INFO - Hiding: build=5.0.0-2110, metric=xdcr_init_1x1_unidir_100M_lww_titan_5x5
...

This script also demonstrates usage of type hints in Python 3.

Change-Id: Iccd1329248dae79a56d767520f32a22e824f0cd4
Reviewed-on: http://review.couchbase.org/75875
Tested-by: Build Bot <80754af91bfb6d1073585b046fe0a474ce868509@couchbase.com>
Reviewed-by: Pavel Paulau <dd88eded64e90046a680e3a6c0828ceb8fe8a0e7@gmail.com>
