Skip to content

Commit cbe0413

Browse files
armenzgandrewshie-sentry
authored andcommitted
feat(auto_source_config): Add a few more metrics (#86598)
1 parent 7b3a2a7 commit cbe0413

File tree

3 files changed

+85
-60
lines changed

3 files changed

+85
-60
lines changed

src/sentry/integrations/source_code_management/repo_trees.py

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
from sentry.integrations.services.integration import RpcOrganizationIntegration
99
from sentry.issues.auto_source_code_config.utils import get_supported_extensions
1010
from sentry.shared_integrations.exceptions import ApiError, IntegrationError
11+
from sentry.utils import metrics
1112
from sentry.utils.cache import cache
1213

1314
logger = logging.getLogger(__name__)
@@ -63,11 +64,13 @@ def integration_name(self) -> str:
6364

6465
def get_trees_for_org(self) -> dict[str, RepoTree]:
6566
trees = {}
66-
repositories = self._populate_repositories()
67+
with metrics.timer("integrations.source_code_management.populate_repositories.duration"):
68+
repositories = self._populate_repositories()
6769
if not repositories:
6870
logger.warning("Fetching repositories returned an empty list.")
6971
else:
70-
trees = self._populate_trees(repositories)
72+
with metrics.timer("integrations.source_code_management.populate_trees.duration"):
73+
trees = self._populate_trees(repositories)
7174

7275
return trees
7376

@@ -80,7 +83,9 @@ def _populate_repositories(self) -> list[dict[str, str]]:
8083
)
8184
repositories: list[dict[str, str]] = cache.get(cache_key, [])
8285

