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(generic-metrics): Add dropped percentiles to aggregation options #70824

Merged
merged 21 commits into from
May 23, 2024

Conversation

ayirr7
Copy link
Member

@ayirr7 ayirr7 commented May 13, 2024

Refactoring the way we used an older option for enabling 10s granularity so its purpose is clearer.

Enable org-level and use case-level of disabling percentiles using the newly created Sentry options.

@ayirr7 ayirr7 requested a review from a team as a code owner May 13, 2024 22:45
@ayirr7 ayirr7 marked this pull request as draft May 13, 2024 22:45
@github-actions github-actions bot added the Scope: Backend Automatically applied to PRs that change backend components label May 13, 2024
Copy link

codecov bot commented May 13, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 77.92%. Comparing base (fea4348) to head (5626223).
Report is 173 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff             @@
##           master   #70824      +/-   ##
==========================================
+ Coverage   77.87%   77.92%   +0.04%     
==========================================
  Files        6529     6525       -4     
  Lines      290909   290480     -429     
  Branches    50338    50254      -84     
==========================================
- Hits       226548   226348     -200     
+ Misses      58122    57874     -248     
- Partials     6239     6258      +19     
Files Coverage Δ
src/sentry/options/defaults.py 100.00% <100.00%> (ø)
...ntry/sentry_metrics/aggregation_option_registry.py 100.00% <100.00%> (ø)

... and 162 files with indirect coverage changes

@ayirr7 ayirr7 marked this pull request as ready for review May 15, 2024 17:51
}


def get_aggregation_options(mri: str, org_id: int) -> dict[AggregationOption, TimeWindow] | None:
Copy link
Member

Choose a reason for hiding this comment

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

Since we are only able to write 1 aggregation option at the moment, what if we added a test case which validated that assumption. I am not exactly sure whether that constraint is enforced somewhere in the code or not. But it would be good to have the constrain in place to avoid potential problems in the near future.

Copy link
Member Author

@ayirr7 ayirr7 May 16, 2024

Choose a reason for hiding this comment

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

Good point. Added some logic to our existing unit tests where there are a variety of aggregation options set up, which cover all the use cases etc. The unit test asserts that only 1 exists per metric bucket payload, though.

Once we have multiple aggregation option support, we can remove and refactor these tests to communicate that change in expectations.

What do you think of these changes?

Copy link
Member

Choose a reason for hiding this comment

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

What if we change the signature of this function to -> (AggregationOption, TimeWindow) | None to enforce this in application code? Once we support multiple options, we can easily change the signature again.

Copy link
Member Author

@ayirr7 ayirr7 May 22, 2024

Choose a reason for hiding this comment

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

The indexer already assumes a dict output from calling get_aggregation_options and basically chooses the first element. So in any case, we are always guaranteed to have 1 aggregation option per payload.

I can change the typing and indexer behavior in a subsequent PR, but for now I think I'd like to not have this PR touch too many files at once.

I added some unit tests which should hopefully make the behavior/sequence of operations in get_aggregation_options clearer.

}


def get_aggregation_options(mri: str, org_id: int) -> dict[AggregationOption, TimeWindow] | None:
Copy link
Member

Choose a reason for hiding this comment

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

What if we change the signature of this function to -> (AggregationOption, TimeWindow) | None to enforce this in application code? Once we support multiple options, we can easily change the signature again.


# Set various aggregation options that
# are use case-wide aggregations
set_use_case_aggregation_options()
Copy link
Member

Choose a reason for hiding this comment

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

This function internally modifies a global, but this is done on every call of get_aggregation_options. The global isn't really needed therefore, it could be just a local variable. This would further allow you to simplify and inline the checks into a single if-chain below that would also more clearly show precedence of the options.

Copy link
Member Author

Choose a reason for hiding this comment

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

Updated

src/sentry/sentry_metrics/aggregation_option_registry.py Outdated Show resolved Hide resolved
@ayirr7
Copy link
Member Author

ayirr7 commented May 21, 2024

Will add more unit tests to check that the logic in get_aggregation_options is correct

src/sentry/sentry_metrics/aggregation_option_registry.py Outdated Show resolved Hide resolved
return USE_CASE_AGG_OPTION[use_case_id]
elif use_case_id in use_case_agg_options:
if org_id not in drop_uc_org_override.get(use_case_id.value, []):
return use_case_agg_options[use_case_id]
Copy link
Member

@jan-auer jan-auer May 22, 2024

Choose a reason for hiding this comment

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

As an optional suggestion, this could be easier to read and follow without use_case_agg_options. This branch could check directly the options and then early return the aggregation option.

Pseudo code skeleton for the entire function:

if org_id in options.get("per-org", []):
  return DISABLE_PERCENTILES
  
opt = options.get("with-override", {})
if use_case in opt and org_id not in opt[use_case]:
  return DISABLE_PERCENTILES

if mri in METRIC_ID_AGG_OPTION:
  return METRIC_ID_AGG_OPTION[mri]
  
if use_case == CUSTOM and options.get("10s"):
  return TEN_SECOND

return {}

@@ -1260,6 +1260,15 @@
flags=FLAG_AUTOMATOR_MODIFIABLE,
)

# Option to remove support for percentiles on a per-use case basis.
# Add the use case to list to disable percentiles.
Copy link
Member

Choose a reason for hiding this comment

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

nit: This isn't a list, the use case must be an entry with a list value (otherwise causing a crash). Should we make this more clear?

Copy link
Member Author

Choose a reason for hiding this comment

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

Good callout, thanks

@ayirr7 ayirr7 merged commit 7ae185f into master May 23, 2024
49 checks passed
@ayirr7 ayirr7 deleted the refactor-add-aggregations branch May 23, 2024 19:19
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.

None yet

3 participants