Skip to content

Commit 0a28637

Browse files
authored
Merge pull request ClickHouse#78089 from ClickHouse/ci_support_for_s3usage_meters_in_praktika
CI: Add S3 Usage meters to praktika
2 parents 602aa5e + 545e82c commit 0a28637

File tree

9 files changed

+459
-68
lines changed

9 files changed

+459
-68
lines changed

ci/praktika/cidb.py

Lines changed: 50 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,11 @@
55
from typing import Optional
66

77
import requests
8-
from praktika.info import Info
98

109
from ._environment import _Environment
10+
from .info import Info
1111
from .result import Result
12+
from .s3 import StorageUsage
1213
from .settings import Settings
1314
from .utils import Utils
1415

@@ -103,7 +104,7 @@ def json_data_generator(cls, result: Result):
103104
record.test_context_raw = result_.info
104105
yield json.dumps(dataclasses.asdict(record))
105106

106-
def insert(self, result: Result):
107+
def insert_rows(self, jsons, retries=3):
107108
params = {
108109
"database": Settings.CI_DB_DB_NAME,
109110
"query": f"INSERT INTO {Settings.CI_DB_TABLE_NAME} FORMAT JSONEachRow",
@@ -112,12 +113,7 @@ def insert(self, result: Result):
112113
}
113114
assert Settings.CI_DB_TABLE_NAME
114115

