Skip to content
This repository was archived by the owner on Jun 13, 2025. It is now read-only.

Commit b80e386

Browse files
authored
bundle analysis: sentry->prometheus metrics for upload view (#899)
1 parent 15f9614 commit b80e386

File tree

2 files changed

+142
-19
lines changed

2 files changed

+142
-19
lines changed

upload/tests/views/test_bundle_analysis.py

Lines changed: 118 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@
1818
@pytest.mark.django_db(databases={"default", "timeseries"})
1919
def test_upload_bundle_analysis_success(db, client, mocker, mock_redis):
2020
upload = mocker.patch.object(TaskService, "upload")
21-
mock_sentry_metrics = mocker.patch(
22-
"upload.views.bundle_analysis.sentry_metrics.incr"
21+
mock_metrics = mocker.patch(
22+
"upload.views.bundle_analysis.BUNDLE_ANALYSIS_UPLOAD_VIEWS_COUNTER.labels"
2323
)
2424
create_presigned_put = mocker.patch(
2525
"services.archive.StorageService.create_presigned_put",
@@ -89,9 +89,8 @@ def test_upload_bundle_analysis_success(db, client, mocker, mock_redis):
8989
report_code=None,
9090
report_type="bundle_analysis",
9191
)
92-
mock_sentry_metrics.assert_called_with(
93-
"upload",
94-
tags={
92+
mock_metrics.assert_called_with(
93+
**{
9594
"agent": "cli",
9695
"version": "0.4.7",
9796
"action": "bundle_analysis",
@@ -201,6 +200,9 @@ def test_upload_bundle_analysis_org_token(db, client, mocker, mock_redis):
201200
"services.archive.StorageService.create_presigned_put",
202201
return_value="test-presigned-put",
203202
)
203+
mock_metrics = mocker.patch(
204+
"upload.views.bundle_analysis.BUNDLE_ANALYSIS_UPLOAD_VIEWS_COUNTER.labels"
205+
)
204206

205207
repository = RepositoryFactory.create()
206208
org_token = OrganizationLevelTokenFactory.create(owner=repository.author)
@@ -217,6 +219,17 @@ def test_upload_bundle_analysis_org_token(db, client, mocker, mock_redis):
217219
format="json",
218220
)
219221
assert res.status_code == 201
222+
mock_metrics.assert_called_with(
223+
**{
224+
"agent": "unknown-user-agent",
225+
"version": "unknown-user-agent",
226+
"action": "bundle_analysis",
227+
"endpoint": "bundle_analysis",
228+
"repo_visibility": "private",
229+
"is_using_shelter": "no",
230+
"position": "end",
231+
},
232+
)
220233

221234

222235
@pytest.mark.django_db(databases={"default", "timeseries"})
@@ -226,6 +239,9 @@ def test_upload_bundle_analysis_existing_commit(db, client, mocker, mock_redis):
226239
"services.archive.StorageService.create_presigned_put",
227240
return_value="test-presigned-put",
228241
)
242+
mock_metrics = mocker.patch(
243+
"upload.views.bundle_analysis.BUNDLE_ANALYSIS_UPLOAD_VIEWS_COUNTER.labels"
244+
)
229245

230246
repository = RepositoryFactory.create()
231247
commit = CommitFactory.create(repository=repository)
@@ -250,6 +266,17 @@ def test_upload_bundle_analysis_existing_commit(db, client, mocker, mock_redis):
250266
report_code=None,
251267
report_type="bundle_analysis",
252268
)
269+
mock_metrics.assert_called_with(
270+
**{
271+
"agent": "unknown-user-agent",
272+
"version": "unknown-user-agent",
273+
"action": "bundle_analysis",
274+
"endpoint": "bundle_analysis",
275+
"repo_visibility": "private",
276+
"is_using_shelter": "no",
277+
"position": "end",
278+
},
279+
)
253280

254281

255282
def test_upload_bundle_analysis_missing_args(db, client, mocker, mock_redis):
@@ -258,6 +285,9 @@ def test_upload_bundle_analysis_missing_args(db, client, mocker, mock_redis):
258285
"services.archive.StorageService.create_presigned_put",
259286
return_value="test-presigned-put",
260287
)
288+
mock_metrics = mocker.patch(
289+
"upload.views.bundle_analysis.BUNDLE_ANALYSIS_UPLOAD_VIEWS_COUNTER.labels"
290+
)
261291

262292
repository = RepositoryFactory.create()
263293
commit = CommitFactory.create(repository=repository)
@@ -286,6 +316,16 @@ def test_upload_bundle_analysis_missing_args(db, client, mocker, mock_redis):
286316
assert res.status_code == 400
287317
assert res.json() == {"commit": ["This field is required."]}
288318
assert not upload.called
319+
mock_metrics.assert_called_with(
320+
**{
321+
"agent": "unknown-user-agent",
322+
"version": "unknown-user-agent",
323+
"action": "bundle_analysis",
324+
"endpoint": "bundle_analysis",
325+
"is_using_shelter": "no",
326+
"position": "start",
327+
},
328+
)
289329

290330

291331
def test_upload_bundle_analysis_invalid_token(db, client, mocker, mock_redis):
@@ -324,6 +364,9 @@ def test_upload_bundle_analysis_github_oidc_auth(
324364
"services.archive.StorageService.create_presigned_put",
325365
return_value="test-presigned-put",
326366
)
367+
mock_metrics = mocker.patch(
368+
"upload.views.bundle_analysis.BUNDLE_ANALYSIS_UPLOAD_VIEWS_COUNTER.labels"
369+
)
327370
repository = RepositoryFactory()
328371
mock_jwt_decode.return_value = {
329372
"repository": f"url/{repository.name}",
@@ -344,18 +387,31 @@ def test_upload_bundle_analysis_github_oidc_auth(
344387
format="json",
345388
)
346389
assert res.status_code == 201
390+
mock_metrics.assert_called_with(
391+
**{
392+
"agent": "unknown-user-agent",
393+
"version": "unknown-user-agent",
394+
"action": "bundle_analysis",
395+
"endpoint": "bundle_analysis",
396+
"repo_visibility": "private",
397+
"is_using_shelter": "no",
398+
"position": "end",
399+
},
400+
)
347401

348402

349403
@pytest.mark.django_db(databases={"default", "timeseries"})
350404
def test_upload_bundle_analysis_measurement_datasets_created(
351405
db, client, mocker, mock_redis
352406
):
353407
mocker.patch.object(TaskService, "upload")
354-
mocker.patch("upload.views.bundle_analysis.sentry_metrics.incr")
355408
mocker.patch(
356409
"services.archive.StorageService.create_presigned_put",
357410
return_value="test-presigned-put",
358411
)
412+
mock_metrics = mocker.patch(
413+
"upload.views.bundle_analysis.BUNDLE_ANALYSIS_UPLOAD_VIEWS_COUNTER.labels"
414+
)
359415

360416
repository = RepositoryFactory.create()
361417
commit_sha = "6fd5b89357fc8cdf34d6197549ac7c6d7e5977ef"
@@ -392,18 +448,32 @@ def test_upload_bundle_analysis_measurement_datasets_created(
392448
repository_id=repository.pk,
393449
).exists()
394450

451+
mock_metrics.assert_called_with(
452+
**{
453+
"agent": "cli",
454+
"version": "0.4.7",
455+
"action": "bundle_analysis",
456+
"endpoint": "bundle_analysis",
457+
"repo_visibility": "private",
458+
"is_using_shelter": "no",
459+
"position": "end",
460+
},
461+
)
462+
395463

396464
@override_settings(TIMESERIES_ENABLED=False)
397465
@pytest.mark.django_db(databases={"default", "timeseries"})
398466
def test_upload_bundle_analysis_measurement_timeseries_disabled(
399467
db, client, mocker, mock_redis
400468
):
401469
mocker.patch.object(TaskService, "upload")
402-
mocker.patch("upload.views.bundle_analysis.sentry_metrics.incr")
403470
mocker.patch(
404471
"services.archive.StorageService.create_presigned_put",
405472
return_value="test-presigned-put",
406473
)
474+
mock_metrics = mocker.patch(
475+
"upload.views.bundle_analysis.BUNDLE_ANALYSIS_UPLOAD_VIEWS_COUNTER.labels"
476+
)
407477

408478
repository = RepositoryFactory.create()
409479
commit_sha = "6fd5b89357fc8cdf34d6197549ac7c6d7e5977ef"
@@ -440,6 +510,18 @@ def test_upload_bundle_analysis_measurement_timeseries_disabled(
440510
repository_id=repository.pk,
441511
).exists()
442512

513+
mock_metrics.assert_called_with(
514+
**{
515+
"agent": "cli",
516+
"version": "0.4.7",
517+
"action": "bundle_analysis",
518+
"endpoint": "bundle_analysis",
519+
"repo_visibility": "private",
520+
"is_using_shelter": "no",
521+
"position": "end",
522+
},
523+
)
524+
443525

444526
@pytest.mark.django_db(databases={"default", "timeseries"})
445527
def test_upload_bundle_analysis_no_repo(db, client, mocker, mock_redis):
@@ -449,6 +531,9 @@ def test_upload_bundle_analysis_no_repo(db, client, mocker, mock_redis):
449531
"services.archive.StorageService.create_presigned_put",
450532
return_value="test-presigned-put",
451533
)
534+
mock_metrics = mocker.patch(
535+
"upload.views.bundle_analysis.BUNDLE_ANALYSIS_UPLOAD_VIEWS_COUNTER.labels"
536+
)
452537

453538
repository = RepositoryFactory.create()
454539
org_token = OrganizationLevelTokenFactory.create(owner=repository.author)
@@ -468,10 +553,24 @@ def test_upload_bundle_analysis_no_repo(db, client, mocker, mock_redis):
468553
assert res.json() == {"detail": "Repository not found."}
469554
assert not upload.called
470555

556+
mock_metrics.assert_called_with(
557+
**{
558+
"agent": "unknown-user-agent",
559+
"version": "unknown-user-agent",
560+
"action": "bundle_analysis",
561+
"endpoint": "bundle_analysis",
562+
"is_using_shelter": "no",
563+
"position": "start",
564+
},
565+
)
566+
471567

472568
@pytest.mark.django_db(databases={"default", "timeseries"})
473569
def test_upload_bundle_analysis_tokenless_success(db, client, mocker, mock_redis):
474570
upload = mocker.patch.object(TaskService, "upload")
571+
mock_metrics = mocker.patch(
572+
"upload.views.bundle_analysis.BUNDLE_ANALYSIS_UPLOAD_VIEWS_COUNTER.labels"
573+
)
475574

476575
create_presigned_put = mocker.patch(
477576
"services.archive.StorageService.create_presigned_put",
@@ -508,6 +607,18 @@ def test_upload_bundle_analysis_tokenless_success(db, client, mocker, mock_redis
508607
assert upload.called
509608
create_presigned_put.assert_called_once_with("bundle-analysis", ANY, 30)
510609

610+
mock_metrics.assert_called_with(
611+
**{
612+
"agent": "cli",
613+
"version": "0.4.7",
614+
"action": "bundle_analysis",
615+
"endpoint": "bundle_analysis",
616+
"repo_visibility": "public",
617+
"is_using_shelter": "no",
618+
"position": "end",
619+
},
620+
)
621+
511622

512623
@pytest.mark.django_db(databases={"default", "timeseries"})
513624
def test_upload_bundle_analysis_tokenless_no_repo(db, client, mocker, mock_redis):

upload/views/bundle_analysis.py

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@
99
from rest_framework.permissions import BasePermission
1010
from rest_framework.response import Response
1111
from rest_framework.views import APIView
12-
from sentry_sdk import metrics as sentry_metrics
1312
from shared.bundle_analysis.storage import StoragePaths, get_bucket_name
13+
from shared.metrics import Counter
1414

1515
from codecov_auth.authentication.repo_auth import (
1616
BundleAnalysisTokenlessAuthentication,
@@ -33,6 +33,21 @@
3333
log = logging.getLogger(__name__)
3434

3535

36+
BUNDLE_ANALYSIS_UPLOAD_VIEWS_COUNTER = Counter(
37+
"bundle_analysis_upload_views_runs",
38+
"Number of times a raw report processor was run and with what result",
39+
[
40+
"agent",
41+
"version",
42+
"action",
43+
"endpoint",
44+
"is_using_shelter",
45+
"repo_visibility",
46+
"position",
47+
],
48+
)
49+
50+
3651
class UploadBundleAnalysisPermission(BasePermission):
3752
def has_permission(self, request: HttpRequest, view: Any) -> bool:
3853
return request.auth is not None and "upload" in request.auth.get_scopes()
@@ -66,16 +81,15 @@ def get_exception_handler(self) -> Callable:
6681
return repo_auth_custom_exception_handler
6782

6883
def post(self, request: HttpRequest) -> Response:
69-
sentry_metrics.incr(
70-
"upload",
71-
tags=generate_upload_sentry_metrics_tags(
84+
BUNDLE_ANALYSIS_UPLOAD_VIEWS_COUNTER.labels(
85+
**generate_upload_sentry_metrics_tags(
7286
action="bundle_analysis",
7387
endpoint="bundle_analysis",
7488
request=self.request,
7589
is_shelter_request=self.is_shelter_request(),
7690
position="start",
77-
),
78-
)
91+
)
92+
).inc()
7993
serializer = UploadSerializer(data=request.data)
8094
if not serializer.is_valid():
8195
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
@@ -154,18 +168,16 @@ def post(self, request: HttpRequest) -> Response:
154168
task_arguments=task_arguments,
155169
),
156170
)
157-
158-
sentry_metrics.incr(
159-
"upload",
160-
tags=generate_upload_sentry_metrics_tags(
171+
BUNDLE_ANALYSIS_UPLOAD_VIEWS_COUNTER.labels(
172+
**generate_upload_sentry_metrics_tags(
161173
action="bundle_analysis",
162174
endpoint="bundle_analysis",
163175
request=self.request,
164176
repository=repo,
165177
is_shelter_request=self.is_shelter_request(),
166178
position="end",
167-
),
168-
)
179+
)
180+
).inc()
169181

170182
dispatch_upload_task(
171183
task_arguments,

0 commit comments

Comments
 (0)