18
18
from dateutil .parser import isoparse
19
19
20
20
21
+ # TODO(elainewy): change this to benchmark.benchmark_regression_report once the table is created
21
22
BENCHMARK_REGRESSION_REPORT_TABLE = "fortesting.benchmark_regression_report"
23
+ BENCHMARK_REGRESSION_TRACKING_CONFIG_IDS = ["compiler_regression" ]
22
24
23
25
logging .basicConfig (
24
26
level = logging .INFO ,
33
35
"CLICKHOUSE_USERNAME" : os .getenv ("CLICKHOUSE_USERNAME" , "" ),
34
36
}
35
37
36
- # TODO(elainewy): change this to benchmark.benchmark_regression_report once the table is created
37
- BENCHMARK_REGRESSION_TRACKING_CONFIG_IDS = ["compiler_regression" ]
38
-
39
38
40
39
def format_ts_with_t (ts : int ) -> str :
41
40
return dt .datetime .fromtimestamp (ts , tz = dt .timezone .utc ).strftime (
@@ -54,7 +53,6 @@ def get_clickhouse_client(
54
53
return clickhouse_connect .get_client (
55
54
host = host , user = user , password = password , secure = True , verify = False
56
55
)
57
-
58
56
return clickhouse_connect .get_client (
59
57
host = host , user = user , password = password , secure = True
60
58
)
@@ -77,8 +75,10 @@ def __init__(
77
75
config_id : str ,
78
76
end_time : int ,
79
77
is_dry_run : bool = False ,
78
+ is_pass_check : bool = False ,
80
79
) -> None :
81
80
self .is_dry_run = is_dry_run
81
+ self .is_pass_check = is_pass_check
82
82
self .config_id = config_id
83
83
self .end_time = end_time
84
84
@@ -127,6 +127,7 @@ def process(
127
127
should_generate = self ._should_generate_report (
128
128
cc , self .end_time , self .config_id , report_freq
129
129
)
130
+
130
131
if not should_generate :
131
132
self .log_info (
132
133
"Skip generate report" ,
@@ -138,7 +139,6 @@ def process(
138
139
f"with frequency { report_freq .get_text ()} ..."
139
140
)
140
141
141
- self .log_info ("get target data" )
142
142
target , ls , le = self .get_target (config , self .end_time )
143
143
if not target :
144
144
self .log_info (
@@ -157,12 +157,12 @@ def process(
157
157
regression_report = generator .generate ()
158
158
if self .is_dry_run :
159
159
print (json .dumps (regression_report , indent = 2 , default = str ))
160
- return
161
160
162
161
reportManager = ReportManager (
163
162
config = config ,
164
163
regression_report = regression_report ,
165
164
db_table_name = BENCHMARK_REGRESSION_REPORT_TABLE ,
165
+ is_dry_run = self .is_dry_run ,
166
166
)
167
167
reportManager .run (cc , ENVS ["GITHUB_TOKEN" ])
168
168
return
@@ -172,7 +172,8 @@ def get_target(self, config: BenchmarkConfig, end_time: int):
172
172
target_s = end_time - data_range .comparison_timedelta_s ()
173
173
target_e = end_time
174
174
self .log_info (
175
- f"get baseline data for time range [{ format_ts_with_t (target_s )} ,{ format_ts_with_t (target_e )} ]"
175
+ "getting target data for time range "
176
+ f"[{ format_ts_with_t (target_s )} ,{ format_ts_with_t (target_e )} ] ..."
176
177
)
177
178
target_data = self ._fetch_from_benchmark_ts_api (
178
179
config_id = config .id ,
@@ -181,7 +182,7 @@ def get_target(self, config: BenchmarkConfig, end_time: int):
181
182
source = config .source ,
182
183
)
183
184
self .log_info (
184
- f"found { len (target_data .time_series )} # of data, with time range { target_data .time_range } " ,
185
+ f"done. found { len (target_data .time_series )} # of data groups , with time range { target_data .time_range } " ,
185
186
)
186
187
if not target_data .time_range or not target_data .time_range .end :
187
188
return None , target_s , target_e
@@ -196,7 +197,8 @@ def get_baseline(self, config: BenchmarkConfig, end_time: int):
196
197
baseline_s = end_time - data_range .total_timedelta_s ()
197
198
baseline_e = end_time - data_range .comparison_timedelta_s ()
198
199
self .log_info (
199
- f"get baseline data for time range [{ format_ts_with_t (baseline_s )} ,{ format_ts_with_t (baseline_e )} ]"
200
+ "getting baseline data for time range "
201
+ f"[{ format_ts_with_t (baseline_s )} ,{ format_ts_with_t (baseline_e )} ] ..."
200
202
)
201
203
# fetch baseline from api
202
204
raw_data = self ._fetch_from_benchmark_ts_api (
@@ -207,11 +209,7 @@ def get_baseline(self, config: BenchmarkConfig, end_time: int):
207
209
)
208
210
209
211
self .log_info (
210
- f"get baseline data for time range [{ format_ts_with_t (baseline_s )} ,{ format_ts_with_t (baseline_e )} ]"
211
- )
212
-
213
- self .log_info (
214
- f"found { len (raw_data .time_series )} # of data, with time range { raw_data .time_range } " ,
212
+ f"Done. found { len (raw_data .time_series )} # of data, with time range { raw_data .time_range } " ,
215
213
)
216
214
217
215
baseline_latest_ts = int (isoparse (raw_data .time_range .end ).timestamp ())
@@ -269,11 +267,8 @@ def _fetch_from_benchmark_ts_api(
269
267
)
270
268
271
269
elapsed_ms = (time .perf_counter () - t0 ) * 1000.0
272
- logger .info (
273
- "[%s] call OK in %.1f ms (query_len=%d)" ,
274
- config_id ,
275
- elapsed_ms ,
276
- len (query ),
270
+ self .log_info (
271
+ f"call OK in { elapsed_ms } ms (query_len={ len (query )} )" ,
277
272
)
278
273
return resp .data
279
274
except requests .exceptions .HTTPError as e :
@@ -290,7 +285,7 @@ def _fetch_from_benchmark_ts_api(
290
285
else str (e )
291
286
)
292
287
self .log_error (
293
- f"[ { config_id } ] call FAILED in { elapsed_ms } ms: { err_msg } " ,
288
+ f"call FAILED in { elapsed_ms } ms: { err_msg } " ,
294
289
)
295
290
raise
296
291
@@ -348,6 +343,12 @@ def _get_latest_record_ts(
348
343
f"time_boundary({ format_ts_with_t (time_boundary )} )"
349
344
f"based on latest_record_ts({ format_ts_with_t (latest_record_ts )} )" ,
350
345
)
346
+ # dry_run is True, is_pass_check is True, then we allow to generate report even the time check is not met
347
+ if self .is_dry_run and self .is_pass_check :
348
+ should_generate = True
349
+ self .log_info (
350
+ f"[{ f .get_text ()} ] dry_run is True, is_pass_check is True, force generate report for print only" ,
351
+ )
351
352
return should_generate
352
353
353
354
@@ -357,7 +358,12 @@ def main(
357
358
args : Optional [argparse .Namespace ] = None ,
358
359
* ,
359
360
is_dry_run : bool = False ,
361
+ is_forced : bool = False ,
360
362
):
363
+ if not is_dry_run and is_forced :
364
+ is_forced = False
365
+ logger .info ("is_dry_run is False, force must be disabled, this is not allowed" )
366
+
361
367
if not github_access_token :
362
368
raise ValueError ("Missing environment variable GITHUB_TOKEN" )
363
369
@@ -378,7 +384,10 @@ def main(
378
384
# caution, raise exception may lead lambda to retry
379
385
try :
380
386
processor = BenchmarkSummaryProcessor (
381
- config_id = config_id , end_time = end_time_ts , is_dry_run = is_dry_run
387
+ config_id = config_id ,
388
+ end_time = end_time_ts ,
389
+ is_dry_run = is_dry_run ,
390
+ is_pass_check = is_forced ,
382
391
)
383
392
processor .process (args = args )
384
393
except Exception as e :
@@ -419,6 +428,12 @@ def parse_args() -> argparse.Namespace:
419
428
action = "store_false" ,
420
429
help = "Disable dry-run mode" ,
421
430
)
431
+ parser .add_argument (
432
+ "--force" ,
433
+ dest = "force" ,
434
+ action = "store_true" ,
435
+ help = "Enable force mode, this only allowed when dry-run is enabled" ,
436
+ )
422
437
parser .add_argument (
423
438
"--config-id" ,
424
439
type = str ,
@@ -466,6 +481,7 @@ def local_run() -> None:
466
481
github_access_token = args .github_access_token ,
467
482
args = args ,
468
483
is_dry_run = args .dry_run ,
484
+ is_forced = args .force ,
469
485
)
470
486
471
487
0 commit comments