diff --git a/graphql_api/tests/test_bundle_analysis_measurements.py b/graphql_api/tests/test_bundle_analysis_measurements.py index 73883091a4..52a320124e 100644 --- a/graphql_api/tests/test_bundle_analysis_measurements.py +++ b/graphql_api/tests/test_bundle_analysis_measurements.py @@ -111,48 +111,46 @@ def test_bundle_report_measurements(self, get_storage_service): repository(name: $repo) { ... on Repository { commit(id: $commit) { - bundleAnalysis { - bundleAnalysisReport { - __typename - ... on BundleAnalysisReport { - bundle(name: "super") { + bundleAnalysisReport { + __typename + ... on BundleAnalysisReport { + bundle(name: "super") { + name + measurements( + filters: $filters + orderingDirection: $orderingDirection + after: $after + interval: $interval + before: $before + ){ + assetType name - measurements( - filters: $filters - orderingDirection: $orderingDirection - after: $after - interval: $interval - before: $before - ){ - assetType - name + size { + loadTime { + threeG + highSpeed + } size { - loadTime { - threeG - highSpeed - } - size { - gzip - uncompress - } + gzip + uncompress } - change { - loadTime { - threeG - highSpeed - } - size { - gzip - uncompress - } + } + change { + loadTime { + threeG + highSpeed } - measurements { - avg - min - max - timestamp + size { + gzip + uncompress } } + measurements { + avg + min + max + timestamp + } } } } @@ -178,7 +176,7 @@ def test_bundle_report_measurements(self, get_storage_service): data = self.gql_request(query, variables=variables) commit = data["owner"]["repository"]["commit"] - assert commit["bundleAnalysis"]["bundleAnalysisReport"] == { + assert commit["bundleAnalysisReport"] == { "__typename": "BundleAnalysisReport", "bundle": { "measurements": [ @@ -581,6 +579,62 @@ def test_bundle_report_measurements(self, get_storage_service): }, }, }, + { + "assetType": "UNKNOWN_SIZE", + "change": { + "loadTime": { + "highSpeed": 0, + "threeG": 0, + }, + "size": { + "gzip": 0, + "uncompress": 0, + }, + }, + "measurements": [ + { + "avg": 0.0, + "max": 0.0, + "min": 0.0, + "timestamp": "2024-06-06T00:00:00+00:00", + }, + { + "avg": None, + "max": None, + "min": None, + "timestamp": "2024-06-07T00:00:00+00:00", + }, + { + "avg": None, + "max": None, + "min": None, + "timestamp": "2024-06-08T00:00:00+00:00", + }, + { + "avg": None, + "max": None, + "min": None, + "timestamp": "2024-06-09T00:00:00+00:00", + }, + { + "avg": 0.0, + "max": 0.0, + "min": 0.0, + "timestamp": "2024-06-10T00:00:00+00:00", + }, + ], + "name": None, + "size": { + "loadTime": { + "highSpeed": 0, + "threeG": 0, + }, + "size": { + "gzip": 0, + "uncompress": 0, + }, + }, + }, ], "name": "super", }, @@ -600,7 +654,7 @@ def test_bundle_report_measurements(self, get_storage_service): data = self.gql_request(query, variables=variables) commit = data["owner"]["repository"]["commit"] - assert commit["bundleAnalysis"]["bundleAnalysisReport"] == { + assert commit["bundleAnalysisReport"] == { "__typename": "BundleAnalysisReport", "bundle": { "measurements": [ @@ -691,47 +745,45 @@ def test_bundle_asset_measurements(self, get_storage_service): repository(name: $repo) { ... on Repository { commit(id: $commit) { - bundleAnalysis { - bundleAnalysisReport { - __typename - ... on BundleAnalysisReport { - bundle(name: "super") { - asset(name: $asset){ + bundleAnalysisReport { + __typename + ... on BundleAnalysisReport { + bundle(name: "super") { + asset(name: $asset){ + name + measurements( + after: $after + interval: $interval + before: $before + ){ + assetType name - measurements( - after: $after - interval: $interval - before: $before - ){ - assetType - name + size { + loadTime { + threeG + highSpeed + } size { - loadTime { - threeG - highSpeed - } - size { - gzip - uncompress - } + gzip + uncompress } - change { - loadTime { - threeG - highSpeed - } - size { - gzip - uncompress - } + } + change { + loadTime { + threeG + highSpeed } - measurements { - avg - min - max - timestamp + size { + gzip + uncompress } } + measurements { + avg + min + max + timestamp + } } } } @@ -757,7 +809,7 @@ def test_bundle_asset_measurements(self, get_storage_service): data = self.gql_request(query, variables=variables) commit = data["owner"]["repository"]["commit"] - assert commit["bundleAnalysis"]["bundleAnalysisReport"] == { + assert commit["bundleAnalysisReport"] == { "__typename": "BundleAnalysisReport", "bundle": { "asset": { @@ -835,7 +887,7 @@ def test_bundle_asset_measurements(self, get_storage_service): data = self.gql_request(query, variables=variables) commit = data["owner"]["repository"]["commit"] - assert commit["bundleAnalysis"]["bundleAnalysisReport"] == { + assert commit["bundleAnalysisReport"] == { "__typename": "BundleAnalysisReport", "bundle": { "asset": { @@ -872,48 +924,46 @@ def test_bundle_report_measurements_carryovers(self, get_storage_service): repository(name: $repo) { ... on Repository { commit(id: $commit) { - bundleAnalysis { - bundleAnalysisReport { - __typename - ... on BundleAnalysisReport { - bundle(name: "super") { + bundleAnalysisReport { + __typename + ... on BundleAnalysisReport { + bundle(name: "super") { + name + measurements( + filters: $filters + orderingDirection: $orderingDirection + after: $after + interval: $interval + before: $before + ){ + assetType name - measurements( - filters: $filters - orderingDirection: $orderingDirection - after: $after - interval: $interval - before: $before - ){ - assetType - name + size { + loadTime { + threeG + highSpeed + } size { - loadTime { - threeG - highSpeed - } - size { - gzip - uncompress - } + gzip + uncompress } - change { - loadTime { - threeG - highSpeed - } - size { - gzip - uncompress - } + } + change { + loadTime { + threeG + highSpeed } - measurements { - avg - min - max - timestamp + size { + gzip + uncompress } } + measurements { + avg + min + max + timestamp + } } } } @@ -939,7 +989,7 @@ def test_bundle_report_measurements_carryovers(self, get_storage_service): data = self.gql_request(query, variables=variables) commit = data["owner"]["repository"]["commit"] - assert commit["bundleAnalysis"]["bundleAnalysisReport"] == { + assert commit["bundleAnalysisReport"] == { "__typename": "BundleAnalysisReport", "bundle": { "measurements": [ @@ -1300,6 +1350,56 @@ def test_bundle_report_measurements_carryovers(self, get_storage_service): }, }, }, + { + "assetType": "UNKNOWN_SIZE", + "change": { + "loadTime": { + "highSpeed": 0, + "threeG": 0, + }, + "size": { + "gzip": 0, + "uncompress": 0, + }, + }, + "measurements": [ + { + "avg": 0.0, + "max": 0.0, + "min": 0.0, + "timestamp": "2024-06-07T00:00:00+00:00", + }, + { + "avg": None, + "max": None, + "min": None, + "timestamp": "2024-06-08T00:00:00+00:00", + }, + { + "avg": None, + "max": None, + "min": None, + "timestamp": "2024-06-09T00:00:00+00:00", + }, + { + "avg": 0.0, + "max": 0.0, + "min": 0.0, + "timestamp": "2024-06-10T00:00:00+00:00", + }, + ], + "name": None, + "size": { + "loadTime": { + "highSpeed": 0, + "threeG": 0, + }, + "size": { + "gzip": 0, + "uncompress": 0, + }, + }, + }, ], "name": "super", }, @@ -1319,7 +1419,7 @@ def test_bundle_report_measurements_carryovers(self, get_storage_service): data = self.gql_request(query, variables=variables) commit = data["owner"]["repository"]["commit"] - assert commit["bundleAnalysis"]["bundleAnalysisReport"] == { + assert commit["bundleAnalysisReport"] == { "__typename": "BundleAnalysisReport", "bundle": { "measurements": [ @@ -1405,48 +1505,46 @@ def test_bundle_report_no_carryovers(self, get_storage_service): repository(name: $repo) { ... on Repository { commit(id: $commit) { - bundleAnalysis { - bundleAnalysisReport { - __typename - ... on BundleAnalysisReport { - bundle(name: "super") { + bundleAnalysisReport { + __typename + ... on BundleAnalysisReport { + bundle(name: "super") { + name + measurements( + filters: $filters + orderingDirection: $orderingDirection + after: $after + interval: $interval + before: $before + ){ + assetType name - measurements( - filters: $filters - orderingDirection: $orderingDirection - after: $after - interval: $interval - before: $before - ){ - assetType - name + size { + loadTime { + threeG + highSpeed + } size { - loadTime { - threeG - highSpeed - } - size { - gzip - uncompress - } + gzip + uncompress } - change { - loadTime { - threeG - highSpeed - } - size { - gzip - uncompress - } + } + change { + loadTime { + threeG + highSpeed } - measurements { - avg - min - max - timestamp + size { + gzip + uncompress } } + measurements { + avg + min + max + timestamp + } } } } @@ -1472,7 +1570,7 @@ def test_bundle_report_no_carryovers(self, get_storage_service): data = self.gql_request(query, variables=variables) commit = data["owner"]["repository"]["commit"] - assert commit["bundleAnalysis"]["bundleAnalysisReport"] == { + assert commit["bundleAnalysisReport"] == { "__typename": "BundleAnalysisReport", "bundle": { "measurements": [ @@ -1917,39 +2015,16 @@ def test_bundle_report_no_carryovers(self, get_storage_service): }, }, }, - ], - "name": "super", - }, - } - - # Test with using asset type filters - variables = { - "org": self.org.username, - "repo": self.repo.name, - "commit": self.commit.commitid, - "orderingDirection": "ASC", - "interval": "INTERVAL_1_DAY", - "after": "2024-06-05", - "before": "2024-06-10", - "filters": {"assetTypes": "JAVASCRIPT_SIZE"}, - } - data = self.gql_request(query, variables=variables) - commit = data["owner"]["repository"]["commit"] - - assert commit["bundleAnalysis"]["bundleAnalysisReport"] == { - "__typename": "BundleAnalysisReport", - "bundle": { - "measurements": [ { - "assetType": "JAVASCRIPT_SIZE", + "assetType": "UNKNOWN_SIZE", "change": { "loadTime": { - "highSpeed": 5, - "threeG": 224, + "highSpeed": 0, + "threeG": 0, }, "size": { - "gzip": 21, - "uncompress": 21000, + "gzip": 0, + "uncompress": 0, }, }, "measurements": [ @@ -1960,9 +2035,9 @@ def test_bundle_report_no_carryovers(self, get_storage_service): "timestamp": "2024-06-05T00:00:00+00:00", }, { - "avg": 5708.0, - "max": 5708.0, - "min": 5708.0, + "avg": 0.0, + "max": 0.0, + "min": 0.0, "timestamp": "2024-06-06T00:00:00+00:00", }, { @@ -1984,20 +2059,105 @@ def test_bundle_report_no_carryovers(self, get_storage_service): "timestamp": "2024-06-09T00:00:00+00:00", }, { - "avg": 26708.0, - "max": 26708.0, - "min": 26708.0, + "avg": 0.0, + "max": 0.0, + "min": 0.0, "timestamp": "2024-06-10T00:00:00+00:00", }, ], "name": None, "size": { "loadTime": { - "highSpeed": 7, - "threeG": 284, + "highSpeed": 0, + "threeG": 0, }, "size": { - "gzip": 26, + "gzip": 0, + "uncompress": 0, + }, + }, + }, + ], + "name": "super", + }, + } + + # Test with using asset type filters + variables = { + "org": self.org.username, + "repo": self.repo.name, + "commit": self.commit.commitid, + "orderingDirection": "ASC", + "interval": "INTERVAL_1_DAY", + "after": "2024-06-05", + "before": "2024-06-10", + "filters": {"assetTypes": "JAVASCRIPT_SIZE"}, + } + data = self.gql_request(query, variables=variables) + commit = data["owner"]["repository"]["commit"] + + assert commit["bundleAnalysisReport"] == { + "__typename": "BundleAnalysisReport", + "bundle": { + "measurements": [ + { + "assetType": "JAVASCRIPT_SIZE", + "change": { + "loadTime": { + "highSpeed": 5, + "threeG": 224, + }, + "size": { + "gzip": 21, + "uncompress": 21000, + }, + }, + "measurements": [ + { + "avg": None, + "max": None, + "min": None, + "timestamp": "2024-06-05T00:00:00+00:00", + }, + { + "avg": 5708.0, + "max": 5708.0, + "min": 5708.0, + "timestamp": "2024-06-06T00:00:00+00:00", + }, + { + "avg": None, + "max": None, + "min": None, + "timestamp": "2024-06-07T00:00:00+00:00", + }, + { + "avg": None, + "max": None, + "min": None, + "timestamp": "2024-06-08T00:00:00+00:00", + }, + { + "avg": None, + "max": None, + "min": None, + "timestamp": "2024-06-09T00:00:00+00:00", + }, + { + "avg": 26708.0, + "max": 26708.0, + "min": 26708.0, + "timestamp": "2024-06-10T00:00:00+00:00", + }, + ], + "name": None, + "size": { + "loadTime": { + "highSpeed": 7, + "threeG": 284, + }, + "size": { + "gzip": 26, "uncompress": 26708, }, }, @@ -2054,49 +2214,47 @@ def test_bundle_report_branch(self, get_storage_service): repository(name: $repo) { ... on Repository { commit(id: $commit) { - bundleAnalysis { - bundleAnalysisReport { - __typename - ... on BundleAnalysisReport { - bundle(name: "super") { + bundleAnalysisReport { + __typename + ... on BundleAnalysisReport { + bundle(name: "super") { + name + measurements( + filters: $filters + orderingDirection: $orderingDirection + after: $after + interval: $interval + before: $before + branch: $branch + ){ + assetType name - measurements( - filters: $filters - orderingDirection: $orderingDirection - after: $after - interval: $interval - before: $before - branch: $branch - ){ - assetType - name + size { + loadTime { + threeG + highSpeed + } size { - loadTime { - threeG - highSpeed - } - size { - gzip - uncompress - } + gzip + uncompress } - change { - loadTime { - threeG - highSpeed - } - size { - gzip - uncompress - } + } + change { + loadTime { + threeG + highSpeed } - measurements { - avg - min - max - timestamp + size { + gzip + uncompress } } + measurements { + avg + min + max + timestamp + } } } } @@ -2122,7 +2280,7 @@ def test_bundle_report_branch(self, get_storage_service): data = self.gql_request(query, variables=variables) commit = data["owner"]["repository"]["commit"] - assert commit["bundleAnalysis"]["bundleAnalysisReport"] == { + assert commit["bundleAnalysisReport"] == { "__typename": "BundleAnalysisReport", "bundle": { "name": "super", @@ -2214,6 +2372,56 @@ def test_bundle_report_branch(self, get_storage_service): "change": None, "measurements": [], }, + { + "assetType": "UNKNOWN_SIZE", + "change": { + "loadTime": { + "highSpeed": 0, + "threeG": -3, + }, + "size": { + "gzip": 0, + "uncompress": -333, + }, + }, + "measurements": [ + { + "avg": 456.0, + "max": 456.0, + "min": 456.0, + "timestamp": "2024-06-07T00:00:00+00:00", + }, + { + "avg": None, + "max": None, + "min": None, + "timestamp": "2024-06-08T00:00:00+00:00", + }, + { + "avg": None, + "max": None, + "min": None, + "timestamp": "2024-06-09T00:00:00+00:00", + }, + { + "avg": 123.0, + "max": 123.0, + "min": 123.0, + "timestamp": "2024-06-10T00:00:00+00:00", + }, + ], + "name": None, + "size": { + "loadTime": { + "highSpeed": 0, + "threeG": 1, + }, + "size": { + "gzip": 0, + "uncompress": 123, + }, + }, + }, ], }, } @@ -2265,49 +2473,47 @@ def test_bundle_report_no_after(self, get_storage_service): repository(name: $repo) { ... on Repository { commit(id: $commit) { - bundleAnalysis { - bundleAnalysisReport { - __typename - ... on BundleAnalysisReport { - bundle(name: "super") { + bundleAnalysisReport { + __typename + ... on BundleAnalysisReport { + bundle(name: "super") { + name + measurements( + filters: $filters + orderingDirection: $orderingDirection + after: $after + interval: $interval + before: $before + branch: $branch + ){ + assetType name - measurements( - filters: $filters - orderingDirection: $orderingDirection - after: $after - interval: $interval - before: $before - branch: $branch - ){ - assetType - name + size { + loadTime { + threeG + highSpeed + } size { - loadTime { - threeG - highSpeed - } - size { - gzip - uncompress - } + gzip + uncompress } - change { - loadTime { - threeG - highSpeed - } - size { - gzip - uncompress - } + } + change { + loadTime { + threeG + highSpeed } - measurements { - avg - min - max - timestamp + size { + gzip + uncompress } } + measurements { + avg + min + max + timestamp + } } } } @@ -2333,7 +2539,7 @@ def test_bundle_report_no_after(self, get_storage_service): data = self.gql_request(query, variables=variables) commit = data["owner"]["repository"]["commit"] - assert commit["bundleAnalysis"]["bundleAnalysisReport"] == { + assert commit["bundleAnalysisReport"] == { "__typename": "BundleAnalysisReport", "bundle": { "name": "super", @@ -2431,6 +2637,320 @@ def test_bundle_report_no_after(self, get_storage_service): "change": None, "measurements": [], }, + { + "assetType": "UNKNOWN_SIZE", + "change": { + "loadTime": { + "highSpeed": 0, + "threeG": -3, + }, + "size": { + "gzip": 0, + "uncompress": -333, + }, + }, + "measurements": [ + { + "avg": 456.0, + "max": 456.0, + "min": 456.0, + "timestamp": "2024-06-06T00:00:00+00:00", + }, + { + "avg": None, + "max": None, + "min": None, + "timestamp": "2024-06-07T00:00:00+00:00", + }, + { + "avg": None, + "max": None, + "min": None, + "timestamp": "2024-06-08T00:00:00+00:00", + }, + { + "avg": None, + "max": None, + "min": None, + "timestamp": "2024-06-09T00:00:00+00:00", + }, + { + "avg": 123.0, + "max": 123.0, + "min": 123.0, + "timestamp": "2024-06-10T00:00:00+00:00", + }, + ], + "name": None, + "size": { + "loadTime": { + "highSpeed": 0, + "threeG": 1, + }, + "size": { + "gzip": 0, + "uncompress": 123, + }, + }, + }, + ], + }, + } + + @patch("graphql_api.dataloader.bundle_analysis.get_appropriate_storage_service") + def test_bundle_report_bad_data_check(self, get_storage_service): + measurements_data = [ + # 2024-06-10 + ["bundle_analysis_report_size", "super", "2024-06-10T19:07:23", 123], + # 2024-06-06 + ["bundle_analysis_image_size", "super", "2024-06-06T19:07:23", 456], + # 2024-06-05 + ["bundle_analysis_image_size", "super", "2024-06-05T19:07:23", 666], + ] + + for item in measurements_data: + MeasurementFactory( + name=item[0], + owner_id=self.org.pk, + repo_id=self.repo.pk, + branch="feat", + measurable_id=item[1], + commit_sha=self.commit.pk, + timestamp=item[2], + value=item[3], + ) + + storage = MemoryStorageService({}) + get_storage_service.return_value = storage + + with open("./services/tests/samples/bundle_with_uuid.sqlite", "rb") as f: + storage_path = StoragePaths.bundle_report.path( + repo_key=ArchiveService.get_archive_hash(self.repo), + report_key=self.head_commit_report.external_id, + ) + storage.write_file(get_bucket_name(), storage_path, f) + + query = """ + query FetchMeasurements( + $org: String!, + $repo: String!, + $commit: String! + $filters: BundleAnalysisMeasurementsSetFilters + $orderingDirection: OrderingDirection! + $interval: MeasurementInterval! + $before: DateTime! + $after: DateTime + $branch: String! + ) { + owner(username: $org) { + repository(name: $repo) { + ... on Repository { + commit(id: $commit) { + bundleAnalysisReport { + __typename + ... on BundleAnalysisReport { + bundle(name: "super") { + name + measurements( + filters: $filters + orderingDirection: $orderingDirection + after: $after + interval: $interval + before: $before + branch: $branch + ){ + assetType + name + size { + loadTime { + threeG + highSpeed + } + size { + gzip + uncompress + } + } + change { + loadTime { + threeG + highSpeed + } + size { + gzip + uncompress + } + } + measurements { + avg + min + max + timestamp + } + } + } + } + } + } + } + } + } + } + """ + + variables = { + "org": self.org.username, + "repo": self.repo.name, + "commit": self.commit.commitid, + "orderingDirection": "ASC", + "interval": "INTERVAL_1_DAY", + "after": None, + "before": "2024-06-10", + "branch": "feat", + "filters": {}, + } + data = self.gql_request(query, variables=variables) + commit = data["owner"]["repository"]["commit"] + + assert commit["bundleAnalysisReport"] == { + "__typename": "BundleAnalysisReport", + "bundle": { + "measurements": [ + { + "assetType": "ASSET_SIZE", + "change": None, + "measurements": [], + "name": "asset-*.js", + "size": None, + }, + { + "assetType": "ASSET_SIZE", + "change": None, + "measurements": [], + "name": "asset-*.js", + "size": None, + }, + { + "assetType": "ASSET_SIZE", + "change": None, + "measurements": [], + "name": "asset-*.js", + "size": None, + }, + { + "assetType": "FONT_SIZE", + "change": None, + "measurements": [], + "name": None, + "size": None, + }, + { + "assetType": "IMAGE_SIZE", + "change": { + "loadTime": { + "highSpeed": 0, + "threeG": -2, + }, + "size": { + "gzip": 0, + "uncompress": -210, + }, + }, + "measurements": [ + { + "avg": 666.0, + "max": 666.0, + "min": 666.0, + "timestamp": "2024-06-05T00:00:00+00:00", + }, + { + "avg": 456.0, + "max": 456.0, + "min": 456.0, + "timestamp": "2024-06-06T00:00:00+00:00", + }, + { + "avg": None, + "max": None, + "min": None, + "timestamp": "2024-06-07T00:00:00+00:00", + }, + { + "avg": None, + "max": None, + "min": None, + "timestamp": "2024-06-08T00:00:00+00:00", + }, + { + "avg": None, + "max": None, + "min": None, + "timestamp": "2024-06-09T00:00:00+00:00", + }, + { + "avg": None, + "max": None, + "min": None, + "timestamp": "2024-06-10T00:00:00+00:00", + }, + ], + "name": None, + "size": { + "loadTime": { + "highSpeed": 0, + "threeG": 4, + }, + "size": { + "gzip": 0, + "uncompress": 456, + }, + }, + }, + { + "assetType": "JAVASCRIPT_SIZE", + "change": None, + "measurements": [], + "name": None, + "size": None, + }, + { + "assetType": "REPORT_SIZE", + "change": None, + "measurements": [ + { + "avg": 123.0, + "max": 123.0, + "min": 123.0, + "timestamp": "2024-06-10T00:00:00+00:00", + }, + ], + "name": None, + "size": { + "loadTime": { + "highSpeed": 0, + "threeG": 1, + }, + "size": { + "gzip": 0, + "uncompress": 123, + }, + }, + }, + { + "assetType": "STYLESHEET_SIZE", + "change": None, + "measurements": [], + "name": None, + "size": None, + }, + { + "assetType": "UNKNOWN_SIZE", + "change": None, + "measurements": [], + "name": None, + "size": None, + }, ], + "name": "super", }, } diff --git a/graphql_api/tests/test_bundle_analysis_measurements_legacy.py b/graphql_api/tests/test_bundle_analysis_measurements_legacy.py index e12e0a63f1..10c57a5eb5 100644 --- a/graphql_api/tests/test_bundle_analysis_measurements_legacy.py +++ b/graphql_api/tests/test_bundle_analysis_measurements_legacy.py @@ -579,6 +579,62 @@ def test_bundle_report_measurements(self, get_storage_service): }, }, }, + { + "assetType": "UNKNOWN_SIZE", + "change": { + "loadTime": { + "highSpeed": 0, + "threeG": 0, + }, + "size": { + "gzip": 0, + "uncompress": 0, + }, + }, + "measurements": [ + { + "avg": 0.0, + "max": 0.0, + "min": 0.0, + "timestamp": "2024-06-06T00:00:00+00:00", + }, + { + "avg": None, + "max": None, + "min": None, + "timestamp": "2024-06-07T00:00:00+00:00", + }, + { + "avg": None, + "max": None, + "min": None, + "timestamp": "2024-06-08T00:00:00+00:00", + }, + { + "avg": None, + "max": None, + "min": None, + "timestamp": "2024-06-09T00:00:00+00:00", + }, + { + "avg": 0.0, + "max": 0.0, + "min": 0.0, + "timestamp": "2024-06-10T00:00:00+00:00", + }, + ], + "name": None, + "size": { + "loadTime": { + "highSpeed": 0, + "threeG": 0, + }, + "size": { + "gzip": 0, + "uncompress": 0, + }, + }, + }, ], "name": "super", }, @@ -1294,6 +1350,56 @@ def test_bundle_report_measurements_carryovers(self, get_storage_service): }, }, }, + { + "assetType": "UNKNOWN_SIZE", + "change": { + "loadTime": { + "highSpeed": 0, + "threeG": 0, + }, + "size": { + "gzip": 0, + "uncompress": 0, + }, + }, + "measurements": [ + { + "avg": 0.0, + "max": 0.0, + "min": 0.0, + "timestamp": "2024-06-07T00:00:00+00:00", + }, + { + "avg": None, + "max": None, + "min": None, + "timestamp": "2024-06-08T00:00:00+00:00", + }, + { + "avg": None, + "max": None, + "min": None, + "timestamp": "2024-06-09T00:00:00+00:00", + }, + { + "avg": 0.0, + "max": 0.0, + "min": 0.0, + "timestamp": "2024-06-10T00:00:00+00:00", + }, + ], + "name": None, + "size": { + "loadTime": { + "highSpeed": 0, + "threeG": 0, + }, + "size": { + "gzip": 0, + "uncompress": 0, + }, + }, + }, ], "name": "super", }, @@ -1909,6 +2015,68 @@ def test_bundle_report_no_carryovers(self, get_storage_service): }, }, }, + { + "assetType": "UNKNOWN_SIZE", + "change": { + "loadTime": { + "highSpeed": 0, + "threeG": 0, + }, + "size": { + "gzip": 0, + "uncompress": 0, + }, + }, + "measurements": [ + { + "avg": None, + "max": None, + "min": None, + "timestamp": "2024-06-05T00:00:00+00:00", + }, + { + "avg": 0.0, + "max": 0.0, + "min": 0.0, + "timestamp": "2024-06-06T00:00:00+00:00", + }, + { + "avg": None, + "max": None, + "min": None, + "timestamp": "2024-06-07T00:00:00+00:00", + }, + { + "avg": None, + "max": None, + "min": None, + "timestamp": "2024-06-08T00:00:00+00:00", + }, + { + "avg": None, + "max": None, + "min": None, + "timestamp": "2024-06-09T00:00:00+00:00", + }, + { + "avg": 0.0, + "max": 0.0, + "min": 0.0, + "timestamp": "2024-06-10T00:00:00+00:00", + }, + ], + "name": None, + "size": { + "loadTime": { + "highSpeed": 0, + "threeG": 0, + }, + "size": { + "gzip": 0, + "uncompress": 0, + }, + }, + }, ], "name": "super", }, @@ -2204,6 +2372,56 @@ def test_bundle_report_branch(self, get_storage_service): "change": None, "measurements": [], }, + { + "assetType": "UNKNOWN_SIZE", + "change": { + "loadTime": { + "highSpeed": 0, + "threeG": -3, + }, + "size": { + "gzip": 0, + "uncompress": -333, + }, + }, + "measurements": [ + { + "avg": 456.0, + "max": 456.0, + "min": 456.0, + "timestamp": "2024-06-07T00:00:00+00:00", + }, + { + "avg": None, + "max": None, + "min": None, + "timestamp": "2024-06-08T00:00:00+00:00", + }, + { + "avg": None, + "max": None, + "min": None, + "timestamp": "2024-06-09T00:00:00+00:00", + }, + { + "avg": 123.0, + "max": 123.0, + "min": 123.0, + "timestamp": "2024-06-10T00:00:00+00:00", + }, + ], + "name": None, + "size": { + "loadTime": { + "highSpeed": 0, + "threeG": 1, + }, + "size": { + "gzip": 0, + "uncompress": 123, + }, + }, + }, ], }, } @@ -2419,6 +2637,62 @@ def test_bundle_report_no_after(self, get_storage_service): "change": None, "measurements": [], }, + { + "assetType": "UNKNOWN_SIZE", + "change": { + "loadTime": { + "highSpeed": 0, + "threeG": -3, + }, + "size": { + "gzip": 0, + "uncompress": -333, + }, + }, + "measurements": [ + { + "avg": 456.0, + "max": 456.0, + "min": 456.0, + "timestamp": "2024-06-06T00:00:00+00:00", + }, + { + "avg": None, + "max": None, + "min": None, + "timestamp": "2024-06-07T00:00:00+00:00", + }, + { + "avg": None, + "max": None, + "min": None, + "timestamp": "2024-06-08T00:00:00+00:00", + }, + { + "avg": None, + "max": None, + "min": None, + "timestamp": "2024-06-09T00:00:00+00:00", + }, + { + "avg": 123.0, + "max": 123.0, + "min": 123.0, + "timestamp": "2024-06-10T00:00:00+00:00", + }, + ], + "name": None, + "size": { + "loadTime": { + "highSpeed": 0, + "threeG": 1, + }, + "size": { + "gzip": 0, + "uncompress": 123, + }, + }, + }, ], }, } diff --git a/graphql_api/types/bundle_analysis/base.graphql b/graphql_api/types/bundle_analysis/base.graphql index dc899c3225..f9785f1214 100644 --- a/graphql_api/types/bundle_analysis/base.graphql +++ b/graphql_api/types/bundle_analysis/base.graphql @@ -5,6 +5,7 @@ enum BundleAnalysisMeasurementsAssetType { FONT_SIZE IMAGE_SIZE ASSET_SIZE + UNKNOWN_SIZE } enum BundleReportGroups { diff --git a/graphql_api/types/bundle_analysis/base.py b/graphql_api/types/bundle_analysis/base.py index c5ed5380f0..a5c550f9b8 100644 --- a/graphql_api/types/bundle_analysis/base.py +++ b/graphql_api/types/bundle_analysis/base.py @@ -1,3 +1,4 @@ +from copy import deepcopy from datetime import datetime from typing import Dict, List, Mapping, Optional, Union @@ -20,6 +21,8 @@ ) from timeseries.models import Interval +ASSET_TYPE_UNKNOWN = "UNKNOWN_SIZE" + bundle_data_bindable = ObjectType("BundleData") bundle_module_bindable = ObjectType("BundleModule") bundle_asset_bindable = ObjectType("BundleAsset") @@ -36,6 +39,35 @@ def _find_index_by_cursor(assets: List, cursor: str) -> int: return -1 +def _compute_unknown_asset_size_raw_measurements(fetched_data: dict) -> List[dict]: + """ + Computes measurements for the unknown asset types, some asset types are not in + the predetermined list of types so we must compute those measurements manually. + The heuristic will be to get the measurements of the bundle type (ie total bundle size) + then substract it from all the known asset type measurements, leaving with only the unknown. + """ + unknown_raw_measurements = deepcopy( + fetched_data[BundleAnalysisMeasurementsAssetType.REPORT_SIZE][ + 0 + ].raw_measurements + ) + + for name, measurements in fetched_data.items(): + if name not in ( + BundleAnalysisMeasurementsAssetType.REPORT_SIZE, + BundleAnalysisMeasurementsAssetType.ASSET_SIZE, + ): + raw_measurements = measurements[0].raw_measurements + for i in range(len(raw_measurements)): + if len(unknown_raw_measurements) != len(raw_measurements): + return [] + unknown_raw_measurements[i]["min"] -= raw_measurements[i]["min"] + unknown_raw_measurements[i]["max"] -= raw_measurements[i]["max"] + unknown_raw_measurements[i]["avg"] -= raw_measurements[i]["avg"] + + return unknown_raw_measurements + + # ============= Bundle Data Bindable ============= @@ -234,7 +266,6 @@ def resolve_bundle_report_filtered( filters: dict[str, list[str]] = {}, ) -> BundleData: group = filters.get("report_group") - return BundleData( bundle_report.report.total_size(asset_types=[group] if group else None), bundle_report.report.total_gzip_size(asset_types=[group] if group else None), @@ -254,13 +285,7 @@ def resolve_bundle_report_measurements( filters: Mapping = {}, ordering_direction: Optional[OrderingDirection] = OrderingDirection.ASC, ) -> List[BundleAnalysisMeasurementData]: - if not filters.get("asset_types", []): - measurable_names = [item for item in list(BundleAnalysisMeasurementsAssetType)] - else: - measurable_names = [ - BundleAnalysisMeasurementsAssetType[item] for item in filters["asset_types"] - ] - + asset_types = list(filters.get("asset_types", [])) bundle_analysis_measurements = BundleAnalysisMeasurementsService( repository=info.context["commit"].repository, interval=interval, @@ -269,10 +294,53 @@ def resolve_bundle_report_measurements( branch=branch, ) + # All measureable names we need to fetch to compute the requested asset types + if not asset_types or ASSET_TYPE_UNKNOWN in asset_types: + measurables_to_fetch = [ + item for item in list(BundleAnalysisMeasurementsAssetType) + ] + else: + measurables_to_fetch = [ + BundleAnalysisMeasurementsAssetType[item] for item in asset_types + ] + + # Retrieve all the measurements necessary to compute the requested asset types + fetched_data = {} + for name in measurables_to_fetch: + fetched_data[name] = bundle_analysis_measurements.compute_report( + bundle_report, asset_type=name + ) + + # All measureable name we need to return + if not asset_types: + measurables_to_display = [ + item for item in list(BundleAnalysisMeasurementsAssetType) + ] + else: + measurables_to_display = [ + BundleAnalysisMeasurementsAssetType[item] + for item in asset_types + if item != ASSET_TYPE_UNKNOWN + ] + measurements = [] - for name in measurable_names: - measurements.extend( - bundle_analysis_measurements.compute_report(bundle_report, asset_type=name) + for measurable in measurables_to_display: + measurements.extend(fetched_data[measurable]) + + # Compute for unknown asset type size if necessary + if not asset_types or ASSET_TYPE_UNKNOWN in asset_types: + unknown_size_raw_measurements = _compute_unknown_asset_size_raw_measurements( + fetched_data + ) + measurements.append( + BundleAnalysisMeasurementData( + raw_measurements=unknown_size_raw_measurements, + asset_type=ASSET_TYPE_UNKNOWN, + asset_name=None, + interval=interval, + after=after, + before=before, + ) ) return sorted( diff --git a/services/bundle_analysis.py b/services/bundle_analysis.py index 032f06dc3e..b212ccf92e 100644 --- a/services/bundle_analysis.py +++ b/services/bundle_analysis.py @@ -3,7 +3,7 @@ from dataclasses import dataclass from datetime import datetime from decimal import Decimal -from typing import Any, Dict, Iterable, List, Optional +from typing import Any, Dict, Iterable, List, Optional, Union from django.utils.functional import cached_property from shared.bundle_analysis import AssetReport as SharedAssetReport @@ -81,7 +81,7 @@ class BundleAnalysisMeasurementData(object): def __init__( self, raw_measurements: List[dict], - asset_type: BundleAnalysisMeasurementsAssetType, + asset_type: Union[BundleAnalysisMeasurementsAssetType, str], asset_name: Optional[str], interval: Interval, after: Optional[datetime], @@ -96,6 +96,8 @@ def __init__( @cached_property def asset_type(self) -> str: + if isinstance(self.measurement_type, str): + return self.measurement_type return self.measurement_type.name @cached_property