Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore(sentry apps): Create forward shims for sentry apps tasks #78344

Merged
merged 14 commits into from
Oct 2, 2024

Conversation

Christinarlong
Copy link
Contributor

Before we start moving task logic for sentry app tasks, we need shims for forward compatibility.

issue ref(#73857 )

@github-actions github-actions bot added the Scope: Backend Automatically applied to PRs that change backend components label Sep 30, 2024
Copy link

codecov bot commented Sep 30, 2024

Codecov Report

Attention: Patch coverage is 84.78261% with 14 lines in your changes missing coverage. Please review.

✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
src/sentry/sentry_apps/tasks/sentry_apps.py 82.22% 8 Missing ⚠️
src/sentry/tasks/sentry_apps.py 86.48% 5 Missing ⚠️
src/sentry/sentry_apps/tasks/service_hooks.py 85.71% 1 Missing ⚠️
Additional details and impacted files
@@           Coverage Diff            @@
##           master   #78344    +/-   ##
========================================
  Coverage   78.08%   78.09%            
========================================
  Files        7066     7079    +13     
  Lines      311763   312112   +349     
  Branches    50956    51025    +69     
========================================
+ Hits       243452   243753   +301     
- Misses      61961    62001    +40     
- Partials     6350     6358     +8     

"sentry.sentry_apps.tasks.sentry_apps.process_resource_change_bound", bind=True, **TASK_OPTIONS
)
@retry_decorator
def process_resource_change_bound(self, action, sender, instance_id, *args, **kwargs):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we're going to need types on the parameters and return types in this module to get through CI.

Copy link
Contributor Author

@Christinarlong Christinarlong Oct 1, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oddly enough a lot of untyped functions in this file don't trigger mypy :thonk, spitballing, but maybe because their callers don't use types? The functions are not in classes? idk, but yes we should type them while we're at it

Edit: oop not this file, but in sentry/tasks/sentry_apps.py [original file], so nvm yea we'll need to type this func

src/sentry/sentry_apps/tasks/sentry_apps.py Outdated Show resolved Hide resolved
# The class is serialized as a string when enqueueing the class.
model = TYPES[sender]
model: Event | Group | Activity = TYPES[sender]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You might need this to be type[Event] | type[Model]

# The Event model has different hooks for the different event types. The sender
# determines which type eg. Error and therefore the 'name' eg. error
if issubclass(model, Event):
if isinstance(model, Event):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't this change how the function works in a meaningful way? issubclass() works with class objects, whereas isinstance() works with class instances.

Copy link
Contributor Author

@Christinarlong Christinarlong Oct 1, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, 100%, it turns out I didn't actually push the corrections... 🫠 [ I would like to blame vscode editor for this one ]

Comment on lines +227 to +245
assert org, "organization must exist to get related sentry app installations"
installations: list[RpcSentryAppInstallation] = [
installation
for installation in app_service.get_installed_for_organization(organization_id=org.id)
if event in installation.sentry_app.events
]

for installation in installations:
data = {}
if isinstance(instance, (Event, GroupEvent)):
assert instance.group_id, "group id is required to create webhook event data"
data[name] = _webhook_event_data(instance, instance.group_id, instance.project_id)
else:
data[name] = serialize(instance)

# Trigger a new task for each webhook
send_resource_change_webhook.delay(
installation_id=installation.id, event=event, data=data
)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a slight logical change here that this code will only be ran if the instance is a Group | Event | GroupEvent (i.e if the instance is an Activity we do nothing) but I believe this was the case with the previous iteration too (?) since we don't get an organization and therefore installation to work with.

Sidenote: Do we process Activity/Comments here ? I couldn't find any related code calling this func for those event types.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a slight logical change here that this code will only be ran if the instance is a Group | Event | GroupEvent (i.e if the instance is an Activity we do nothing) but I believe this was the case with the previous iteration too

I don't think that difference in behavior will matter. Currently if Activity is used there will be an AttributeError for org.id which doesn't exist.

Sidenote: Do we process Activity/Comments here ? I couldn't find any related code calling this func for those event types.

There are no tests covering Comments/Activity, and no call sites that I could find. Once we've finished moving the tasks we could add a metric/log message to validate that there are no indirect paths that use Activity and then remove this code if it is truly unused.

Comment on lines +227 to +245
assert org, "organization must exist to get related sentry app installations"
installations: list[RpcSentryAppInstallation] = [
installation
for installation in app_service.get_installed_for_organization(organization_id=org.id)
if event in installation.sentry_app.events
]

for installation in installations:
data = {}
if isinstance(instance, (Event, GroupEvent)):
assert instance.group_id, "group id is required to create webhook event data"
data[name] = _webhook_event_data(instance, instance.group_id, instance.project_id)
else:
data[name] = serialize(instance)

# Trigger a new task for each webhook
send_resource_change_webhook.delay(
installation_id=installation.id, event=event, data=data
)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a slight logical change here that this code will only be ran if the instance is a Group | Event | GroupEvent (i.e if the instance is an Activity we do nothing) but I believe this was the case with the previous iteration too

I don't think that difference in behavior will matter. Currently if Activity is used there will be an AttributeError for org.id which doesn't exist.

Sidenote: Do we process Activity/Comments here ? I couldn't find any related code calling this func for those event types.

There are no tests covering Comments/Activity, and no call sites that I could find. Once we've finished moving the tasks we could add a metric/log message to validate that there are no indirect paths that use Activity and then remove this code if it is truly unused.

@@ -449,6 +473,7 @@ def send_webhooks(installation, event, **kwargs):
kwargs["install"] = installation

request_data = AppPlatformEvent(**kwargs)
assert servicehook.sentry_app, "sentry app must exist to get webhook url"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interesting that we use both installation.sentry_app and servicehook.sentry_app here 🤔

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🌵

@Christinarlong Christinarlong marked this pull request as ready for review October 2, 2024 16:53
@Christinarlong Christinarlong requested review from a team as code owners October 2, 2024 16:53
@Christinarlong Christinarlong merged commit c4fe51a into master Oct 2, 2024
49 checks passed
@Christinarlong Christinarlong deleted the forward-sentryapp-shims branch October 2, 2024 21:15
Copy link

sentry-io bot commented Oct 3, 2024

Suspect Issues

This pull request was deployed and Sentry observed the following issues:

  • ‼️ RateLimitExceeded: Query on could not be run due to allocation policies, info: {'details': {'ConcurrentRateLimitAllo... sentry.tasks.process_resource_change_bound View Issue
  • ‼️ SnubaError: HTTPConnectionPool(host='127.0.0.1', port=10006): Read timed out. (read timeout=30) sentry.tasks.process_resource_change_bound View Issue

Did you find this useful? React with a 👍 or 👎

@github-actions github-actions bot locked and limited conversation to collaborators Oct 19, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Scope: Backend Automatically applied to PRs that change backend components
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants