"""Lambda Functions for calculate MTTR of TiDB Clusters""" # import json # from datetime import datetime, timedelta # # import pymysql # import sliutil.connection # import sliutil.string # import sliutil.tidb # import sliutil.time # # SLI_TABLE_NAME = "reporter_service_level_probe_cluster_counter" # MTTR_TABLE_NAME = "mttr" def lambda_handler(event, context): # pylint:disable=unused-argument """AWS Lambda Function Handler Parameters ---------- event: dict, required API Gateway Lambda Proxy Input Format Event doc: https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-lambda-proxy-integrations.html#api-gateway-simple-proxy-for-lambda-input-format # pylint:disable=line-too-long # noqa context: object, required Lambda Context runtime methods and attributes Context doc: https://docs.aws.amazon.com/lambda/latest/dg/python-context-object.html Returns ------ API Gateway Lambda Proxy Output Format: dict Return doc: https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-lambda-proxy-integrations.html # pylint:disable=line-too-long """ # # tidb_conn = sliutil.connection.get_tidb_connection() # # month_str = event.get("month", "") # begin_ts, end_ts = sliutil.time.get_month_begin_end_ts(month=month_str) # # handler = Handler(connection=tidb_conn) # handler.run(begin_ts=begin_ts, end_ts=end_ts) # # return { # "statusCode": 200, # "body": json.dumps( # { # "message": "hello world", # # "location": ip.text.replace("\n", "") # } # ), # } # # # class Handler: # """Handle metrics `reporter_service_level_probe_cluster_counter`""" # # def __init__(self, connection: pymysql.Connection) -> None: # self.connection = connection # # def run(self, begin_ts: float, end_ts: float) -> None: # """Calculate MTTR of TiDB Clusters from table # `reporter_service_level_probe_cluster_counter` # from begin_ts to end_ts and save the results into a new table # """ # print(f"Start to calculate MTTR, begin_ts: {begin_ts}, end_ts: {end_ts}") # # dedicate_clusters = sliutil.tidb.list_dedicated_clusters_ts( # connection=self.connection, # begin_ts=begin_ts, # end_ts=end_ts, # ) # # results = self.search( # begin_ts=begin_ts, # end_ts=end_ts, # dedicate_cluster_ids=[x["cluster_id"] for x in dedicate_clusters], # ) # # incidents_map = {} # downtime_minutes_map = {} # latest_downtime_map = {} # for row in results: # if row["cluster_id"] not in downtime_minutes_map: # downtime_minutes_map[row["cluster_id"]] = 1 # incidents_map[row["cluster_id"]] = 1 # latest_downtime_map[row["cluster_id"]] = row["downtime_minute"] # continue # # downtime_minutes_map[row["cluster_id"]] += 1 # latest_downtime = latest_downtime_map[row["cluster_id"]] # if datetime.fromtimestamp(row["downtime_minute"]) - datetime.fromtimestamp( # latest_downtime # ) > timedelta(minutes=1): # incidents_map[row["cluster_id"]] += 1 # latest_downtime_map[row["cluster_id"]] = row["downtime_minute"] # # data = [] # for cluster in dedicate_clusters: # if cluster["cluster_id"] in incidents_map: # downtime_minutes = downtime_minutes_map[cluster["cluster_id"]] # incidents = incidents_map[cluster["cluster_id"]] # mttr = downtime_minutes / incidents # data.append( # ( # cluster["cluster_id"], # sliutil.time.get_month_from_timestamp(timestamp=begin_ts), # mttr, # incidents, # downtime_minutes, # ) # ) # else: # data.append( # ( # cluster["cluster_id"], # sliutil.time.get_month_from_timestamp(timestamp=begin_ts), # 0, # 0, # 0, # ) # ) # # self.save(data=data) # print("Finish calculate MTTR") # # def search(self, begin_ts: float, end_ts: float, dedicate_cluster_ids: list) -> list: # """List downtime minutes from `reporter_service_level_probe_cluster_counter` # from begin_ts to end_ts""" # results = [] # start = datetime.now().timestamp() # with self.connection.cursor() as cursor: # for i in range(0, len(dedicate_cluster_ids), 100): # end = min(i + 100, len(dedicate_cluster_ids)) # sql = f""" # SELECT cluster_id, FLOOR(timestamp / 60) * 60 as downtime_minute # FROM `{SLI_TABLE_NAME}` # WHERE # timestamp >= {begin_ts:.0f} AND timestamp <= {end_ts:.0f} # AND increment > 0 # AND cluster_id in # ({sliutil.string.list_to_string(dedicate_cluster_ids[i:end])}) # GROUP BY # cluster_id, downtime_minute # HAVING # BIT_AND( # status != "alive" # AND status != "skipped_by_not_ready" # AND status != "skipped_by_suspend" # ) # ORDER BY cluster_id ASC, downtime_minute ASC # """ # # print("search, sql: ", sql) # cursor.execute(sql) # results.extend(cursor.fetchall()) # end = datetime.now().timestamp() # print(f"search, take {end-start:.2f}s") # return results # # def save(self, data: list) -> None: # """Save data into table `mttr`""" # print(f"save data, len: {len(data)}") # with self.connection.cursor() as cursor: # sql = f""" # INSERT INTO `{MTTR_TABLE_NAME}` ( # cluster_id, month, value, incidents, downtime_minutes # ) # VALUES # (%s, %s, %s, %s, %s) ON DUPLICATE KEY UPDATE # value=VALUES(value), # incidents=VALUES(incidents), # downtime_minutes=VALUES(downtime_minutes) # """ # cursor.executemany(sql, data) # self.connection.commit()