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

feat(integrations): Introduce common abstraction for messaging SLOs #77820

Draft
wants to merge 3 commits into
base: messaging-command-abstraction
Choose a base branch
from

Conversation

RyanSkonnord
Copy link
Member

This is a preliminary sketch of a way to have consistent metrics on actions fired from messaging integrations. The goal is to unify both the different messaging integrations (Slack, MsTeams, Discord) and the legacy differences in ways of firing the actions (chat commands and webhook actions).

MessagingInteractionType is our new inventory of, roughly, every kind of user action on which we might want to establish SLOs. MessagingInteractionEvent is an abstraction over metrics on those actions.

For the chat commands, we exploit the new common dispatcher introduced in #77169, meaning we only have to set up MessagingInteractionEvents in that one place. For the webhook actions, each of the three messaging integrations has a different place where we have to add new code.

Left to do (maybe or not in this PR):

  1. Implement the MessagingInteractionEvent.record_* methods, which will probably just be metrics.incr. The only big question is whether to reuse (and move) existing keys, or just create a new namespace (sentry.integrations.slo.* perhaps).
  2. Add assertions in unit tests to ensure that the "record" methods are hit when expected.
  3. Per the comments on having a too-broad definition of "success", dig into soft-failure conditions and consider refactoring as needed.
  4. See if there are other flows lurking in the integration code that should be covered by one of the existing MessagingInteractionTypes.

@github-actions github-actions bot added the Scope: Backend Automatically applied to PRs that change backend components label Sep 19, 2024
arg_input = cmd_input.adjust(slug)
return callback(arg_input)
@dataclass(frozen=True)
class CandidateHandler:
Copy link
Member Author

Choose a reason for hiding this comment

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

If you're wondering why I've nested this class definition in such a strange place, it's so that R can have the same meaning inside and out. The alternative is kind of ugly: see 07b5401.


elif self.custom_id.startswith(CustomIds.ASSIGN):
logger.info(
"discord.interaction.component.assign",
extra={**logging_data, "assign_to": self.request.get_selected_options()[0]},
)
return self.assign()
with record_event(MessagingInteractionType.ASSIGN).capture():
Copy link
Member

Choose a reason for hiding this comment

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

Is there ever a scenario where we wouldn't want to record the event type? I guess I'm curious if we can make this logic more generic now that we have a MessagingInteractionType enum to key off of.

Copy link
Member Author

Choose a reason for hiding this comment

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

I don't know. I'm thinking not? It depends on what we log in the MessagingInteractionEvent.record_* methods.

If there's a use case for logging "an interaction happened where we know the integration but not what the user did", then sure, we could make this optional.

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 I phrased this poorly. I'm asking if we need to manually wrap every interaction we want to record a metric for with a capture context manager, vs finding some way to automate this and capture metrics for every handled messaging interaction type instead.

Copy link
Member Author

Choose a reason for hiding this comment

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

I see. Are you envisioning, like, one flow for determining what action/command is being executed, which is common to all the messaging integrations and outputs the interaction type? That's more or less what I spiked on earlier this week and decided against trying to tackle right now.

Some gestures in that direction include linking MessagingIntegrationCommands to them, and this mapping onto an existing enum (albeit for only one integration).

@@ -9,11 +9,13 @@
from sentry.models.notificationaction import ActionService
from sentry.rules.actions import IntegrationEventAction

PROVIDER = "slack"
Copy link
Member

Choose a reason for hiding this comment

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

Mainly curious about this, but is there any chance someone can accidentally pollute their imports with this being identical between specs?

Copy link
Member Author

Choose a reason for hiding this comment

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

Er, yes, very much so. 😅

Instead of referring to this constant, it might be safer in other places to just write SlackMessagingSpec().provider_slug, which is clearer but also more semantically noisy. (It looks weird at first glance to instantiate the class just to retrieve a single property. There's an argument for making provider_slug a class variable, but then we couldn't annotate it as an @abstactmethod in the same way.)

Copy link

codecov bot commented Sep 19, 2024

Codecov Report

Attention: Patch coverage is 96.24060% with 5 lines in your changes missing coverage. Please review.

✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
src/sentry/integrations/messaging/metrics.py 92.30% 3 Missing and 1 partial ⚠️
src/sentry/integrations/messaging/commands.py 96.15% 1 Missing ⚠️
Additional details and impacted files
@@                       Coverage Diff                       @@
##           messaging-command-abstraction   #77820    +/-   ##
===============================================================
  Coverage                          78.09%   78.10%            
===============================================================
  Files                               6980     6981     +1     
  Lines                             309812   309913   +101     
  Branches                           50710    50732    +22     
===============================================================
+ Hits                              241957   242062   +105     
+ Misses                             61381    61379     -2     
+ Partials                            6474     6472     -2     

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
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