import requests from auth0.authentication import GetToken from ..config import config from . import utils import time from dataclasses import dataclass class O11yAPI: auth0_token = None auth0_expires_at = 0 num_retrys = 3 def __init__(self, cfg: config.Config): self.cfg = cfg def getToken(self): if self.auth0_token is not None: current_timestamp = int(time.time()) if current_timestamp < self.auth0_expires_at: return self.auth0_token return self.refreshToken() def refreshToken(self): current_timestamp = int(time.time()) domain = 'tidb-soc2.us.auth0.com' get_token = GetToken(domain, self.cfg.o11y_auth0_client_id, client_secret=self.cfg.o11y_auth0_client_secret) token = get_token.client_credentials( 'https://{}/api/v2/'.format(domain)) mgmt_api_token = token['access_token'] expires_in = token['expires_in'] self.auth0_token = mgmt_api_token self.auth0_expires_at = current_timestamp+expires_in return mgmt_api_token def getO11yClusterInfo(self, applicationID: str,isServerless: bool=False): # query o11y cluster info globally url = "https://www.gs.us-west-2.aws.observability.tidbcloud.com/api/v1/global/clusters/" body = { "applicationID": applicationID, "bizType": utils.env2BizType(self.cfg.env,isServerless) } print("applicationID {} bizType {}".format(applicationID,utils.env2BizType(self.cfg.env,isServerless))) # access o11y with auth0 token mgmt_api_token = self.getToken() headers = { 'authorization': 'Bearer {}'.format(mgmt_api_token) } resp = requests.get(url, headers=headers, params=body) info = resp.json() print("get o11y cluster info {}".format(resp.text)) if info['code'] != 0: raise Exception( "get o11y cluster info failed {}".format(info['message'])) if info['data']['clusters'] is None: return None cluster = info['data']['clusters'][0] return ClusterInfo(cluster['vendor'], cluster['region'], cluster['tenantID'], cluster['projectID'], cluster['applicationID'], cluster['bizType'], cluster['id'], cluster['shareMode']) def getO11yMetrics(self, dsPath: str, metrics_expr: str, startTime: int, endTime: int, step: int): url = "https://" + dsPath + "/api/v1/query_range" body = { "query": metrics_expr, "start": startTime, "end": endTime, "step": "{}s".format(step), } for _ in range(self.num_retrys): try: resp = requests.get(url, params=body) info = resp.json() if info['status'] != 'success': raise Exception("get o11y metrics failed") return info['data']['result'] except Exception as e: time.sleep(0.1) print("get o11y metrics failed {}".format(e)) return None def getO11yLoki(self, dsPath: str, log_expr: str, startTime: int, endTime: int): url = "https://" + dsPath + "/loki/api/v1/query_range" body = { "query": log_expr, "start": startTime, "end": endTime, "limit": 1000, "direction": "backward", } resp = requests.get(url, params=body) info = resp.json() if info['status'] != 'success': raise Exception("get o11y loki logs failed") return info['data']['result'] @dataclass class ClusterInfo: vendor: str region: str tenantID: str projectID: str applicationID: str bizType: str clusterID: str shareMode: str