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

Commit d8de0bb

Browse files
committed
bundle analysis: sentry->prometheus metrics for upload view
1 parent 3b84808 commit d8de0bb

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",
@@ -110,6 +109,9 @@ def test_upload_bundle_analysis_org_token(db, client, mocker, mock_redis):
110109
"services.archive.StorageService.create_presigned_put",
111110
return_value="test-presigned-put",
112111
)
112+
mock_metrics = mocker.patch(
113+
"upload.views.bundle_analysis.BUNDLE_ANALYSIS_UPLOAD_VIEWS_COUNTER.labels"
114+
)
113115

114116
repository = RepositoryFactory.create()
115117
org_token = OrganizationLevelTokenFactory.create(owner=repository.author)
@@ -126,6 +128,17 @@ def test_upload_bundle_analysis_org_token(db, client, mocker, mock_redis):
126128
format="json",
127129
)
128130
assert res.status_code == 201
131+
mock_metrics.assert_called_with(
132+
**{
133+
"agent": "unknown-user-agent",
134+
"version": "unknown-user-agent",
135+
"action": "bundle_analysis",
136+
"endpoint": "bundle_analysis",
137+
"repo_visibility": "private",
138+
"is_using_shelter": "no",
139+
"position": "end",
140+
},
141+
)
129142

130143

131144
@pytest.mark.django_db(databases={"default", "timeseries"})
@@ -135,6 +148,9 @@ def test_upload_bundle_analysis_existing_commit(db, client, mocker, mock_redis):
135148
"services.archive.StorageService.create_presigned_put",
136149
return_value="test-presigned-put",
137150
)
151+
mock_metrics = mocker.patch(
152+
"upload.views.bundle_analysis.BUNDLE_ANALYSIS_UPLOAD_VIEWS_COUNTER.labels"
153+
)
138154

139155
repository = RepositoryFactory.create()
140156
commit = CommitFactory.create(repository=repository)
@@ -159,6 +175,17 @@ def test_upload_bundle_analysis_existing_commit(db, client, mocker, mock_redis):
159175
report_code=None,
160176
report_type="bundle_analysis",
161177
)
178+
mock_metrics.assert_called_with(
179+
**{
180+
"agent": "unknown-user-agent",
181+
"version": "unknown-user-agent",
182+
"action": "bundle_analysis",
183+
"endpoint": "bundle_analysis",
184+
"repo_visibility": "private",
185+
"is_using_shelter": "no",
186+
"position": "end",
187+
},
188+
)
162189

163190

164191
def test_upload_bundle_analysis_missing_args(db, client, mocker, mock_redis):
@@ -167,6 +194,9 @@ def test_upload_bundle_analysis_missing_args(db, client, mocker, mock_redis):
167194
"services.archive.StorageService.create_presigned_put",
168195
return_value="test-presigned-put",
169196
)
197+
mock_metrics = mocker.patch(
198+
"upload.views.bundle_analysis.BUNDLE_ANALYSIS_UPLOAD_VIEWS_COUNTER.labels"
199+
)
170200

171201
repository = RepositoryFactory.create()
172202
commit = CommitFactory.create(repository=repository)
@@ -195,6 +225,16 @@ def test_upload_bundle_analysis_missing_args(db, client, mocker, mock_redis):
195225
assert res.status_code == 400
196226
assert res.json() == {"commit": ["This field is required."]}
197227
assert not upload.called
228+
mock_metrics.assert_called_with(
229+
**{
230+
"agent": "unknown-user-agent",
231+
"version": "unknown-user-agent",
232+
"action": "bundle_analysis",
233+
"endpoint": "bundle_analysis",
234+
"is_using_shelter": "no",
235+
"position": "start",
236+
},
237+
)
198238

199239

