async def test_apps_stats_app_not_found(self): async with HttpClientContext(app) as client: local_address = ( f"http://{client._server.host}:{client._server.port}") with aioresponses( passthrough=[local_address, settings.STATS_API_URL ]) as rsps: agent_id = "ead07ffb-5a61-42c9-9386-21b680597e6c-S0" build_mesos_cluster(rsps, agent_id) # namespace=asgard-infra app_stats_datapoints = get_fixture( f"agents/{agent_id}/app_stats.json") resp = await client.get( f"/apps/asgard/api/not-exist/stats?account_id={ACCOUNT_DEV_ID}", headers={ "Authorization": f"Token {USER_WITH_MULTIPLE_ACCOUNTS_AUTH_KEY}" }, ) self.assertEqual(HTTPStatus.OK, resp.status) data = await resp.json() self.assertEqual( AppStats(cpu_pct="0", ram_pct="0", cpu_thr_pct="0").dict(), data["stats"], )
async def test_get_apps_stats_with_data(self): """ Prepara um ElasticSearch com alguns dados e faz o cálculo agregado do uso de CPU e RAM """ app_stats_datapoints = get_fixture( f"agents/ead07ffb-5a61-42c9-9386-21b680597e6c-S0/app_stats.json") app = MesosApp(id="infra/asgard/api") await self._load_app_stats_into_storage(self.INDEX_NAME, self.utc_now, app_stats_datapoints) backend = MarathonAppsBackend() user = User(**USER_WITH_MULTIPLE_ACCOUNTS_DICT) account = Account(**ACCOUNT_DEV_DICT) async with Elasticsearch([settings.STATS_API_URL]) as es: raw = await es.search(index=self.INDEX_NAME) cpu_pcts = [ hit["_source"]["cpu_pct"] for hit in raw["hits"]["hits"] ] mem_pcts = [ hit["_source"]["mem_pct"] for hit in raw["hits"]["hits"] ] self.assertEqual(5, len(cpu_pcts)) self.assertEqual(5, len(mem_pcts)) app_stats = await backend.get_app_stats(app, user, account) self.assertEqual( AppStats(cpu_pct="0.25", ram_pct="15.05", cpu_thr_pct="1.00"), app_stats, )
async def test_apps_stats_with_avg_1_min(self): with aioresponses(passthrough=[ TEST_LOCAL_AIOHTTP_ADDRESS, settings.STATS_API_URL ]) as rsps: agent_id = "ead07ffb-5a61-42c9-9386-21b680597e6c-S0" build_mesos_cluster(rsps, agent_id) # namespace=asgard-infra app_stats_datapoints = get_fixture( f"agents/{agent_id}/app_stats.json") await self._load_app_stats_into_storage(self.INDEX_NAME, self.utc_now, app_stats_datapoints) resp = await self.client.get( f"/apps/infra/asgard/api/stats/avg-1min?account_id={ACCOUNT_DEV_ID}", headers={ "Authorization": f"Token {USER_WITH_MULTIPLE_ACCOUNTS_AUTH_KEY}" }, ) self.assertEqual(HTTPStatus.OK, resp.status) data = await resp.json() self.assertEqual( AppStats(cpu_pct="0.25", ram_pct="15.05", cpu_thr_pct="1.00").dict(), data["stats"], )
async def test_get_app_stats_has_some_data(self): with aioresponses() as rsps: agent_id = "ead07ffb-5a61-42c9-9386-21b680597e6c-S0" build_mesos_cluster(rsps, agent_id) add_agent_task_stats(rsps, agent_id, index_name="asgard-app-stats-2019-03-29-*") stats = await self.apps_backend.get_app_stats( MesosApp(id="infra-asgard-api"), self.user, self.account) self.assertEqual( AppStats(cpu_pct="4.51", ram_pct="22.68", cpu_thr_pct="2.89"), stats, )
async def get_app_stats(self, app: App, interval: Interval, user: User, account: Account) -> AppStats: utc_now = datetime.utcnow().replace(tzinfo=timezone.utc) index_name = f"asgard-app-stats-{utc_now.strftime('%Y-%m-%d')}-*" bool_query = Q( "bool", must=[ Q("term", appname__keyword=f"/{account.namespace}/{app.id}"), Q("range", timestamp={"gte": f"now-{interval}"}), ], ) query = Search().query(bool_query).extra(size=2) query.aggs.bucket("avg_cpu_pct", A("avg", field="cpu_pct")) query.aggs.bucket("avg_mem_pct", A("avg", field="mem_pct")) query.aggs.bucket("avg_cpu_thr_pct", A("avg", field="cpu_thr_pct")) dict_query = query.to_dict() errors = {} raw_result = None try: async with Elasticsearch([settings.STATS_API_URL]) as es: raw_result = await es.search(index=index_name, body=dict_query) except Exception as e: errors["global"] = str(e) if raw_result and raw_result["hits"]["hits"]: app_stats_result = raw_result["aggregations"] cpu_pct = round_up( Decimal(str(app_stats_result["avg_cpu_pct"]["value"]))) mem_pct = round_up( Decimal(str(app_stats_result["avg_mem_pct"]["value"]))) cpu_thr_pct = round_up( Decimal(str(app_stats_result["avg_cpu_thr_pct"]["value"]))) else: cpu_pct = Decimal(0) mem_pct = Decimal(0) cpu_thr_pct = Decimal(0) return AppStats( cpu_pct=str(cpu_pct), ram_pct=str(mem_pct), cpu_thr_pct=str(cpu_thr_pct), errors=errors, )
async def test_get_apps_stats_no_data(self): """ Prepara um ElasticSearch com alguns dados e faz o cálculo agregado do uso de CPU e RAM """ app_stats_datapoints = get_fixture( f"agents/ead07ffb-5a61-42c9-9386-21b680597e6c-S0/app_stats.json") app = MesosApp(id="infra/app-does-not-exist") await self._load_app_stats_into_storage(self.INDEX_NAME, self.utc_now, app_stats_datapoints) backend = MarathonAppsBackend() user = User(**USER_WITH_MULTIPLE_ACCOUNTS_DICT) account = Account(**ACCOUNT_DEV_DICT) app_stats = await backend.get_app_stats(app, user, account) self.assertEqual(AppStats(cpu_pct="0", ram_pct="0", cpu_thr_pct="0"), app_stats)
async def test_get_app_stats_exception_on_search(self): """ Returns AppStats with errors filled if any exception happend during ES query """ with aioresponses() as rsps: agent_id = "ead07ffb-5a61-42c9-9386-21b680597e6c-S0" build_mesos_cluster(rsps, agent_id) index_name = "asgard-app-stats-2019-03-29-*" url = f"{settings.STATS_API_URL}/{index_name}/_search" rsps.get(url, exception=Exception("Connection error to ES")) stats = await self.apps_backend.get_app_stats( MesosApp(id="infra-asgard-api"), self.user, self.account) self.assertEqual( AppStats( cpu_pct="0", ram_pct="0", cpu_thr_pct="0", errors={"global": "Connection error to ES"}, ), stats, )
async def test_apps_stats_app_not_found(self): with aioresponses(passthrough=[ TEST_LOCAL_AIOHTTP_ADDRESS, settings.STATS_API_URL ]) as rsps: agent_id = "ead07ffb-5a61-42c9-9386-21b680597e6c-S0" build_mesos_cluster(rsps, agent_id) # namespace=asgard-infra app_stats_datapoints = get_fixture( f"agents/{agent_id}/app_stats.json") resp = await self.client.get( f"/apps/asgard/api/not-exist/stats?account_id={ACCOUNT_DEV_ID}", headers={ "Authorization": f"Token {USER_WITH_MULTIPLE_ACCOUNTS_AUTH_KEY}" }, ) self.assertEqual(200, resp.status) data = await resp.json() self.assertEqual( AppStats(cpu_pct="0", ram_pct="0", cpu_thr_pct="0").dict(), data["stats"], )