1
- import dataclasses
2
1
import datetime as dt
3
2
import json
4
3
import logging
5
4
import uuid
6
5
from typing import Any , Dict
7
6
8
7
import clickhouse_connect
9
- from common .config_model import BenchmarkConfig , Frequency
10
- from common .regression_utils import (
11
- BenchmarkRegressionReport ,
12
- get_regression_status ,
13
- PerGroupResult ,
14
- )
8
+ from common .config_model import BenchmarkConfig , ReportConfig , to_dict
9
+ from common .regression_utils import BenchmarkRegressionReport , get_regression_status
15
10
from jinja2 import Template
16
11
17
12
71
66
"""
72
67
73
68
74
- logger = logging .getLogger ()
75
-
76
-
77
69
class ReportManager :
78
70
"""
79
71
handles db insertion and notification processing
@@ -91,27 +83,28 @@ def __init__(
91
83
):
92
84
self .is_dry_run = is_dry_run
93
85
94
- self .report = regression_report
86
+ self .raw_report = regression_report
87
+
95
88
self .config_id = config .id
96
89
self .config = config
97
-
98
90
self .type = type
99
91
self .repo = repo
100
92
self .db_table_name = db_table_name
101
93
102
94
self .id = str (uuid .uuid4 ())
103
95
104
96
# extract latest meta data from report
105
- self .baseline = self .report ["baseline_meta_data" ]
106
- self .target = self .report ["new_meta_data" ]
97
+ self .baseline = self .raw_report ["baseline_meta_data" ]
98
+ self .target = self .raw_report ["new_meta_data" ]
107
99
self .target_latest_commit = self .target ["end" ]["commit" ]
108
100
self .target_latest_ts_str = self .target ["end" ]["timestamp" ]
109
- self .status = get_regression_status (self .report ["summary" ])
101
+ self .status = get_regression_status (self .raw_report ["summary" ])
110
102
111
103
self .report_data = self ._to_report_data (
112
104
config_id = config .id ,
113
- regression_report = self .report ,
114
- frequency = self .config .policy .frequency ,
105
+ regression_report = self .raw_report ,
106
+ config = self .config ,
107
+ status = self .status ,
115
108
)
116
109
117
110
def run (
@@ -146,7 +139,7 @@ def notify_github_comment(self, github_token: str):
146
139
)
147
140
return
148
141
logger .info ("[%s] prepareing gitub comment content" , self .config_id )
149
- content = self ._to_markdoown ()
142
+ content = self ._to_markdown ()
150
143
if self .is_dry_run :
151
144
logger .info (
152
145
"[%s]dry run, skip sending comment to github, report(%s)" ,
@@ -161,31 +154,24 @@ def notify_github_comment(self, github_token: str):
161
154
github_notification .create_github_comment (content , github_token )
162
155
logger .info ("[%s] done. comment is sent to github" , self .config_id )
163
156
164
- def _to_markdoown (self ):
165
- self .regression_items = self ._collect_regression_items ()
166
- url = ""
167
- if self .config .hud_info :
168
- url = self .config .hud_info .get ("url" , "" )
169
-
170
- md = Template (REPORT_MD_TEMPLATE , trim_blocks = True , lstrip_blocks = True ).render (
157
+ def _to_markdown (self ) -> str :
158
+ regression_items = [
159
+ r for r in self .raw_report ["results" ] if r .get ("label" ) == "regression"
160
+ ]
161
+ url = (self .config .hud_info or {}).get ("url" , "" )
162
+ return Template (
163
+ REPORT_MD_TEMPLATE , trim_blocks = True , lstrip_blocks = True
164
+ ).render (
171
165
id = self .id ,
172
166
url = url ,
173
167
status = self .status ,
174
168
report_id = self .config_id ,
175
- summary = self .report ["summary" ],
169
+ summary = self .raw_report ["summary" ],
176
170
baseline = self .baseline ,
177
171
target = self .target ,
178
172
frequency = self .config .policy .frequency .get_text (),
179
- regression_items = self . regression_items ,
173
+ regression_items = regression_items ,
180
174
)
181
- return md
182
-
183
- def _collect_regression_items (self ) -> list [PerGroupResult ]:
184
- items = []
185
- for item in self .report ["results" ]:
186
- if item ["label" ] == "regression" :
187
- items .append (item )
188
- return items
189
175
190
176
def insert_to_db (
191
177
self ,
@@ -205,7 +191,7 @@ def insert_to_db(
205
191
206
192
try :
207
193
report_json = json .dumps (
208
- self .report , ensure_ascii = False , separators = ("," , ":" ), default = str
194
+ self .report_data , ensure_ascii = False , separators = ("," , ":" ), default = str
209
195
)
210
196
except Exception :
211
197
logger .exception (
@@ -214,12 +200,12 @@ def insert_to_db(
214
200
)
215
201
raise
216
202
217
- regression_summary = self .report ["summary" ]
203
+ regression_summary = self .raw_report ["summary" ]
218
204
params = {
219
205
"id" : str (self .id ),
220
206
"report_id" : self .config_id ,
221
207
"type" : self .type ,
222
- "status" : get_regression_status (self .report ["summary" ]),
208
+ "status" : get_regression_status (self .raw_report ["summary" ]),
223
209
"last_record_commit" : self .target_latest_commit ,
224
210
"last_record_ts" : last_record_ts ,
225
211
"regression_count" : regression_summary ["regression_count" ],
@@ -238,9 +224,10 @@ def insert_to_db(
238
224
self .config_id ,
239
225
self .id ,
240
226
)
241
- logger .info ("[dry run] printing db params data" )
242
227
if self .is_dry_run :
243
- print (json .dumps (params , indent = 2 , default = str ))
228
+ logger .info ("[dry run] printing db params data" )
229
+ print ({k : v for k , v in params .items () if k != "report_json" })
230
+ print (json .dumps (self .report_data , indent = 2 , default = str ))
244
231
logger .info ("[dry run] Done! Finish printing db params data" )
245
232
return False
246
233
logger .info (
@@ -382,28 +369,32 @@ def _validate_latest_meta_info(
382
369
def _to_report_data (
383
370
self ,
384
371
config_id : str ,
372
+ config : BenchmarkConfig ,
385
373
regression_report : BenchmarkRegressionReport ,
386
- frequency : Frequency ,
374
+ status : str ,
387
375
) -> dict [str , Any ]:
388
376
if not self .target_latest_commit :
389
377
raise ValueError (
390
378
f"missing commit from new is required, latest is { self .target } "
391
379
)
392
- lastest_ts_str = self .target_latest_ts_str
393
- if not lastest_ts_str :
394
- raise ValueError (f"timestamp from new is required, latest is { self .target } " )
395
380
396
- def to_dict (x ): # handle dataclass or dict/object
397
- if dataclasses .is_dataclass (x ):
398
- return dataclasses .asdict (x )
399
- if isinstance (x , dict ):
400
- return x
401
- return vars (x ) if hasattr (x , "__dict__" ) else {"value" : str (x )}
402
-
403
- report = to_dict (regression_report )
381
+ filtered = self ._filter_report (regression_report , config .report_config )
382
+ logger .info ("policy: %s" , to_dict (self .config .policy ))
404
383
return {
405
- "status" : self . status ,
384
+ "status" : status ,
406
385
"report_id" : config_id ,
407
- "report " : report ,
408
- "frequency " : frequency . get_text ( ),
386
+ "policy " : to_dict ( config . policy ) ,
387
+ "report " : to_dict ( filtered ),
409
388
}
389
+
390
+ def _filter_report (
391
+ self , report : BenchmarkRegressionReport , report_config : ReportConfig
392
+ ) -> dict [str , Any ]:
393
+ new_report = {k : v for k , v in report .items () if k != "results" }
394
+ level_order = report_config .get_severity_map ()
395
+ threshold = report_config .get_order ()
396
+
397
+ new_report ["results" ] = [
398
+ r for r in report ["results" ] if level_order [r ["label" ]] >= threshold
399
+ ]
400
+ return new_report
0 commit comments