Skip to content

Commit 2bb8eb7

Browse files
authored
Bundle analysis add to sizes to timeseries (#493)
1 parent 099911a commit 2bb8eb7

7 files changed

+833
-46
lines changed

services/bundle_analysis.py

+136-1
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,27 @@
1313
BundleAnalysisReportLoader,
1414
BundleChange,
1515
)
16+
from shared.bundle_analysis.models import AssetType
1617
from shared.bundle_analysis.storage import get_bucket_name
1718
from shared.reports.enums import UploadState
1819
from shared.storage import get_appropriate_storage_service
1920
from shared.storage.exceptions import FileNotInStorageError, PutRequestRateLimitError
2021
from shared.torngit.base import TorngitBaseAdapter
2122
from shared.torngit.exceptions import TorngitClientError
2223
from shared.yaml import UserYaml
24+
from sqlalchemy.dialects.postgresql import insert
25+
from sqlalchemy.orm import Session
2326

2427
from database.enums import ReportType
25-
from database.models import Commit, CommitReport, Repository, Upload, UploadError
28+
from database.models import (
29+
Commit,
30+
CommitReport,
31+
Measurement,
32+
MeasurementName,
33+
Repository,
34+
Upload,
35+
UploadError,
36+
)
2637
from database.models.core import GITHUB_APP_INSTALLATION_DEFAULT_NAME
2738
from services.archive import ArchiveService
2839
from services.report import BaseReportService
@@ -32,6 +43,7 @@
3243
get_repo_provider_service,
3344
)
3445
from services.storage import get_storage_client
46+
from services.timeseries import repository_datasets_query
3547
from services.urls import get_bundle_analysis_pull_url
3648
from services.yaml import read_yaml_field
3749

@@ -253,6 +265,129 @@ def process_upload(self, commit: Commit, upload: Upload) -> ProcessingResult:
253265
session_id=session_id,
254266
)
255267

268+
def _save_to_timeseries(
269+
self,
270+
db_session: Session,
271+
commit: Commit,
272+
name: str,
273+
measurable_id: str,
274+
value: float,
275+
):
276+
command = insert(Measurement.__table__).values(
277+
name=name,
278+
owner_id=commit.repository.ownerid,
279+
repo_id=commit.repoid,
280+
measurable_id=measurable_id,
281+
branch=commit.branch,
282+
commit_sha=commit.commitid,
283+
timestamp=commit.timestamp,
284+
value=value,
285+
)
286+
command = command.on_conflict_do_update(
287+
index_elements=[
288+
Measurement.name,
289+
Measurement.owner_id,
290+
Measurement.repo_id,
291+
Measurement.measurable_id,
292+
Measurement.commit_sha,
293+
Measurement.timestamp,
294+
],
295+
set_=dict(
296+
branch=command.excluded.branch,
297+
value=command.excluded.value,
298+
),
299+
)
300+
db_session.execute(command)
301+
db_session.flush()
302+
303+
@sentry_sdk.trace
304+
def save_measurements(self, commit: Commit, upload: Upload) -> ProcessingResult:
305+
"""
306+
Save timeseries measurements for this bundle analysis report
307+
"""
308+
try:
309+
commit_report: CommitReport = upload.report
310+
repo_hash = ArchiveService.get_archive_hash(commit_report.commit.repository)
311+
storage_service = get_storage_client()
312+
bundle_loader = BundleAnalysisReportLoader(storage_service, repo_hash)
313+
314+
# fetch existing bundle report from storage
315+
bundle_analysis_report = bundle_loader.load(commit_report.external_id)
316+
317+
dataset_names = [
318+
dataset.name for dataset in repository_datasets_query(commit.repository)
319+
]
320+
321+
db_session = commit.get_db_session()
322+
for bundle_report in bundle_analysis_report.bundle_reports():
323+
# For overall bundle size
324+
if MeasurementName.bundle_analysis_report_size.value in dataset_names:
325+
self._save_to_timeseries(
326+
db_session,
327+
commit,
328+
MeasurementName.bundle_analysis_report_size.value,
329+
bundle_report.name,
330+
bundle_report.total_size(),
331+
)
332+
333+
# For individual javascript associated assets using UUID
334+
if MeasurementName.bundle_analysis_asset_size.value in dataset_names:
335+
for asset in bundle_report.asset_reports():
336+
if asset.asset_type == AssetType.JAVASCRIPT:
337+
self._save_to_timeseries(
338+
db_session,
339+
commit,
340+
MeasurementName.bundle_analysis_asset_size.value,
341+
asset.uuid,
342+
asset.size,
343+
)
344+
345+
# For asset types sizes
346+
asset_type_map = {
347+
MeasurementName.bundle_analysis_font_size: AssetType.FONT,
348+
MeasurementName.bundle_analysis_image_size: AssetType.IMAGE,
349+
MeasurementName.bundle_analysis_stylesheet_size: AssetType.STYLESHEET,
350+
MeasurementName.bundle_analysis_javascript_size: AssetType.JAVASCRIPT,
351+
}
352+
for measurement_name, asset_type in asset_type_map.items():
353+
if measurement_name.value in dataset_names:
354+
total_size = 0
355+
for asset in bundle_report.asset_reports():
356+
if asset.asset_type == asset_type:
357+
total_size += asset.size
358+
self._save_to_timeseries(
359+
db_session,
360+
commit,
361+
measurement_name.value,
362+
bundle_report.name,
363+
total_size,
364+
)
365+
366+
return ProcessingResult(
367+
upload=upload,
368+
commit=commit,
369+
)
370+
except Exception:
371+
sentry_metrics.incr(
372+
"bundle_analysis_upload",
373+
tags={
374+
"result": "parser_error",
375+
"repository": commit.repository.repoid,
376+
},
377+
)
378+
return ProcessingResult(
379+
upload=upload,
380+
commit=commit,
381+
error=ProcessingError(
382+
code="measurement_save_error",
383+
params={
384+
"location": upload.storage_path,
385+
"repository": commit.repository.repoid,
386+
},
387+
is_retryable=False,
388+
),
389+
)
390+
256391

257392
class ComparisonError(Exception):
258393
pass

0 commit comments

Comments
 (0)