Skip to content
New issue

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

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

Already on GitHub? # to your account

IA-98: add rollout for sentry task latency #83244

Open
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

bmckerry
Copy link
Member

In #71778 the option to allow latency metrics from a SentryTask was added, but defaulted to false and has since only been enabled on 3 tasks.

This PR adds a rollout option to increase the rate at which all tasks in a region report latency metrics. This will allow us to configure monitors based off of task latency instead of backlog similar to what we have for kafka.

@github-actions github-actions bot added the Scope: Backend Automatically applied to PRs that change backend components label Jan 10, 2025
Comment on lines -89 to -90
# Use a try/catch here to contain the blast radius of an exception being unhandled through the options lib
# Unhandled exception could cause all tasks to be effected and not work
Copy link
Member Author

Choose a reason for hiding this comment

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

the code this comment refers to was deleted in a previous PR

do_record_timing_rollout = False
record_timing_rollout = options.get("sentry.tasks.record.timing.rollout")
if record_timing_rollout and record_timing_rollout > random():
do_record_timing_rollout = True
Copy link
Member Author

Choose a reason for hiding this comment

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

setting record_timing = True here made it so the wrapped function wouldn't use the parameter record_timing, so I added do_record_timing_rollout for the rollout logic

Comment on lines 90 to 91
record_timing_rollout = options.get("sentry.tasks.record.timing.rollout")
if record_timing_rollout and record_timing_rollout > random():
Copy link
Member

Choose a reason for hiding this comment

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

You could use sentry.features.rollout.in_random_rollout to handle the comparison with random and handling unset option values.

Copy link

codecov bot commented Jan 10, 2025

❌ 4 Tests Failed:

Tests completed Failed Passed Skipped
23464 4 23460 272
View the top 3 failed tests by shortest run time
tests.sentry.tasks.test_base::test_task_silo_limit_call_control
Stack Traces | 0.039s run time
#x1B[1m#x1B[.../sentry/tasks/test_base.py#x1B[0m:32: in test_task_silo_limit_call_control
    assert "Control task hi" == control_task("hi")
#x1B[1m#x1B[.../sentry/silo/base.py#x1B[0m:158: in override
    return original_method(*args, **kwargs)
#x1B[1m#x1B[31m.venv/lib/python3.12.../site-packages/celery/local.py#x1B[0m:182: in __call__
    return self._get_current_object()(*a, **kw)
#x1B[1m#x1B[31m.venv/lib/python3.12.../celery/app/task.py#x1B[0m:411: in __call__
    return self.run(*args, **kwargs)
#x1B[1m#x1B[.../sentry/silo/base.py#x1B[0m:158: in override
    return original_method(*args, **kwargs)
#x1B[1m#x1B[.../sentry/tasks/base.py#x1B[0m:88: in _wrapped
    record_timing_rollout = in_random_rollout("sentry.tasks.record.timing.rollout")
#x1B[1m#x1B[.../sentry/features/rollout.py#x1B[0m:14: in in_random_rollout
    return random.random() < options.get(option_name)
#x1B[1m#x1B[.../sentry/options/manager.py#x1B[0m:299: in get
    result = self.store.get(opt, silent=silent)
#x1B[1m#x1B[.../sentry/options/store.py#x1B[0m:97: in get
    result = self.get_store(key, silent=silent)
#x1B[1m#x1B[.../sentry/options/store.py#x1B[0m:193: in get_store
    value = self.model.objects.get(key=key.name).value
#x1B[1m#x1B[31m.venv/lib/python3.12.../db/models/manager.py#x1B[0m:87: in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
#x1B[1m#x1B[31m.venv/lib/python3.12.../db/models/query.py#x1B[0m:645: in get
    num = len(clone)
#x1B[1m#x1B[31m.venv/lib/python3.12.../db/models/query.py#x1B[0m:382: in __len__
    self._fetch_all()
#x1B[1m#x1B[31m.venv/lib/python3.12.../db/models/query.py#x1B[0m:1928: in _fetch_all
    self._result_cache = list(self._iterable_class(self))
