from typing import Dict, Tuple from o11ydiagnosis.subtasks.slowlogconverter.slowlog import SlowLog class SlowStats: digest: str count: int query_time_sum: float query_time_max: float mem_max_sum: float mem_max_max: float disk_max_sum: float disk_max_max: float def __init__(self, digest: str): self.digest = digest self.count = 0 self.query_time_sum = 0 self.query_time_max = 0 self.mem_max_sum = 0 self.mem_max_max = 0 self.disk_max_sum = 0 self.disk_max_max = 0 def merge(self, sl: SlowLog): self.count += 1 if sl.query_time: self.query_time_sum += sl.query_time if self.query_time_max < sl.query_time: self.query_time_max = sl.query_time if sl.mem_max: self.mem_max_sum += sl.mem_max if self.mem_max_max < sl.mem_max: self.mem_max_max = sl.mem_max if sl.disk_max: self.disk_max_sum += sl.disk_max if self.disk_max_max < sl.disk_max: self.disk_max_max = sl.disk_max class SlowStatsMerger: begin: int end: int meta: Dict[str, Tuple[str, bool]] # Map stats: Dict[str, SlowStats] stats_by_db: Dict[str, Dict[str, SlowStats]] count_per_minute: Dict[str, Dict[int, int]] # [begin, end) def __init__( self, begin: int, end: int, meta: Dict[str, Tuple[str, bool]], stats: Dict[str, SlowStats] = {}, stats_by_db: Dict[str, Dict[str, SlowStats]] = {}, count_per_minute: Dict[str, Dict[int, int]] = {}, ): self.begin = begin self.end = end self.meta = meta self.stats = stats self.stats_by_db = stats_by_db self.count_per_minute = count_per_minute def merge(self, sl: SlowLog): if not sl.digest: return if sl.time < self.begin or sl.time >= self.end: return self.merge_meta(sl) self.merge_stats(sl) self.merge_stats_by_db(sl) self.merge_count_per_minute(sl) def merge_meta(self, sl: SlowLog): query = sl.query if query is None: query = "" internal = sl.is_internal if internal is None: internal = False self.meta[sl.digest] = (query, internal) def merge_stats(self, sl: SlowLog): if sl.digest not in self.stats: self.stats[sl.digest] = SlowStats(sl.digest) self.stats[sl.digest].merge(sl) def merge_stats_by_db(self, sl: SlowLog): if sl.db not in self.stats_by_db: self.stats_by_db[sl.db] = {} if sl.digest not in self.stats_by_db[sl.db]: self.stats_by_db[sl.db][sl.digest] = SlowStats(sl.digest) self.stats_by_db[sl.db][sl.digest].merge(sl) def merge_count_per_minute(self, sl: SlowLog): if not sl.digest: return if sl.is_internal: return if "" not in self.count_per_minute: self.count_per_minute[""] = {} if sl.digest not in self.count_per_minute: self.count_per_minute[sl.digest] = {} ts = int(sl.time) ts -= ts % 60 if ts not in self.count_per_minute[""]: self.count_per_minute[""][ts] = 0 if ts not in self.count_per_minute[sl.digest]: self.count_per_minute[sl.digest][ts] = 0 self.count_per_minute[""][ts] += 1 self.count_per_minute[sl.digest][ts] += 1 def merge_stats(dst: SlowStats, src: SlowStats): dst.count += src.count dst.query_time_sum += src.query_time_sum if src.query_time_max > dst.query_time_max: dst.query_time_max = src.query_time_max dst.mem_max_sum += src.mem_max_sum if src.mem_max_max > dst.mem_max_max: dst.mem_max_max = src.mem_max_max dst.disk_max_sum += src.disk_max_sum if src.disk_max_max > dst.disk_max_max: dst.disk_max_max = src.disk_max_max