200240
def test_upload_bundle_analysis_invalid_token(db, client, mocker, mock_redis):
@@ -233,6 +273,9 @@ def test_upload_bundle_analysis_github_oidc_auth(
233273
"services.archive.StorageService.create_presigned_put",
234274
return_value="test-presigned-put",
235275
)
276+
mock_metrics = mocker.patch(
277+
"upload.views.bundle_analysis.BUNDLE_ANALYSIS_UPLOAD_VIEWS_COUNTER.labels"
278+
)
236279
repository = RepositoryFactory()
237280
mock_jwt_decode.return_value = {
238281
"repository": f"url/{repository.name}",
@@ -253,18 +296,31 @@ def test_upload_bundle_analysis_github_oidc_auth(
253296
format="json",
254297
)
255298
assert res.status_code == 201
299+
mock_metrics.assert_called_with(
300+
**{
301+
"agent": "unknown-user-agent",
302+
"version": "unknown-user-agent",
303+
"action": "bundle_analysis",
304+
"endpoint": "bundle_analysis",
305+
"repo_visibility": "private",
306+
"is_using_shelter": "no",
307+
"position": "end",
308+
},
309+
)
256310

257311

258312
@pytest.mark.django_db(databases={"default", "timeseries"})
259313
def test_upload_bundle_analysis_measurement_datasets_created(
260314
db, client, mocker, mock_redis
261315
):
262316
mocker.patch.object(TaskService, "upload")
263-
mocker.patch("upload.views.bundle_analysis.sentry_metrics.incr")
264317
mocker.patch(
265318
"services.archive.StorageService.create_presigned_put",
266319
return_value="test-presigned-put",
267320
)
321+
mock_metrics = mocker.patch(
322+
"upload.views.bundle_analysis.BUNDLE_ANALYSIS_UPLOAD_VIEWS_COUNTER.labels"
323+
)
268324

269325
repository = RepositoryFactory.create()
270326
commit_sha = "6fd5b89357fc8cdf34d6197549ac7c6d7e5977ef"
@@ -301,18 +357,32 @@ def test_upload_bundle_analysis_measurement_datasets_created(
301357
repository_id=repository.pk,
302358
).exists()
303359

360+
mock_metrics.assert_called_with(
361+
**{
362+
"agent": "cli",
363+
"version": "0.4.7",
364+
"action": "bundle_analysis",
365+
"endpoint": "bundle_analysis",
366+
"repo_visibility": "private",
367+
"is_using_shelter": "no",
368+
"position": "end",
369+
},
370+
)
371+
304372

305373
@override_settings(TIMESERIES_ENABLED=False)
306374
@pytest.mark.django_db(databases={"default", "timeseries"})
307375
def test_upload_bundle_analysis_measurement_timeseries_disabled(
308376
db, client, mocker, mock_redis
309377
):
310378
mocker.patch.object(TaskService, "upload")
311-
mocker.patch("upload.views.bundle_analysis.sentry_metrics.incr")
312379
mocker.patch(
313380
"services.archive.StorageService.create_presigned_put",
314381
return_value="test-presigned-put",
315382
)
383+
mock_metrics = mocker.patch(
384+
"upload.views.bundle_analysis.BUNDLE_ANALYSIS_UPLOAD_VIEWS_COUNTER.labels"
385+
)
316386

317387
repository = RepositoryFactory.create()
318388
commit_sha = "6fd5b89357fc8cdf34d6197549ac7c6d7e5977ef"
@@ -349,6 +419,18 @@ def test_upload_bundle_analysis_measurement_timeseries_disabled(
349419
repository_id=repository.pk,
350420
).exists()
351421

422+
mock_metrics.assert_called_with(
423+
**{
424+
"agent": "cli",
425+
"version": "0.4.7",
426+
"action": "bundle_analysis",
427+
"endpoint": "bundle_analysis",
428+
"repo_visibility": "private",
429+
"is_using_shelter": "no",
430+
"position": "end",
431+
},
432+
)
433+
352434

353435
@pytest.mark.django_db(databases={"default", "timeseries"})
354436
def test_upload_bundle_analysis_no_repo(db, client, mocker, mock_redis):
@@ -358,6 +440,9 @@ def test_upload_bundle_analysis_no_repo(db, client, mocker, mock_redis):
358440
"services.archive.StorageService.create_presigned_put",
359441
return_value="test-presigned-put",
360442
)
443+
mock_metrics = mocker.patch(
444+
"upload.views.bundle_analysis.BUNDLE_ANALYSIS_UPLOAD_VIEWS_COUNTER.labels"
445+
)
361446