115-
MAX_RETRIES = 3
116-
jsons = []
117-
for json_str in self.json_data_generator(result):
118-
jsons.append(json_str)
119-
120-
for retry in range(MAX_RETRIES):
116+
for retry in range(retries):
121117
try:
122118
response = requests.post(
123119
url=self.url,
@@ -131,14 +127,58 @@ def insert(self, result: Result):
131127
print(f"INFO: {len(jsons)} rows inserted into CIDB")
132128
break
133129
else:
134-
if retry == MAX_RETRIES - 1:
130+
if retry == retries - 1:
135131
raise RuntimeError(
136132
f"Failed to write to CI DB, response code [{response.status_code}]"
137133
)
138134
except Exception as ex:
139-
if retry == MAX_RETRIES - 1:
135+
if retry == retries - 1:
140136
raise ex
141137

138+
def insert(self, result: Result):
139+
jsons = []
140+
for json_str in self.json_data_generator(result):
141+
jsons.append(json_str)
142+
self.insert_rows(jsons)
143+
return self
144+
145+
def insert_storage_usage(self, storage_usage: StorageUsage):
146+
info = Info()
147+
json_rows = []
148+
record = self.TableRecord(
149+
pull_request_number=info.pr_number,
150+
commit_sha=info.sha,
151+
commit_url=info.commit_url,
152+
check_name="Usage",
153+
check_status=Result.Status.SUCCESS,
154+
check_duration_ms=0,
155+
check_start_time=Utils.timestamp_to_str(Utils.timestamp()),
156+
report_url=info.get_report_url(),
157+
pull_request_url=info.change_url,
158+
base_ref=info.base_branch,
159+
base_repo=info.repo_name,
160+
head_ref=info.git_branch,
161+
head_repo=info.fork_name,
162+
task_url="",
163+
instance_type=",".join(
164+
filter(None, [info.instance_type, info.instance_lifecycle])
165+
),
166+
instance_id=info.instance_id,
167+
test_name="storage_usage_uploaded_bytes",
168+
test_status="OK",
169+
test_duration_ms=storage_usage.uploaded,
170+
test_context_raw="test_duration_ms shows total size uploaded in bytes",
171+
)
172+
json_rows.append(json.dumps(dataclasses.asdict(record)))
173+
record.test_name = "storage_usage_uploaded_items"
174+
record.test_duration_ms = len(storage_usage.uploaded_details)
175+
record.test_context_raw = (
176+
"test_duration_ms shows total number of uniq object names uploaded"
177+
)
178+
json_rows.append(json.dumps(dataclasses.asdict(record)))
179+
self.insert_rows(json_rows)
180+
return self
181+
142182
def check(self):
143183
# Create a session object
144184
params = {

ci/praktika/hook_html.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
from .parser import WorkflowConfigParser
1313
from .result import Result, ResultInfo, _ResultS3
1414
from .runtime import RunConfig
15-
from .s3 import S3
15+
from .s3 import S3, StorageUsage
1616
from .settings import Settings
1717
from .utils import Utils
1818

@@ -225,6 +225,14 @@ def run(cls, _workflow, _job):
225225
def post_run(cls, _workflow, _job, info_errors):
226226
result = Result.from_fs(_job.name)
227227
_ResultS3.upload_result_files_to_s3(result).dump()
228+
storage_usage = None
229+
if StorageUsage.exist():
230+
StorageUsage.add_uploaded(
231+
result.file_name()
232+
) # add Result file beforehand to upload actual storage usage data
233+
print("Storage usage data found - add to Result")
234+
storage_usage = StorageUsage.from_fs()
235+
result.ext["storage_usage"] = storage_usage
228236
_ResultS3.copy_result_to_s3(result)
229237

230238
env = _Environment.get()
@@ -282,6 +290,7 @@ def add_dependees(job_name):
282290
new_info=new_result_info,
283291
new_sub_results=new_sub_results,
284292
workflow_name=_workflow.name,
293+
storage_usage=storage_usage,
285294
)
286295

287296
if updated_status:

ci/praktika/html_prepare.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,23 @@
77
class Html:
88
@classmethod
99
def prepare(cls, is_test):
10+
import htmlmin
11+
1012
if is_test:
1113
page_file = Settings.HTML_PAGE_FILE.removesuffix(".html") + "_test.html"
1214
Shell.check(f"cp {Settings.HTML_PAGE_FILE} {page_file}")
1315
else:
1416
page_file = Settings.HTML_PAGE_FILE
17+
18+
with open(page_file, "r", encoding="utf-8") as f:
19+
html = f.read()
20+
21+
minified = htmlmin.minify(html, remove_comments=True, remove_empty_space=True)
22+
23+
with open(page_file, "w", encoding="utf-8") as f:
24+
f.write(minified)
25+
1526
S3.copy_file_to_s3(s3_path=Settings.HTML_S3_PATH, local_path=page_file)
27+
28+
with open(page_file, "w", encoding="utf-8") as f:
29+
f.write(html)

ci/praktika/info.py

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
from pathlib import Path
44
from typing import Optional
55

6-
from praktika.runtime import RunConfig
7-
from praktika.settings import Settings
6+
from .runtime import RunConfig
7+
from .settings import Settings
88

99

1010
class Info:
@@ -51,10 +51,18 @@ def pr_url(self):
5151
def commit_url(self):
5252
return self.env.COMMIT_URL
5353

54+
@property
55+
def change_url(self):
56+
return self.pr_url if self.pr_number else self.commit_url
57+
5458
@property
5559
def git_branch(self):
5660
return self.env.BRANCH
5761

62+
@property
63+
def base_branch(self):
64+
return self.env.BASE_BRANCH
65+
5866
@property
5967
def git_sha(self):
6068
return self.env.SHA
@@ -83,6 +91,10 @@ def pr_labels(self):
8391
def instance_type(self):
8492
return self.env.INSTANCE_TYPE
8593

94+
@property
95+
def instance_lifecycle(self):
96+
return self.env.INSTANCE_LIFE_CYCLE
97+
8698
@property
8799
def instance_id(self):
88100
return self.env.INSTANCE_ID
@@ -93,7 +105,7 @@ def is_local_run(self):
93105

94106
# TODO: Consider defining secrets outside of workflow as it project data in most of the cases
95107
def get_secret(self, name):
96-
from praktika.mangle import _get_workflows
108+
from .mangle import _get_workflows
97109

98110
if not self.workflow:
99111
self.workflow = _get_workflows(self.env.WORKFLOW_NAME)[0]
@@ -115,7 +127,7 @@ def dump(self):
115127
self.env.dump()
116128

117129
def get_specific_report_url(self, pr_number, branch, sha, job_name=""):
118-
from praktika.settings import Settings
130+
from .settings import Settings
119131

120132
if pr_number:
121133
ref_param = f"PR={pr_number}"
@@ -134,7 +146,7 @@ def get_specific_report_url(self, pr_number, branch, sha, job_name=""):
134146

135147
@staticmethod
136148
def get_workflow_input_value(input_name) -> Optional[str]:
137-
from praktika.settings import _Settings
149+
from .settings import _Settings
138150

139151
try:
140152
with open(_Settings.WORKFLOW_INPUTS_FILE, "r", encoding="utf8") as f:
@@ -174,7 +186,7 @@ def is_workflow_ok(self):
174186
Experimental function
175187
:return:
176188
"""
177-
from praktika.result import Result
189+
from .result import Result
178190

179191
result = Result.from_fs(self.env.WORKFLOW_NAME)
180192
for subresult in result.results:

0 commit comments

Comments
 (0)