86+
use_cache = True
8387
if not repositories:
88+
use_cache = False
8489
repositories = [
8590
# Do not use RepoAndBranch so it stores in the cache as a simple dict
8691
{
@@ -91,6 +96,11 @@ def _populate_repositories(self) -> list[dict[str, str]]:
9196
if not repo_info.get("archived")
9297
]
9398

99+
metrics.incr(
100+
"integrations.source_code_management.populate_repositories",
101+
tags={"cached": use_cache, "integration": self.integration_name},
102+
)
103+
94104
if repositories:
95105
cache.set(cache_key, repositories, self.CACHE_SECONDS)
96106

@@ -115,6 +125,11 @@ def _populate_trees(self, repositories: Sequence[dict[str, str]]) -> dict[str, R
115125
"Loading trees from cache. Execution will continue. Check logs.", exc_info=True
116126
)
117127

128+
metrics.incr(
129+
"integrations.source_code_management.populate_trees",
130+
tags={"cached": use_cache, "integration": self.integration_name},
131+
)
132+
118133
for index, repo_info in enumerate(repositories):
119134
repo_full_name = repo_info["full_name"]
120135
extra = {"repo_full_name": repo_full_name}

src/sentry/issues/auto_source_code_config/code_mapping.py

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,10 @@
1515
from sentry.models.organization import Organization
1616
from sentry.models.project import Project
1717
from sentry.models.repository import Repository
18+
from sentry.utils import metrics
1819
from sentry.utils.event_frames import EventFrame, try_munge_frame_path
1920

21+
from .constants import METRIC_PREFIX
2022
from .integration_utils import InstallationNotFoundError, get_installation
2123
from .utils import PlatformConfig
2224

@@ -172,16 +174,19 @@ def generate_code_mappings(
172174
self.code_mappings = {}
173175
self.platform = platform
174176

175-
buckets: dict[str, list[FrameInfo]] = self._stacktrace_buckets(frames)
176-
177-
# We reprocess stackframes until we are told that no code mappings were produced
178-
# This is order to reprocess past stackframes in light of newly discovered code mappings
179-
# This allows for idempotency since the order of the stackframes will not matter
180-
# This has no performance issue because stackframes that match an existing code mapping
181-
# will be skipped
182-
while True:
183-
if not self._process_stackframes(buckets):
184-
break
177+
with metrics.timer(
178+
f"{METRIC_PREFIX}.generate_code_mappings.duration", tags={"platform": platform}
179+
):
180+
buckets: dict[str, list[FrameInfo]] = self._stacktrace_buckets(frames)
181+
182+
# We reprocess stackframes until we are told that no code mappings were produced
183+
# This is order to reprocess past stackframes in light of newly discovered code mappings
184+
# This allows for idempotency since the order of the stackframes will not matter
185+
# This has no performance issue because stackframes that match an existing code mapping
186+
# will be skipped
187+
while True:
188+
if not self._process_stackframes(buckets):
189+
break
185190

186191
return list(self.code_mappings.values())
187192

src/sentry/issues/auto_source_code_config/task.py

Lines changed: 53 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -176,58 +176,63 @@ def create_repos_and_code_mappings(
176176
raise InstallationNotFoundError
177177

178178
organization_id = organization_integration.organization_id
179-
for code_mapping in code_mappings:
180-
repository = (
181-
Repository.objects.filter(name=code_mapping.repo.name, organization_id=organization_id)
182-
.order_by("-date_added")
183-
.first()
184-
)
185-
186-
if not repository:
187-
if not dry_run:
188-
repository = Repository.objects.create(
189-
name=code_mapping.repo.name,
190-
organization_id=organization_id,
191-
integration_id=organization_integration.integration_id,
179+
with metrics.timer(
180+
f"{METRIC_PREFIX}.create_configurations.duration", tags={"platform": platform}
181+
):
182+
for code_mapping in code_mappings:
183+
repository = (
184+
Repository.objects.filter(
185+
name=code_mapping.repo.name, organization_id=organization_id
192186
)
193-
metrics.incr(
194-
key=f"{METRIC_PREFIX}.repository.created",
195-
tags={"platform": platform, "dry_run": dry_run},
196-
sample_rate=1.0,
187+
.order_by("-date_added")
188+
.first()
197189
)
198190

199-
extra = {
200-
"project_id": project.id,
201-
"stack_root": code_mapping.stacktrace_root,
202-
"repository_name": code_mapping.repo.name,
203-
}
204-
# The project and stack_root are unique together
205-
existing_code_mappings = RepositoryProjectPathConfig.objects.filter(
206-
project=project, stack_root=code_mapping.stacktrace_root
207-
)
208-
if existing_code_mappings.exists():
209-
logger.warning("Investigate.", extra=extra)
210-
continue
211-
212-
if not dry_run:
213-
if repository is None: # This is mostly to appease the type checker
191+
if not repository:
192+
if not dry_run:
193+
repository = Repository.objects.create(
194+
name=code_mapping.repo.name,
195+
organization_id=organization_id,
196+
integration_id=organization_integration.integration_id,
197+
)
198+
metrics.incr(
199+
key=f"{METRIC_PREFIX}.repository.created",
200+
tags={"platform": platform, "dry_run": dry_run},
201+
sample_rate=1.0,
202+
)
203+
204+
extra = {
205+
"project_id": project.id,
206+
"stack_root": code_mapping.stacktrace_root,
207+
"repository_name": code_mapping.repo.name,
208+
}
209+
# The project and stack_root are unique together
210+
existing_code_mappings = RepositoryProjectPathConfig.objects.filter(
211+
project=project, stack_root=code_mapping.stacktrace_root
212+
)
213+
if existing_code_mappings.exists():
214214
logger.warning("Investigate.", extra=extra)
215215
continue
216216

217-
RepositoryProjectPathConfig.objects.create(
218-
project=project,
219-
stack_root=code_mapping.stacktrace_root,
220-
repository=repository,
221-
organization_integration_id=organization_integration.id,
222-
integration_id=organization_integration.integration_id,
223-
organization_id=organization_integration.organization_id,
224-
source_root=code_mapping.source_path,
225-
default_branch=code_mapping.repo.branch,
226-
automatically_generated=True,
227-
)
217+
if not dry_run:
218+
if repository is None: # This is mostly to appease the type checker
219+
logger.warning("Investigate.", extra=extra)
220+
continue
221+
222+
RepositoryProjectPathConfig.objects.create(
223+
project=project,
224+
stack_root=code_mapping.stacktrace_root,
225+
repository=repository,
226+
organization_integration_id=organization_integration.id,
227+
integration_id=organization_integration.integration_id,
228+
organization_id=organization_integration.organization_id,
229+
source_root=code_mapping.source_path,
230+
default_branch=code_mapping.repo.branch,
231+
automatically_generated=True,
232+
)
228233

229-
metrics.incr(
230-
key=f"{METRIC_PREFIX}.code_mapping.created",
231-
tags={"platform": platform, "dry_run": dry_run},
232-
sample_rate=1.0,
233-
)
234+
metrics.incr(
235+
key=f"{METRIC_PREFIX}.code_mapping.created",
236+
tags={"platform": platform, "dry_run": dry_run},
237+
sample_rate=1.0,
238+
)

0 commit comments

Comments
 (0)