#x1B[1m#x1B[31m.venv/lib/python3.12.../db/models/query.py#x1B[0m:91: in __iter__
    results = compiler.execute_sql(
#x1B[1m#x1B[31m.venv/lib/python3.12.../models/sql/compiler.py#x1B[0m:1572: in execute_sql
    cursor = self.connection.cursor()
#x1B[1m#x1B[31m.venv/lib/python3.12.../django/utils/asyncio.py#x1B[0m:26: in inner
    return func(*args, **kwargs)
#x1B[1m#x1B[31m.venv/lib/python3.12.../backends/base/base.py#x1B[0m:320: in cursor
    return self._cursor()
#x1B[1m#x1B[.../db/postgres/decorators.py#x1B[0m:40: in inner
    return func(self, *args, **kwargs)
#x1B[1m#x1B[.../db/postgres/base.py#x1B[0m:108: in _cursor
    return super()._cursor()
#x1B[1m#x1B[31m.venv/lib/python3.12.../backends/base/base.py#x1B[0m:296: in _cursor
    self.ensure_connection()
#x1B[1m#x1B[31mE   RuntimeError: Database access not allowed, use the "django_db" mark, or the "db" or "transactional_db" fixtures to enable it.#x1B[0m
tests.sentry.tasks.test_base::test_task_silo_limit_call_monolith
Stack Traces | 0.039s run time
#x1B[1m#x1B[.../sentry/tasks/test_base.py#x1B[0m:37: in test_task_silo_limit_call_monolith
    assert "Region task hi" == region_task("hi")
#x1B[1m#x1B[.../sentry/silo/base.py#x1B[0m:158: in override
    return original_method(*args, **kwargs)
#x1B[1m#x1B[31m.venv/lib/python3.12.../site-packages/celery/local.py#x1B[0m:182: in __call__
    return self._get_current_object()(*a, **kw)
#x1B[1m#x1B[31m.venv/lib/python3.12.../celery/app/task.py#x1B[0m:411: in __call__
    return self.run(*args, **kwargs)
#x1B[1m#x1B[.../sentry/silo/base.py#x1B[0m:158: in override
    return original_method(*args, **kwargs)
#x1B[1m#x1B[.../sentry/tasks/base.py#x1B[0m:88: in _wrapped
    record_timing_rollout = in_random_rollout("sentry.tasks.record.timing.rollout")
#x1B[1m#x1B[.../sentry/features/rollout.py#x1B[0m:14: in in_random_rollout
    return random.random() < options.get(option_name)
#x1B[1m#x1B[.../sentry/options/manager.py#x1B[0m:299: in get
    result = self.store.get(opt, silent=silent)
#x1B[1m#x1B[.../sentry/options/store.py#x1B[0m:97: in get
    result = self.get_store(key, silent=silent)
#x1B[1m#x1B[.../sentry/options/store.py#x1B[0m:193: in get_store
    value = self.model.objects.get(key=key.name).value
#x1B[1m#x1B[31m.venv/lib/python3.12.../db/models/manager.py#x1B[0m:87: in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
#x1B[1m#x1B[31m.venv/lib/python3.12.../db/models/query.py#x1B[0m:645: in get
    num = len(clone)
#x1B[1m#x1B[31m.venv/lib/python3.12.../db/models/query.py#x1B[0m:382: in __len__
    self._fetch_all()
#x1B[1m#x1B[31m.venv/lib/python3.12.../db/models/query.py#x1B[0m:1928: in _fetch_all
    self._result_cache = list(self._iterable_class(self))
#x1B[1m#x1B[31m.venv/lib/python3.12.../db/models/query.py#x1B[0m:91: in __iter__
    results = compiler.execute_sql(
#x1B[1m#x1B[31m.venv/lib/python3.12.../models/sql/compiler.py#x1B[0m:1572: in execute_sql
    cursor = self.connection.cursor()
#x1B[1m#x1B[31m.venv/lib/python3.12.../django/utils/asyncio.py#x1B[0m:26: in inner
    return func(*args, **kwargs)
#x1B[1m#x1B[31m.venv/lib/python3.12.../backends/base/base.py#x1B[0m:320: in cursor
    return self._cursor()
#x1B[1m#x1B[.../db/postgres/decorators.py#x1B[0m:40: in inner
    return func(self, *args, **kwargs)
#x1B[1m#x1B[.../db/postgres/base.py#x1B[0m:108: in _cursor
    return super()._cursor()
#x1B[1m#x1B[31m.venv/lib/python3.12.../backends/base/base.py#x1B[0m:296: in _cursor
    self.ensure_connection()
#x1B[1m#x1B[31mE   RuntimeError: Database access not allowed, use the "django_db" mark, or the "db" or "transactional_db" fixtures to enable it.#x1B[0m
tests.sentry.tasks.test_base::test_task_silo_limit_call_region
Stack Traces | 0.041s run time
#x1B[1m#x1B[.../sentry/tasks/test_base.py#x1B[0m:20: in test_task_silo_limit_call_region
    result = region_task("hi")
#x1B[1m#x1B[.../sentry/silo/base.py#x1B[0m:158: in override
    return original_method(*args, **kwargs)
#x1B[1m#x1B[31m.venv/lib/python3.12.../site-packages/celery/local.py#x1B[0m:182: in __call__
    return self._get_current_object()(*a, **kw)
#x1B[1m#x1B[31m.venv/lib/python3.12.../celery/app/task.py#x1B[0m:411: in __call__
    return self.run(*args, **kwargs)
#x1B[1m#x1B[.../sentry/silo/base.py#x1B[0m:158: in override
    return original_method(*args, **kwargs)
#x1B[1m#x1B[.../sentry/tasks/base.py#x1B[0m:88: in _wrapped
    record_timing_rollout = in_random_rollout("sentry.tasks.record.timing.rollout")
#x1B[1m#x1B[.../sentry/features/rollout.py#x1B[0m:14: in in_random_rollout
    return random.random() < options.get(option_name)
#x1B[1m#x1B[.../sentry/options/manager.py#x1B[0m:299: in get
    result = self.store.get(opt, silent=silent)
#x1B[1m#x1B[.../sentry/options/store.py#x1B[0m:97: in get
    result = self.get_store(key, silent=silent)
#x1B[1m#x1B[.../sentry/options/store.py#x1B[0m:193: in get_store
    value = self.model.objects.get(key=key.name).value
#x1B[1m#x1B[31m.venv/lib/python3.12.../db/models/manager.py#x1B[0m:87: in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
#x1B[1m#x1B[31m.venv/lib/python3.12.../db/models/query.py#x1B[0m:645: in get
    num = len(clone)
#x1B[1m#x1B[31m.venv/lib/python3.12.../db/models/query.py#x1B[0m:382: in __len__
    self._fetch_all()
#x1B[1m#x1B[31m.venv/lib/python3.12.../db/models/query.py#x1B[0m:1928: in _fetch_all
    self._result_cache = list(self._iterable_class(self))
#x1B[1m#x1B[31m.venv/lib/python3.12.../db/models/query.py#x1B[0m:91: in __iter__
    results = compiler.execute_sql(
#x1B[1m#x1B[31m.venv/lib/python3.12.../models/sql/compiler.py#x1B[0m:1572: in execute_sql
    cursor = self.connection.cursor()
#x1B[1m#x1B[31m.venv/lib/python3.12.../django/utils/asyncio.py#x1B[0m:26: in inner
    return func(*args, **kwargs)
#x1B[1m#x1B[31m.venv/lib/python3.12.../backends/base/base.py#x1B[0m:320: in cursor
    return self._cursor()
#x1B[1m#x1B[.../db/postgres/decorators.py#x1B[0m:40: in inner
    return func(self, *args, **kwargs)
#x1B[1m#x1B[.../db/postgres/base.py#x1B[0m:108: in _cursor
    return super()._cursor()
#x1B[1m#x1B[31m.venv/lib/python3.12.../backends/base/base.py#x1B[0m:296: in _cursor
    self.ensure_connection()
#x1B[1m#x1B[31mE   RuntimeError: Database access not allowed, use the "django_db" mark, or the "db" or "transactional_db" fixtures to enable it.#x1B[0m

To view more test analytics, go to the Test Analytics Dashboard
📢 Thoughts on this report? Let us know!

Copy link
Member

@markstory markstory left a comment

Choose a reason for hiding this comment

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

Looks good to me.

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