362447
repository = RepositoryFactory.create()
363448
org_token = OrganizationLevelTokenFactory.create(owner=repository.author)
@@ -377,10 +462,24 @@ def test_upload_bundle_analysis_no_repo(db, client, mocker, mock_redis):
377462
assert res.json() == {"detail": "Repository not found."}
378463
assert not upload.called
379464

465+
mock_metrics.assert_called_with(
466+
**{
467+
"agent": "unknown-user-agent",
468+
"version": "unknown-user-agent",
469+
"action": "bundle_analysis",
470+
"endpoint": "bundle_analysis",
471+
"is_using_shelter": "no",
472+
"position": "start",
473+
},
474+
)
475+
380476

381477
@pytest.mark.django_db(databases={"default", "timeseries"})
382478
def test_upload_bundle_analysis_tokenless_success(db, client, mocker, mock_redis):
383479
upload = mocker.patch.object(TaskService, "upload")
480+
mock_metrics = mocker.patch(
481+
"upload.views.bundle_analysis.BUNDLE_ANALYSIS_UPLOAD_VIEWS_COUNTER.labels"
482+
)
384483

385484
create_presigned_put = mocker.patch(
386485
"services.archive.StorageService.create_presigned_put",
@@ -417,6 +516,18 @@ def test_upload_bundle_analysis_tokenless_success(db, client, mocker, mock_redis
417516
assert upload.called
418517
create_presigned_put.assert_called_once_with("bundle-analysis", ANY, 30)
419518

519+
mock_metrics.assert_called_with(
520+
**{
521+
"agent": "cli",
522+
"version": "0.4.7",
523+
"action": "bundle_analysis",
524+
"endpoint": "bundle_analysis",
525+
"repo_visibility": "public",
526+
"is_using_shelter": "no",
527+
"position": "end",
528+
},
529+
)
530+
420531

421532
@pytest.mark.django_db(databases={"default", "timeseries"})
422533
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()
@@ -64,16 +79,15 @@ def get_exception_handler(self) -> Callable:
6479
return repo_auth_custom_exception_handler
6580

6681
def post(self, request: HttpRequest) -> Response:
67-
sentry_metrics.incr(
68-
"upload",
69-
tags=generate_upload_sentry_metrics_tags(
82+
BUNDLE_ANALYSIS_UPLOAD_VIEWS_COUNTER.labels(
83+
**generate_upload_sentry_metrics_tags(
7084
action="bundle_analysis",
7185
endpoint="bundle_analysis",
7286
request=self.request,
7387
is_shelter_request=self.is_shelter_request(),
7488
position="start",
75-
),
76-
)
89+
)
90+
).inc()
7791
serializer = UploadSerializer(data=request.data)
7892
if not serializer.is_valid():
7993
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
@@ -148,18 +162,16 @@ def post(self, request: HttpRequest) -> Response:
148162
task_arguments=task_arguments,
149163
),
150164
)
151-
152-
sentry_metrics.incr(
153-
"upload",
154-
tags=generate_upload_sentry_metrics_tags(
165+
BUNDLE_ANALYSIS_UPLOAD_VIEWS_COUNTER.labels(
166+
**generate_upload_sentry_metrics_tags(
155167
action="bundle_analysis",
156168
endpoint="bundle_analysis",
157169
request=self.request,
158170
repository=repo,
159171
is_shelter_request=self.is_shelter_request(),
160172
position="end",
161-
),
162-
)
173+
)
174+
).inc()
163175

164176
dispatch_upload_task(
165177
task_arguments,

0 commit comments

Comments
 (0)