diff --git a/.github/workflows/semgrep.yml b/.github/workflows/semgrep.yml
deleted file mode 100644
index 2a971adae360..000000000000
--- a/.github/workflows/semgrep.yml
+++ /dev/null
@@ -1,47 +0,0 @@
-# Finds code problems by structural pattern matching.
-#
-# New rules can be added to test_root/semgrep/ and they should be picked up
-# automatically. See https://semgrep.dev/docs/ for documentation.
-
-name: Semgrep code quality
-
-on:
- pull_request:
- merge_group:
- push:
- branches:
- - master
-
-jobs:
- run_semgrep:
- name: Semgrep analysis
- runs-on: "${{ matrix.os }}"
- strategy:
- matrix:
- os: ["ubuntu-latest"]
- python-version:
- - "3.12"
-
- steps:
- - uses: actions/checkout@v7
- with:
- fetch-depth: 1
-
- - uses: actions/setup-python@v6
- with:
- python-version: "${{ matrix.python-version }}"
-
- - name: Install semgrep
- run: |
- make pre-requirements
- pip-sync requirements/edx/semgrep.txt
-
- - name: Run semgrep
- env:
- # Peg this to some reasonable value so that semgrep's rewrapping
- # of messages doesn't break up lines in an unpredictable manner:
- # https://github.com/returntocorp/semgrep/issues/8608
- COLUMNS: 80
- run: |
- semgrep scan --config test_root/semgrep/ --error --quiet \
- -- lms cms common openedx
diff --git a/Makefile b/Makefile
index 98931cb608d2..e97c3c2fd9c4 100644
--- a/Makefile
+++ b/Makefile
@@ -96,7 +96,6 @@ REQ_FILES = \
requirements/edx/testing \
requirements/edx/assets \
requirements/edx/development \
- requirements/edx/semgrep \
scripts/xblock/requirements \
scripts/user_retirement/requirements/base \
scripts/user_retirement/requirements/testing \
diff --git a/cms/djangoapps/cms_user_tasks/tasks.py b/cms/djangoapps/cms_user_tasks/tasks.py
index 0efc852e22c6..7be7762f3fd6 100644
--- a/cms/djangoapps/cms_user_tasks/tasks.py
+++ b/cms/djangoapps/cms_user_tasks/tasks.py
@@ -9,7 +9,6 @@
from celery.utils.log import get_task_logger
from django.conf import settings
from django.core import mail
-from edx_django_utils.monitoring import set_code_owner_attribute
from common.djangoapps.edxmako.shortcuts import render_to_string
from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers
@@ -20,7 +19,6 @@
@shared_task(bind=True)
-@set_code_owner_attribute
def send_task_complete_email(self, task_name, task_state_text, dest_addr, detail_url,
olx_validation_text=None, is_course_optimizer_task=False):
"""
diff --git a/cms/djangoapps/contentstore/tasks.py b/cms/djangoapps/contentstore/tasks.py
index d16e941b09e1..f5227a480a23 100644
--- a/cms/djangoapps/contentstore/tasks.py
+++ b/cms/djangoapps/contentstore/tasks.py
@@ -26,8 +26,6 @@
from django.test import RequestFactory
from django.utils.text import get_valid_filename
from edx_django_utils.monitoring import (
- set_code_owner_attribute,
- set_code_owner_attribute_from_module,
set_custom_attribute,
set_custom_attributes_for_course_key,
)
@@ -166,7 +164,6 @@ def clone_instance(instance, field_values):
@shared_task
-@set_code_owner_attribute
def rerun_course(source_course_key_string, destination_course_key_string, user_id, fields=None):
"""
Reruns a course in a new celery task.
@@ -262,7 +259,6 @@ def _parse_time(time_isoformat):
@shared_task
-@set_code_owner_attribute
def update_search_index(course_id, triggered_time_isoformat):
""" Updates course search index. """
try:
@@ -293,7 +289,6 @@ def update_search_index(course_id, triggered_time_isoformat):
@shared_task
-@set_code_owner_attribute
def update_library_index(library_id, triggered_time_isoformat):
""" Updates course search index. """
try:
@@ -307,7 +302,6 @@ def update_library_index(library_id, triggered_time_isoformat):
@shared_task
-@set_code_owner_attribute
def update_special_exams_and_publish(course_key_str):
"""
Registers special exams for a given course and calls publishing flow.
@@ -368,13 +362,11 @@ def generate_name(cls, arguments_dict):
@shared_task(base=CourseExportTask, bind=True)
-# Note: The decorator @set_code_owner_attribute cannot be used here because the UserTaskMixin
# does stack inspection and can't handle additional decorators.
def export_olx(self, user_id, course_key_string, language):
"""
Export a course or library to an OLX .tar.gz archive and prepare it for download.
"""
- set_code_owner_attribute_from_module(__name__)
courselike_key = CourseKey.from_string(course_key_string)
try:
@@ -546,14 +538,12 @@ def sync_discussion_settings(course_key, user):
@shared_task(base=CourseImportTask, bind=True)
-# Note: The decorator @set_code_owner_attribute cannot be used here because the UserTaskMixin
# does stack inspection and can't handle additional decorators.
# pylint: disable=too-many-statements
def import_olx(self, user_id, course_key_string, archive_path, archive_name, language):
"""
Import a course or library from a provided OLX .tar.gz or .zip archive.
"""
- set_code_owner_attribute_from_module(__name__)
current_step = 'Unpacking'
courselike_key = CourseKey.from_string(course_key_string)
set_custom_attributes_for_course_key(courselike_key)
@@ -789,7 +779,6 @@ def read_chunk():
@shared_task
-@set_code_owner_attribute
def update_all_outlines_from_modulestore_task():
"""
Celery task that creates multiple celery tasks - one per learning_sequence course outline
@@ -816,7 +805,6 @@ def update_all_outlines_from_modulestore_task():
@shared_task
-@set_code_owner_attribute
def update_outline_from_modulestore_task(course_key_str: str):
"""
Celery task that creates a learning_sequence course outline.
@@ -961,7 +949,6 @@ def _get_users_by_access_level(v1_library_key):
@shared_task(time_limit=30)
-@set_code_owner_attribute
def delete_v1_library(v1_library_key_string):
"""
Delete a v1 library index by key string.
@@ -987,6 +974,146 @@ def delete_v1_library(v1_library_key_string):
}
+@shared_task(time_limit=30)
+def validate_all_library_source_blocks_ids_for_course(course_key_string, v1_to_v2_lib_map):
+ """Search a Modulestore for all library source blocks in a course by querying mongo.
+ replace all source_library_ids with the corresponding v2 value from the map
+ """
+ course_id = CourseKey.from_string(course_key_string)
+ store = modulestore()
+ with store.bulk_operations(course_id):
+ visited = []
+ for branch in [ModuleStoreEnum.BranchName.draft, ModuleStoreEnum.BranchName.published]:
+ blocks = store.get_items(
+ course_id.for_branch(branch),
+ settings={'source_library_id': {'$exists': True}}
+ )
+ for xblock in blocks:
+ if xblock.source_library_id not in v1_to_v2_lib_map.values():
+ # pylint: disable=broad-except
+ raise Exception(
+ f'{xblock.source_library_id} in {course_id} is not found in mapping. Validation failed'
+ )
+ visited.append(xblock.source_library_id)
+ # return sucess
+ return visited
+
+
+@shared_task(time_limit=30)
+def replace_all_library_source_blocks_ids_for_course(course_key_string, v1_to_v2_lib_map): # pylint: disable=useless-return
+ """Search a Modulestore for all library source blocks in a course by querying mongo.
+ replace all source_library_ids with the corresponding v2 value from the map.
+
+ This will trigger a publish on the course for every published library source block.
+ """
+ store = modulestore()
+ course_id = CourseKey.from_string(course_key_string)
+
+ with store.bulk_operations(course_id):
+ #for branch in [ModuleStoreEnum.BranchName.draft, ModuleStoreEnum.BranchName.published]:
+ draft_blocks, published_blocks = [
+ store.get_items(
+ course_id.for_branch(branch),
+ settings={'source_library_id': {'$exists': True}}
+ )
+ for branch in [ModuleStoreEnum.BranchName.draft, ModuleStoreEnum.BranchName.published]
+ ]
+
+ published_dict = {block.location: block for block in published_blocks}
+
+ for draft_library_source_block in draft_blocks:
+ try:
+ new_source_id = str(v1_to_v2_lib_map[draft_library_source_block.source_library_id])
+ except KeyError:
+ #skip invalid keys
+ LOGGER.error(
+ 'Key %s not found in mapping. Skipping block for course %s',
+ str({draft_library_source_block.source_library_id}),
+ str(course_id)
+ )
+ continue
+
+ # The publsihed branch should be updated as well as the draft branch
+ # This way, if authors "discard changes," they won't be reverted back to the V1 lib.
+ # However, we also don't want to publish the draft branch.
+ try:
+ if published_dict[draft_library_source_block.location] is not None:
+ #temporarily set the published version to be the draft & publish it.
+ temp = published_dict[draft_library_source_block.location]
+ temp.source_library_id = new_source_id
+ store.update_item(temp, None)
+ store.publish(temp.location, None)
+ draft_library_source_block.source_library_id = new_source_id
+ store.update_item(draft_library_source_block, None)
+ except KeyError:
+ #Warn, but just update the draft block if no published block for draft block.
+ LOGGER.warning(
+ 'No matching published block for draft block %s',
+ str(draft_library_source_block.location)
+ )
+ draft_library_source_block.source_library_id = new_source_id
+ store.update_item(draft_library_source_block, None)
+ # return success
+ return
+
+
+@shared_task(time_limit=30)
+def undo_all_library_source_blocks_ids_for_course(course_key_string, v1_to_v2_lib_map): # pylint: disable=useless-return
+ """Search a Modulestore for all library source blocks in a course by querying mongo.
+ replace all source_library_ids with the corresponding v1 value from the inverted map.
+ This is exists to undo changes made previously.
+ """
+ course_id = CourseKey.from_string(course_key_string)
+
+ v2_to_v1_lib_map = {v: k for k, v in v1_to_v2_lib_map.items()}
+
+ store = modulestore()
+ draft_blocks, published_blocks = [
+ store.get_items(
+ course_id.for_branch(branch),
+ settings={'source_library_id': {'$exists': True}}
+ )
+ for branch in [ModuleStoreEnum.BranchName.draft, ModuleStoreEnum.BranchName.published]
+ ]
+
+ published_dict = {block.location: block for block in published_blocks}
+
+ for draft_library_source_block in draft_blocks:
+ try:
+ new_source_id = str(v2_to_v1_lib_map[draft_library_source_block.source_library_id])
+ except KeyError:
+ #skip invalid keys
+ LOGGER.error(
+ 'Key %s not found in mapping. Skipping block for course %s',
+ str({draft_library_source_block.source_library_id}),
+ str(course_id)
+ )
+ continue
+
+ # The publsihed branch should be updated as well as the draft branch
+ # This way, if authors "discard changes," they won't be reverted back to the V1 lib.
+ # However, we also don't want to publish the draft branch.
+ try:
+ if published_dict[draft_library_source_block.location] is not None:
+ #temporarily set the published version to be the draft & publish it.
+ temp = published_dict[draft_library_source_block.location]
+ temp.source_library_id = new_source_id
+ store.update_item(temp, None)
+ store.publish(temp.location, None)
+ draft_library_source_block.source_library_id = new_source_id
+ store.update_item(draft_library_source_block, None)
+ except KeyError:
+ #Warn, but just update the draft block if no published block for draft block.
+ LOGGER.warning(
+ 'No matching published block for draft block %s',
+ str(draft_library_source_block.location)
+ )
+ draft_library_source_block.source_library_id = new_source_id
+ store.update_item(draft_library_source_block, None)
+ # return success
+ return
+
+
class CourseLinkCheckTask(UserTask): # pylint: disable=abstract-method
"""
Base class for course link check tasks.
@@ -1021,13 +1148,11 @@ def generate_name(cls, arguments_dict):
@shared_task(base=CourseLinkCheckTask, bind=True)
-# Note: The decorator @set_code_owner_attribute cannot be used here because the UserTaskMixin
# does stack inspection and can't handle additional decorators.
def check_broken_links(self, user_id, course_key_string, language):
"""
Checks for broken links in a course and store the results in a file.
"""
- set_code_owner_attribute_from_module(__name__)
return _check_broken_links(self, user_id, course_key_string, language)
@@ -1495,7 +1620,6 @@ def _write_broken_links_to_file(broken_or_locked_urls, broken_links_file):
@shared_task
-@set_code_owner_attribute
def handle_create_xblock_upstream_link(usage_key):
"""
Create upstream link for a single xblock.
@@ -1523,7 +1647,6 @@ def handle_create_xblock_upstream_link(usage_key):
@shared_task
-@set_code_owner_attribute
def handle_update_xblock_upstream_link(usage_key):
"""
Update upstream link for a single xblock.
@@ -1540,7 +1663,6 @@ def handle_update_xblock_upstream_link(usage_key):
@shared_task
-@set_code_owner_attribute
def create_or_update_upstream_links(
course_key_str: str,
force: bool = False,
@@ -1581,7 +1703,6 @@ def create_or_update_upstream_links(
@shared_task
-@set_code_owner_attribute
def handle_unlink_upstream_block(upstream_usage_key_string: str) -> None:
"""
Handle updates needed to downstream blocks when the upstream link is severed.
@@ -1601,7 +1722,6 @@ def handle_unlink_upstream_block(upstream_usage_key_string: str) -> None:
@shared_task
-@set_code_owner_attribute
def handle_unlink_upstream_container(upstream_container_key_string: str) -> None:
"""
Handle updates needed to downstream blocks when the upstream link is severed.
@@ -1658,7 +1778,6 @@ def update_course_rerun_links(
"""
Updates course links to point to the latest re-run.
"""
- set_code_owner_attribute_from_module(__name__)
return _update_course_rerun_links(
self, user_id, course_id, action, data, language
)
@@ -2214,7 +2333,6 @@ def migrate_course_legacy_library_blocks_to_item_bank(
leaving migrated blocks as drafts.
"""
ensure_cms("Legacy library content references may only be executed in CMS")
- set_code_owner_attribute_from_module(__name__)
_cancel_old_tasks(course_key, self.status.user, [self.status.task_id])
try:
key = CourseKey.from_string(course_key)
diff --git a/cms/djangoapps/export_course_metadata/tasks.py b/cms/djangoapps/export_course_metadata/tasks.py
index c95b91adde28..5477e873a4bf 100644
--- a/cms/djangoapps/export_course_metadata/tasks.py
+++ b/cms/djangoapps/export_course_metadata/tasks.py
@@ -6,7 +6,6 @@
from celery import shared_task
from django.core.files.base import ContentFile
-from edx_django_utils.monitoring import set_code_owner_attribute
from opaque_keys.edx.keys import CourseKey
from openedx.core.djangoapps.schedules.content_highlights import get_all_course_highlights
@@ -15,7 +14,6 @@
@shared_task(bind=True)
-@set_code_owner_attribute
def export_course_metadata_task(self, course_key_string): # pylint: disable=unused-argument
"""
Export course metadata
diff --git a/cms/djangoapps/modulestore_migrator/tasks.py b/cms/djangoapps/modulestore_migrator/tasks.py
index 3426302c3c10..a4b7c503aa94 100644
--- a/cms/djangoapps/modulestore_migrator/tasks.py
+++ b/cms/djangoapps/modulestore_migrator/tasks.py
@@ -17,7 +17,6 @@
from django.db import transaction
from django.utils.text import slugify
from django.utils.translation import gettext_lazy as _
-from edx_django_utils.monitoring import set_code_owner_attribute_from_module
from lxml import etree
from lxml.etree import _ElementTree as XmlTree
from opaque_keys import InvalidKeyError
@@ -490,7 +489,6 @@ def _set_migrations_to_fail(source_data_list: list[_MigrationSourceData]):
@shared_task(base=_BulkMigrationTask, bind=True)
-# Note: The decorator @set_code_owner_attribute cannot be used here because the UserTaskMixin
# does stack inspection and can't handle additional decorators.
def bulk_migrate_from_modulestore(
self: _BulkMigrationTask,
@@ -548,7 +546,6 @@ def bulk_migrate_from_modulestore(
# This is a large function, but breaking it up futher would probably not
# make it any easier to understand.
- set_code_owner_attribute_from_module(__name__)
status: UserTaskStatus = self.status
# Validating input
diff --git a/common/djangoapps/entitlements/tasks.py b/common/djangoapps/entitlements/tasks.py
index 2ce2399ef847..63d70fcf6e6f 100644
--- a/common/djangoapps/entitlements/tasks.py
+++ b/common/djangoapps/entitlements/tasks.py
@@ -7,7 +7,6 @@
from celery.utils.log import get_task_logger
from django.conf import settings # pylint: disable=unused-import # noqa: F401
from django.contrib.auth import get_user_model
-from edx_django_utils.monitoring import set_code_owner_attribute
from common.djangoapps.entitlements.models import CourseEntitlement, CourseEntitlementSupportDetail
@@ -24,7 +23,6 @@
@shared_task(bind=True, ignore_result=True)
-@set_code_owner_attribute
def expire_old_entitlements(self, start, end, logid='...'):
"""
This task is designed to be called to process a bundle of entitlements
@@ -69,7 +67,6 @@ def expire_old_entitlements(self, start, end, logid='...'):
@shared_task(bind=True)
-@set_code_owner_attribute
def expire_and_create_entitlements(self, entitlement_ids, support_username):
"""
Expire entitlements older than one year.
diff --git a/common/djangoapps/student/tasks.py b/common/djangoapps/student/tasks.py
index cf95d56a99db..a366d295859d 100644
--- a/common/djangoapps/student/tasks.py
+++ b/common/djangoapps/student/tasks.py
@@ -6,7 +6,6 @@
from celery import shared_task
from django.conf import settings
from django.contrib.auth import get_user_model
-from edx_django_utils.monitoring import set_code_owner_attribute
from opaque_keys.edx.keys import CourseKey
from common.djangoapps.course_modes.models import CourseMode
@@ -28,7 +27,6 @@
@shared_task(bind=True, ignore_result=True)
-@set_code_owner_attribute
def send_course_enrollment_email(
self, user_id, course_id, course_title, short_description, course_ended, pacing_type, track_mode
):
diff --git a/common/djangoapps/third_party_auth/tasks.py b/common/djangoapps/third_party_auth/tasks.py
index ad942814ae56..704375717c96 100644
--- a/common/djangoapps/third_party_auth/tasks.py
+++ b/common/djangoapps/third_party_auth/tasks.py
@@ -8,7 +8,6 @@
import requests
from celery import shared_task
from django.core.exceptions import ObjectDoesNotExist
-from edx_django_utils.monitoring import set_code_owner_attribute
from lxml import etree
from requests import exceptions
from social_django.models import UserSocialAuth
@@ -28,7 +27,6 @@
@shared_task
-@set_code_owner_attribute
def fetch_saml_metadata():
"""
Fetch and store/update the metadata of all IdPs
@@ -139,7 +137,6 @@ def fetch_saml_metadata():
@shared_task
-@set_code_owner_attribute
def update_saml_users_social_auth_uid(reader, slug):
"""
Update the UserSocialAuth UID for users based on a CSV reader input.
diff --git a/lms/djangoapps/bulk_email/tasks.py b/lms/djangoapps/bulk_email/tasks.py
index ff3108fbe0e3..06c7c9786876 100644
--- a/lms/djangoapps/bulk_email/tasks.py
+++ b/lms/djangoapps/bulk_email/tasks.py
@@ -25,7 +25,6 @@
from django.utils import timezone
from django.utils.translation import gettext as _
from django.utils.translation import override as override_language
-from edx_django_utils.monitoring import set_code_owner_attribute
from eventtracking import tracker
from markupsafe import escape
@@ -232,7 +231,6 @@ def _create_send_email_subtask(to_list, initial_subtask_status):
@shared_task(default_retry_delay=settings.BULK_EMAIL_DEFAULT_RETRY_DELAY, max_retries=settings.BULK_EMAIL_MAX_RETRIES)
-@set_code_owner_attribute
def send_course_email(entry_id, email_id, to_list, global_email_context, subtask_status_dict):
"""
Sends an email to a list of recipients.
diff --git a/lms/djangoapps/ccx/tasks.py b/lms/djangoapps/ccx/tasks.py
index 5b9fd9c17d33..43877ce8bfee 100644
--- a/lms/djangoapps/ccx/tasks.py
+++ b/lms/djangoapps/ccx/tasks.py
@@ -7,7 +7,6 @@
from ccx_keys.locator import CCXLocator
from django.dispatch import receiver
-from edx_django_utils.monitoring import set_code_owner_attribute
from opaque_keys import InvalidKeyError
from opaque_keys.edx.locator import CourseLocator
@@ -28,7 +27,6 @@ def course_published_handler(sender, course_key, **kwargs): # pylint: disable=u
@CELERY_APP.task
-@set_code_owner_attribute
def send_ccx_course_published(course_key):
"""
Find all CCX derived from this course, and send course published event for them.
diff --git a/lms/djangoapps/certificates/tasks.py b/lms/djangoapps/certificates/tasks.py
index 93a7a05938b1..80c0fea7075d 100644
--- a/lms/djangoapps/certificates/tasks.py
+++ b/lms/djangoapps/certificates/tasks.py
@@ -9,7 +9,6 @@
from celery import shared_task
from celery_utils.persist_on_failure import LoggedPersistOnFailureTask, LoggedTask
from django.contrib.auth import get_user_model
-from edx_django_utils.monitoring import set_code_owner_attribute
from opaque_keys.edx.keys import CourseKey
from lms.djangoapps.certificates.data import CertificateStatuses
@@ -27,7 +26,6 @@
@shared_task(
base=LoggedPersistOnFailureTask, bind=True, default_retry_delay=30, max_retries=2
)
-@set_code_owner_attribute
def generate_certificate(self, **kwargs): # pylint: disable=unused-argument
"""
Generates a certificate for a single user.
@@ -60,7 +58,6 @@ def generate_certificate(self, **kwargs): # pylint: disable=unused-argument
@shared_task(base=LoggedTask, ignore_result=True)
-@set_code_owner_attribute
def handle_modify_cert_template(options: Dict[str, Any]) -> None: # noqa: UP006
"""
Celery task to handle the modify_cert_template management command.
diff --git a/lms/djangoapps/course_home_api/tasks.py b/lms/djangoapps/course_home_api/tasks.py
index 39bc2bbb3c2a..06c883b094bd 100644
--- a/lms/djangoapps/course_home_api/tasks.py
+++ b/lms/djangoapps/course_home_api/tasks.py
@@ -5,7 +5,6 @@
from celery import shared_task
from django.contrib.auth import get_user_model
-from edx_django_utils.monitoring import set_code_owner_attribute
from eventtracking import tracker
from opaque_keys import InvalidKeyError
from opaque_keys.edx.keys import CourseKey
@@ -20,7 +19,6 @@
@shared_task
-@set_code_owner_attribute
def collect_progress_for_user_in_course(course_id: str, user_id: str) -> None:
"""
Celery task that retrieves a learner's progress in a given course.
diff --git a/lms/djangoapps/discussion/rest_api/tasks.py b/lms/djangoapps/discussion/rest_api/tasks.py
index 8fe8ee37dadb..943ec80466c6 100644
--- a/lms/djangoapps/discussion/rest_api/tasks.py
+++ b/lms/djangoapps/discussion/rest_api/tasks.py
@@ -5,7 +5,6 @@
from celery import shared_task
from django.contrib.auth import get_user_model
-from edx_django_utils.monitoring import set_code_owner_attribute
from eventtracking import tracker
from forum import api as forum_api
from opaque_keys.edx.locator import CourseKey
@@ -25,7 +24,6 @@
@shared_task
-@set_code_owner_attribute
def send_thread_created_notification(thread_id, course_key_str, user_id, notify_all_learners=False):
"""
Send notification when a new thread is created
@@ -49,7 +47,6 @@ def send_thread_created_notification(thread_id, course_key_str, user_id, notify_
@shared_task
-@set_code_owner_attribute
def send_response_notifications(thread_id, course_key_str, user_id, comment_id, parent_id=None):
"""
Send notifications to users who are subscribed to the thread.
@@ -68,7 +65,6 @@ def send_response_notifications(thread_id, course_key_str, user_id, comment_id,
@shared_task
-@set_code_owner_attribute
def send_response_endorsed_notifications(thread_id, response_id, course_key_str, endorsed_by):
"""
Send notifications when a response is marked answered/ endorsed
@@ -93,7 +89,6 @@ def send_response_endorsed_notifications(thread_id, response_id, course_key_str,
@shared_task
-@set_code_owner_attribute
def delete_course_post_for_user(user_id, username, course_ids, event_data=None):
"""
Deletes all posts for user in a course.
diff --git a/lms/djangoapps/discussion/tasks.py b/lms/djangoapps/discussion/tasks.py
index bcb59ffdae02..777c937ed990 100644
--- a/lms/djangoapps/discussion/tasks.py
+++ b/lms/djangoapps/discussion/tasks.py
@@ -15,7 +15,6 @@
from edx_ace.channel import ChannelType
from edx_ace.recipient import Recipient
from edx_ace.utils import date
-from edx_django_utils.monitoring import set_code_owner_attribute
from eventtracking import tracker
from opaque_keys.edx.keys import CourseKey
from six.moves.urllib.parse import urljoin
@@ -41,7 +40,6 @@
@shared_task(base=LoggedTask)
-@set_code_owner_attribute
def update_discussions_map(context):
"""
Updates the mapping between discussion_id to discussion block usage key
@@ -78,7 +76,6 @@ class CommentNotification(BaseMessageType):
@shared_task(base=LoggedTask)
-@set_code_owner_attribute
def send_ace_message(context): # pylint: disable=missing-function-docstring
context['course_id'] = CourseKey.from_string(context['course_id'])
@@ -119,7 +116,6 @@ def send_ace_message(context): # pylint: disable=missing-function-docstring
@shared_task(base=LoggedTask)
-@set_code_owner_attribute
def send_ace_message_for_reported_content(context): # pylint: disable=missing-function-docstring
context['course_id'] = CourseKey.from_string(context['course_id'])
context['course_name'] = modulestore().get_course(context['course_id']).display_name
diff --git a/lms/djangoapps/gating/tasks.py b/lms/djangoapps/gating/tasks.py
index d58767637e81..04bc0cbf6364 100644
--- a/lms/djangoapps/gating/tasks.py
+++ b/lms/djangoapps/gating/tasks.py
@@ -7,7 +7,6 @@
from celery import shared_task
from django.contrib.auth.models import User # pylint: disable=imported-auth-user
-from edx_django_utils.monitoring import set_code_owner_attribute
from opaque_keys.edx.keys import CourseKey, UsageKey
from lms.djangoapps.course_blocks.api import get_course_blocks
@@ -18,7 +17,6 @@
@shared_task
-@set_code_owner_attribute
def task_evaluate_subsection_completion_milestones(course_id, block_id, user_id):
"""
Updates users' milestones related to completion of a subsection.
diff --git a/lms/djangoapps/grades/tasks.py b/lms/djangoapps/grades/tasks.py
index fa6cc23817b0..f00bed8ab1ba 100644
--- a/lms/djangoapps/grades/tasks.py
+++ b/lms/djangoapps/grades/tasks.py
@@ -10,7 +10,6 @@
from django.core.exceptions import ValidationError
from django.db.utils import DatabaseError
from edx_django_utils.monitoring import (
- set_code_owner_attribute,
set_custom_attribute,
set_custom_attributes_for_course_key,
)
@@ -55,7 +54,6 @@
@shared_task(base=LoggedPersistOnFailureTask)
-@set_code_owner_attribute
def compute_all_grades_for_course(**kwargs):
"""
Compute grades for all students in the specified course.
@@ -88,7 +86,6 @@ def compute_all_grades_for_course(**kwargs):
time_limit=COURSE_GRADE_TIMEOUT_SECONDS,
rate_limit=settings.POLICY_CHANGE_TASK_RATE_LIMIT,
)
-@set_code_owner_attribute
def compute_grades_for_course_v2(self, **kwargs):
"""
Compute grades for a set of students in the specified course.
@@ -113,7 +110,6 @@ def compute_grades_for_course_v2(self, **kwargs):
@shared_task(base=LoggedPersistOnFailureTask)
-@set_code_owner_attribute
def compute_grades_for_course(course_key, offset, batch_size, **kwargs): # pylint: disable=unused-argument
"""
Compute and save grades for a set of students in the specified course.
@@ -141,7 +137,6 @@ def compute_grades_for_course(course_key, offset, batch_size, **kwargs): # pyli
max_retries=2,
default_retry_delay=RETRY_DELAY_SECONDS,
)
-@set_code_owner_attribute
def recalculate_course_and_subsection_grades_for_user(self, **kwargs): # pylint: disable=unused-argument
"""
Recalculates the course grade and all subsection grades
@@ -182,7 +177,6 @@ def recalculate_course_and_subsection_grades_for_user(self, **kwargs): # pylint
max_retries=2,
default_retry_delay=RETRY_DELAY_SECONDS
)
-@set_code_owner_attribute
def recalculate_subsection_grade_v3(self, **kwargs):
"""
Latest version of the recalculate_subsection_grade task. See docstring
diff --git a/lms/djangoapps/instructor/tasks.py b/lms/djangoapps/instructor/tasks.py
index 8265be3b1187..63fb95bcaf86 100644
--- a/lms/djangoapps/instructor/tasks.py
+++ b/lms/djangoapps/instructor/tasks.py
@@ -5,7 +5,6 @@
from celery import shared_task
from celery_utils.logged_task import LoggedTask
from django.core.exceptions import ObjectDoesNotExist
-from edx_django_utils.monitoring import set_code_owner_attribute
from opaque_keys import InvalidKeyError
from opaque_keys.edx.keys import UsageKey
from xblock.completable import XBlockCompletionMode
@@ -21,7 +20,6 @@
@shared_task(base=LoggedTask, ignore_result=True)
-@set_code_owner_attribute
def update_exam_completion_task(user_identifier: str, content_id: str, completion: float) -> None:
"""
Marks all completable children of content_id as complete for the user.
diff --git a/lms/djangoapps/instructor_task/tasks.py b/lms/djangoapps/instructor_task/tasks.py
index 5baee74adbbc..7de7e4fddf9f 100644
--- a/lms/djangoapps/instructor_task/tasks.py
+++ b/lms/djangoapps/instructor_task/tasks.py
@@ -25,7 +25,6 @@
from celery import shared_task
from django.utils.translation import gettext_noop
-from edx_django_utils.monitoring import set_code_owner_attribute
from lms.djangoapps.bulk_email.tasks import perform_delegate_email_batches
from lms.djangoapps.instructor_task.tasks_base import BaseInstructorTask
@@ -59,7 +58,6 @@
@shared_task(base=BaseInstructorTask)
-@set_code_owner_attribute
def rescore_problem(entry_id, xblock_instance_args):
"""Rescores a problem in a course, for all students or one specific student.
@@ -87,7 +85,6 @@ def rescore_problem(entry_id, xblock_instance_args):
@shared_task(base=BaseInstructorTask)
-@set_code_owner_attribute
def override_problem_score(entry_id, xblock_instance_args):
"""
Overrides a specific learner's score on a problem.
@@ -101,7 +98,6 @@ def override_problem_score(entry_id, xblock_instance_args):
@shared_task(base=BaseInstructorTask)
-@set_code_owner_attribute
def reset_problem_attempts(entry_id, xblock_instance_args):
"""Resets problem attempts to zero for a particular problem for all students in a course.
@@ -124,7 +120,6 @@ def reset_problem_attempts(entry_id, xblock_instance_args):
@shared_task(base=BaseInstructorTask)
-@set_code_owner_attribute
def delete_problem_state(entry_id, xblock_instance_args):
"""Deletes problem state entirely for all students on a particular problem in a course.
@@ -147,7 +142,6 @@ def delete_problem_state(entry_id, xblock_instance_args):
@shared_task(base=BaseInstructorTask)
-@set_code_owner_attribute
def send_bulk_course_email(entry_id, _xblock_instance_args):
"""Sends emails to recipients enrolled in a course.
@@ -172,7 +166,6 @@ def send_bulk_course_email(entry_id, _xblock_instance_args):
name='lms.djangoapps.instructor_task.tasks.calculate_problem_responses_csv.v2',
base=BaseInstructorTask,
)
-@set_code_owner_attribute
def calculate_problem_responses_csv(entry_id, xblock_instance_args):
"""
Compute student answers to a given problem and upload the CSV to
@@ -185,7 +178,6 @@ def calculate_problem_responses_csv(entry_id, xblock_instance_args):
@shared_task(base=BaseInstructorTask)
-@set_code_owner_attribute
def calculate_grades_csv(entry_id, xblock_instance_args):
"""
Grade a course and push the results to an S3 bucket for download.
@@ -202,7 +194,6 @@ def calculate_grades_csv(entry_id, xblock_instance_args):
@shared_task(base=BaseInstructorTask)
-@set_code_owner_attribute
def calculate_problem_grade_report(entry_id, xblock_instance_args):
"""
Generate a CSV for a course containing all students' problem
@@ -220,7 +211,6 @@ def calculate_problem_grade_report(entry_id, xblock_instance_args):
@shared_task(base=BaseInstructorTask)
-@set_code_owner_attribute
def calculate_students_features_csv(entry_id, xblock_instance_args):
"""
Compute student profile information for a course and upload the
@@ -233,7 +223,6 @@ def calculate_students_features_csv(entry_id, xblock_instance_args):
@shared_task(base=BaseInstructorTask)
-@set_code_owner_attribute
def course_survey_report_csv(entry_id, xblock_instance_args):
"""
Compute the survey report for a course and upload the
@@ -246,7 +235,6 @@ def course_survey_report_csv(entry_id, xblock_instance_args):
@shared_task(base=BaseInstructorTask)
-@set_code_owner_attribute
def proctored_exam_results_csv(entry_id, xblock_instance_args):
"""
Compute proctored exam results report for a course and upload the
@@ -258,7 +246,6 @@ def proctored_exam_results_csv(entry_id, xblock_instance_args):
@shared_task(base=BaseInstructorTask)
-@set_code_owner_attribute
def calculate_may_enroll_csv(entry_id, xblock_instance_args):
"""
Compute information about invited students who have not enrolled
@@ -272,7 +259,6 @@ def calculate_may_enroll_csv(entry_id, xblock_instance_args):
@shared_task(base=BaseInstructorTask)
-@set_code_owner_attribute
def calculate_inactive_enrolled_students_info_csv(entry_id, xblock_instance_args):
"""
Compute information about invited students who have not enrolled
@@ -286,7 +272,6 @@ def calculate_inactive_enrolled_students_info_csv(entry_id, xblock_instance_args
@shared_task(base=BaseInstructorTask)
-@set_code_owner_attribute
def generate_certificates(entry_id, xblock_instance_args):
"""
Grade students and generate certificates.
@@ -303,7 +288,6 @@ def generate_certificates(entry_id, xblock_instance_args):
@shared_task(base=BaseInstructorTask)
-@set_code_owner_attribute
def cohort_students(entry_id, xblock_instance_args):
"""
Cohort students in bulk, and upload the results.
@@ -316,7 +300,6 @@ def cohort_students(entry_id, xblock_instance_args):
@shared_task(base=BaseInstructorTask)
-@set_code_owner_attribute
def generate_anonymous_ids_for_course(entry_id, xblock_instance_args):
"""
Generate a CSV of anonymize IDs for enrolled learner for course.
@@ -329,7 +312,6 @@ def generate_anonymous_ids_for_course(entry_id, xblock_instance_args):
@shared_task(base=BaseInstructorTask)
-@set_code_owner_attribute
def export_ora2_data(entry_id, xblock_instance_args):
"""
Generate a CSV of ora2 responses and push it to S3.
@@ -340,7 +322,6 @@ def export_ora2_data(entry_id, xblock_instance_args):
@shared_task(base=BaseInstructorTask)
-@set_code_owner_attribute
def export_ora2_submission_files(entry_id, xblock_instance_args):
"""
Download all submission files, generate csv downloads list,
@@ -352,7 +333,6 @@ def export_ora2_submission_files(entry_id, xblock_instance_args):
@shared_task(base=BaseInstructorTask)
-@set_code_owner_attribute
def export_ora2_summary(entry_id, xblock_instance_args):
"""
Generate a CSV of ora2/student summaries and push it to S3.
@@ -363,7 +343,6 @@ def export_ora2_summary(entry_id, xblock_instance_args):
@shared_task(base=BaseInstructorTask)
-@set_code_owner_attribute
def student_enrollment_batch(entry_id, xblock_instance_args):
"""
Process student enrollment/unenrollment operations in batch asynchronously.
diff --git a/lms/djangoapps/lti_provider/tasks.py b/lms/djangoapps/lti_provider/tasks.py
index 365db52614b2..74537e40d965 100644
--- a/lms/djangoapps/lti_provider/tasks.py
+++ b/lms/djangoapps/lti_provider/tasks.py
@@ -6,7 +6,6 @@
import logging
from django.contrib.auth.models import User # pylint: disable=imported-auth-user
-from edx_django_utils.monitoring import set_code_owner_attribute
from opaque_keys.edx.keys import CourseKey
import lms.djangoapps.lti_provider.outcomes as outcomes
@@ -19,7 +18,6 @@
@CELERY_APP.task(name='lms.djangoapps.lti_provider.tasks.send_composite_outcome')
-@set_code_owner_attribute
def send_composite_outcome(user_id, course_id, assignment_id, version):
"""
Calculate and transmit the score for a composite module (such as a
@@ -69,7 +67,6 @@ def send_composite_outcome(user_id, course_id, assignment_id, version):
@CELERY_APP.task
-@set_code_owner_attribute
def send_leaf_outcome(assignment_id, points_earned, points_possible):
"""
Calculate and transmit the score for a single problem. This method assumes
diff --git a/lms/djangoapps/monitoring/README.rst b/lms/djangoapps/monitoring/README.rst
index f61781c62ed4..702c50e9e4ea 100644
--- a/lms/djangoapps/monitoring/README.rst
+++ b/lms/djangoapps/monitoring/README.rst
@@ -1,13 +1,6 @@
Monitoring
==========
-This directory contains utilities for adding a code_owner custom attribute for help with split-ownership of the LMS.
-
-For details on the decision to implement the code_owner custom attribute, see:
-lms/djangoapps/monitoring/docs/decisions/0001-monitoring-by-code-owner.rst
-
-Originally, this directory contained the ``CodeOwnerMetricMiddleware``, but that has since been moved to
-https://github.com/openedx/edx-django-utils/tree/master/edx_django_utils/monitoring/code_owner
-and renamed ``CodeOwnerMonitoringMiddleware``.
-
-This directory continues to contain scripts that can help generate the appropriate ownership mappings for the LMS.
+This directory previously contained utilities for the code_owner custom attribute
+for split-ownership monitoring of the LMS. That functionality has been removed as
+part of DEPR cleanup (openedx/edx-django-utils#469).
diff --git a/lms/djangoapps/monitoring/docs/decisions/0001-monitoring-by-code-owner.rst b/lms/djangoapps/monitoring/docs/decisions/0001-monitoring-by-code-owner.rst
deleted file mode 100644
index 6425e8e12a3f..000000000000
--- a/lms/djangoapps/monitoring/docs/decisions/0001-monitoring-by-code-owner.rst
+++ /dev/null
@@ -1,50 +0,0 @@
-Monitoring by Code Owner
-************************
-
-Status
-======
-
-Accepted
-
-Context
-=======
-
-It is currently difficult for different teams to have team-based on-calls rotations, alerting and monitoring for various parts of the edx-platform (specifically LMS).
-
-Decision
-========
-
-We will implement a custom attribute "code_owner" that can be used in NewRelic (or other monitoring solutions that are made pluggable).
-
-The new custom attribute makes it simple to query NewRelic for all Transactions or TransactionErrors that are associated with requests with a specific owner. This enables a team to quickly identify data that they own, for use in NewRelic alerts or NewRelic dashboards.
-
-To minimize maintenance, the value of the "code_owner" attribute will be populated using the source-of-truth of ownership of various parts of edx-platform.
-
-See `Rejected Alternatives`_ for details of the decision **not** to split the NewRelic application into multiple NewRelic applications.
-
-Note: "owner" is a MySql reserved word, which NewRelic cautions against using, so we are using "code_owner".
-
-Consequences
-============
-
-This attribute should be quickly available for use with custom alerts and custom dashboards.
-
-In the future, this attribute could potentially be added to logging as well.
-
-Rejected Alternatives
-=====================
-
-Splitting the NewRelic application
-----------------------------------
-
-The edx-platform (LMS) NewRelic application could have been split into multiple applications. This would have had the benefit of getting the out-of-the-box APM Dashboards for free.
-
-We decided against this alternative because:
-
-* To enable this solution, we would need to disable gunicorn instrumentation, and this instrumentation has proved to be valuable for understanding certain types of production issues.
-* Splitting the app may make it more difficult to pinpoint the source of any problem that affects multiple applications.
-* The application splitting depends on a slight "hack" from NewRelic, by resetting the application name for each path.
-
- * This "hack" goes against the grain of NewRelic's typical recommendations, so there could be unknown pitfalls.
- * The mapping of request path to owner would require additional maintenance.
- * Processing time is **not** accounted for in the NewRelic transaction time, because any processing required takes place before the NewRelic transaction gets started.
diff --git a/lms/djangoapps/monitoring/scripts/clean_unmapped_view_modules.py b/lms/djangoapps/monitoring/scripts/clean_unmapped_view_modules.py
deleted file mode 100644
index 77fb5fcf9c99..000000000000
--- a/lms/djangoapps/monitoring/scripts/clean_unmapped_view_modules.py
+++ /dev/null
@@ -1,74 +0,0 @@
-"""
-Provided a CSV of data from our monitoring system, this script outputs a unique and clean
-set of apps of unmapped view_func_modules.
-
-Context: This script was useful when first introducing ownership mapping and we had many
-apps from 3rd-party dependencies that were missed. At this point, we'd probably only
-expect 0-2 new unmapped apps, which could be cleaned manually very quickly without this
-script.
-
-Sample usage::
-
- python lms/djangoapps/monitoring/scripts/clean_unmapped_view_modules.py --unmapped-csv "unmapped-apps.csv"
-
-Or for more details::
-
- python lms/djangoapps/monitoring/scripts/clean_unmapped_view_modules.py --help
-
-
-"""
-import csv
-
-import click
-
-
-@click.command()
-@click.option(
- '--unmapped-csv',
- help="File name of .csv file with unmapped edx-platform view modules.",
- required=True
-)
-def main(unmapped_csv):
- """
- Reads CSV of unmapped view_func_modules and outputs a clean list of apps to map.
-
- NewRelic Insights Query to create CSV of unmapped modules:
-
- \b
- SELECT count(view_func_module) FROM Transaction
- WHERE code_owner is null FACET view_func_module
- SINCE 1 week ago
- LIMIT 50
-
- \b
- * Increase or decrease SINCE clause as necessary based on when the mappings were last updated.
- * Save results as CSV for use in script
-
- Sample CSV input::
-
- \b
- View Func Module,View Func Modules
- enterprise.api.v1.views,1542
- edx_proctoring.views,116
- social_django.views,53
-
- Script removes duplicates in addition to providing sorted list of plain app names.
-
- """
- with open(unmapped_csv) as file:
- csv_data = file.read()
- reader = csv.DictReader(csv_data.splitlines())
-
- clean_apps_set = set()
- for row in reader:
- path = row.get('View Func Module')
- path_parts = path.split('.')
- clean_apps_set.add(path_parts[0])
-
- print('# Move into generate_code_owner_mappings.py and complete mappings.')
- for clean_app in sorted(clean_apps_set):
- print(clean_app)
-
-
-if __name__ == "__main__":
- main() # pylint: disable=no-value-for-parameter
diff --git a/lms/djangoapps/program_enrollments/tasks.py b/lms/djangoapps/program_enrollments/tasks.py
index 300abc4d1054..46fc236e9b22 100644
--- a/lms/djangoapps/program_enrollments/tasks.py
+++ b/lms/djangoapps/program_enrollments/tasks.py
@@ -7,7 +7,6 @@
from celery import shared_task
from celery_utils.logged_task import LoggedTask
from django.utils import timezone
-from edx_django_utils.monitoring import set_code_owner_attribute
from lms.djangoapps.program_enrollments.models import ProgramCourseEnrollment, ProgramEnrollment
@@ -15,7 +14,6 @@
@shared_task(base=LoggedTask)
-@set_code_owner_attribute
def expire_waiting_enrollments(expiration_days):
"""
Remove all ProgramEnrollments and related ProgramCourseEnrollments for
diff --git a/lms/djangoapps/support/tasks.py b/lms/djangoapps/support/tasks.py
index b30e92a11a8b..083866958a3c 100644
--- a/lms/djangoapps/support/tasks.py
+++ b/lms/djangoapps/support/tasks.py
@@ -8,7 +8,6 @@
from django.contrib.sites.models import Site
from edx_ace import ace
from edx_ace.recipient import Recipient
-from edx_django_utils.monitoring import set_code_owner_attribute
from common.djangoapps.student.models.course_enrollment import CourseEnrollment
from common.djangoapps.student.models.user import get_user_by_username_or_email
@@ -45,7 +44,6 @@ def get_blocks(course):
@shared_task
-@set_code_owner_attribute
def send_reset_course_completion_email(course, user):
"""
Sends email to a learner when whole course reset is complete.
@@ -85,7 +83,6 @@ def send_reset_course_completion_email(course, user):
@shared_task
-@set_code_owner_attribute
def reset_student_course(course_id, learner_email, reset_by_user_email):
"""
Resets a learner's course progress
diff --git a/lms/djangoapps/verify_student/tasks.py b/lms/djangoapps/verify_student/tasks.py
index ca0548cdd082..454f28960347 100644
--- a/lms/djangoapps/verify_student/tasks.py
+++ b/lms/djangoapps/verify_student/tasks.py
@@ -11,7 +11,6 @@
from celery.states import FAILURE
from django.conf import settings
from django.core.mail import EmailMessage
-from edx_django_utils.monitoring import set_code_owner_attribute
from common.djangoapps.edxmako.shortcuts import render_to_string
from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers
@@ -73,7 +72,6 @@ def after_return(self, status, retval, task_id, args, kwargs, einfo):
@shared_task
-@set_code_owner_attribute
def send_verification_status_email(context):
"""
Spins a task to send verification status email to the learner
@@ -100,7 +98,6 @@ def send_verification_status_email(context):
default_retry_delay=settings.SOFTWARE_SECURE_REQUEST_RETRY_DELAY,
max_retries=settings.SOFTWARE_SECURE_RETRY_MAX_ATTEMPTS,
)
-@set_code_owner_attribute
def send_request_to_ss_for_user(self, user_verification_id, copy_id_photo_from):
"""
Assembles a submission to Software Secure.
diff --git a/lms/envs/common.py b/lms/envs/common.py
index e8a185c1d49c..a6ea409164e7 100644
--- a/lms/envs/common.py
+++ b/lms/envs/common.py
@@ -1210,7 +1210,6 @@
# Various monitoring middleware
'edx_django_utils.monitoring.CachedCustomMonitoringMiddleware',
- 'edx_django_utils.monitoring.CodeOwnerMonitoringMiddleware',
'edx_django_utils.monitoring.CookieMonitoringMiddleware',
'edx_django_utils.monitoring.DeploymentMonitoringMiddleware',
'edx_django_utils.monitoring.FrontendMonitoringMiddleware',
diff --git a/openedx/core/djangoapps/bookmarks/tasks.py b/openedx/core/djangoapps/bookmarks/tasks.py
index a35affb05180..91b405723dcc 100644
--- a/openedx/core/djangoapps/bookmarks/tasks.py
+++ b/openedx/core/djangoapps/bookmarks/tasks.py
@@ -7,7 +7,6 @@
from celery import shared_task
from django.db import transaction
-from edx_django_utils.monitoring import set_code_owner_attribute
from opaque_keys.edx.keys import CourseKey
from xmodule.modulestore.django import modulestore
@@ -145,7 +144,6 @@ def update_block_cache_if_needed(block_cache, block_data):
@shared_task(name='openedx.core.djangoapps.bookmarks.tasks.update_xblocks_cache')
-@set_code_owner_attribute
def update_xblocks_cache(course_id):
"""
Update the XBlocks cache for a course.
diff --git a/openedx/core/djangoapps/ccxcon/tasks.py b/openedx/core/djangoapps/ccxcon/tasks.py
index 12a8cc7d9f33..77ecc3505cd7 100644
--- a/openedx/core/djangoapps/ccxcon/tasks.py
+++ b/openedx/core/djangoapps/ccxcon/tasks.py
@@ -5,7 +5,6 @@
from celery import shared_task
from celery.utils.log import get_task_logger
-from edx_django_utils.monitoring import set_code_owner_attribute
from opaque_keys.edx.keys import CourseKey
from requests.exceptions import ( # pylint: disable=redefined-builtin
ConnectionError,
@@ -20,7 +19,6 @@
@shared_task(name='openedx.core.djangoapps.ccxcon.tasks.update_ccxcon')
-@set_code_owner_attribute
def update_ccxcon(course_id, cur_retry=0):
"""
Pass through function to update course information on CCXCon.
diff --git a/openedx/core/djangoapps/content/block_structure/tasks.py b/openedx/core/djangoapps/content/block_structure/tasks.py
index 4490650fe06e..f5cd4e347fa4 100644
--- a/openedx/core/djangoapps/content/block_structure/tasks.py
+++ b/openedx/core/djangoapps/content/block_structure/tasks.py
@@ -7,7 +7,6 @@
from celery import shared_task
from django.conf import settings
-from edx_django_utils.monitoring import set_code_owner_attribute
from edxval.api import ValInternalError
from lxml.etree import XMLSyntaxError
from opaque_keys.edx.keys import CourseKey
@@ -36,7 +35,6 @@ def block_structure_task(**kwargs):
@block_structure_task()
-@set_code_owner_attribute
def update_course_in_cache_v2(self, **kwargs):
"""
Updates the course blocks (mongo -> BlockStructure) for the specified course.
@@ -47,7 +45,6 @@ def update_course_in_cache_v2(self, **kwargs):
@block_structure_task()
-@set_code_owner_attribute
def update_course_in_cache(self, course_id):
"""
Updates the course blocks (mongo -> BlockStructure) for the specified course.
@@ -63,7 +60,6 @@ def _update_course_in_cache(self, **kwargs):
@block_structure_task()
-@set_code_owner_attribute
def get_course_in_cache_v2(self, **kwargs):
"""
Gets the course blocks for the specified course, updating the cache if needed.
@@ -74,7 +70,6 @@ def get_course_in_cache_v2(self, **kwargs):
@block_structure_task()
-@set_code_owner_attribute
def get_course_in_cache(self, course_id):
"""
Gets the course blocks for the specified course, updating the cache if needed.
diff --git a/openedx/core/djangoapps/content/course_overviews/tasks.py b/openedx/core/djangoapps/content/course_overviews/tasks.py
index 155a2011d40c..bf1fe0818816 100644
--- a/openedx/core/djangoapps/content/course_overviews/tasks.py
+++ b/openedx/core/djangoapps/content/course_overviews/tasks.py
@@ -5,7 +5,6 @@
from celery import shared_task
from celery_utils.persist_on_failure import LoggedPersistOnFailureTask
from django.conf import settings
-from edx_django_utils.monitoring import set_code_owner_attribute
from opaque_keys.edx.keys import CourseKey
from openedx.core.djangoapps.content.course_overviews.models import CourseOverview
@@ -58,7 +57,6 @@ def enqueue_async_course_overview_update_tasks( # pylint: disable=missing-funct
@shared_task(base=LoggedPersistOnFailureTask)
-@set_code_owner_attribute
def async_course_overview_update(*args, **kwargs):
course_keys = [CourseKey.from_string(arg) for arg in args]
CourseOverview.update_select_courses(course_keys, force_update=kwargs['force_update'])
diff --git a/openedx/core/djangoapps/content/search/tasks.py b/openedx/core/djangoapps/content/search/tasks.py
index a95bedb062db..2245cc85fa76 100644
--- a/openedx/core/djangoapps/content/search/tasks.py
+++ b/openedx/core/djangoapps/content/search/tasks.py
@@ -8,7 +8,6 @@
from celery import shared_task
from celery_utils.logged_task import LoggedTask
-from edx_django_utils.monitoring import set_code_owner_attribute
from meilisearch.errors import MeilisearchError
from opaque_keys.edx.keys import CourseKey, UsageKey
from opaque_keys.edx.locator import (
@@ -24,7 +23,6 @@
@shared_task(base=LoggedTask, autoretry_for=(MeilisearchError, ConnectionError))
-@set_code_owner_attribute
def upsert_xblock_index_doc(usage_key_str: str, recursive: bool) -> None:
"""
Celery task to update the content index document for an XBlock
@@ -37,7 +35,6 @@ def upsert_xblock_index_doc(usage_key_str: str, recursive: bool) -> None:
@shared_task(base=LoggedTask, autoretry_for=(MeilisearchError, ConnectionError))
-@set_code_owner_attribute
def upsert_course_blocks_docs(course_key_str: str) -> None:
"""
Celery task to update the content index document for all XBlocks in a course.
@@ -50,7 +47,6 @@ def upsert_course_blocks_docs(course_key_str: str) -> None:
@shared_task(base=LoggedTask, autoretry_for=(MeilisearchError, ConnectionError))
-@set_code_owner_attribute
def delete_xblock_index_doc(usage_key_str: str) -> None:
"""
Celery task to delete the content index document for an XBlock
@@ -64,7 +60,6 @@ def delete_xblock_index_doc(usage_key_str: str) -> None:
@shared_task(base=LoggedTask, autoretry_for=(MeilisearchError, ConnectionError))
-@set_code_owner_attribute
def upsert_library_block_index_doc(usage_key_str: str) -> None:
"""
Celery task to update the content index document for a library block
@@ -77,7 +72,6 @@ def upsert_library_block_index_doc(usage_key_str: str) -> None:
@shared_task(base=LoggedTask, autoretry_for=(MeilisearchError, ConnectionError))
-@set_code_owner_attribute
def delete_library_block_index_doc(usage_key_str: str) -> None:
"""
Celery task to delete the content index document for a library block
@@ -90,7 +84,6 @@ def delete_library_block_index_doc(usage_key_str: str) -> None:
@shared_task(base=LoggedTask, autoretry_for=(MeilisearchError, ConnectionError))
-@set_code_owner_attribute
def update_content_library_index_docs(library_key_str: str, full_index: bool = False) -> None:
"""
Celery task to update the content index documents for all library blocks in a library
@@ -104,7 +97,6 @@ def update_content_library_index_docs(library_key_str: str, full_index: bool = F
@shared_task(base=LoggedTask, autoretry_for=(MeilisearchError, ConnectionError))
-@set_code_owner_attribute
def update_library_collection_index_doc(collection_key_str: str) -> None:
"""
Celery task to update the content index document for a library collection
@@ -118,7 +110,6 @@ def update_library_collection_index_doc(collection_key_str: str) -> None:
@shared_task(base=LoggedTask, autoretry_for=(MeilisearchError, ConnectionError))
-@set_code_owner_attribute
def update_library_components_collections(collection_key_str: str) -> None:
"""
Celery task to update the "collections" field for components in the given content library collection.
@@ -132,7 +123,6 @@ def update_library_components_collections(collection_key_str: str) -> None:
@shared_task(base=LoggedTask, autoretry_for=(MeilisearchError, ConnectionError))
-@set_code_owner_attribute
def update_library_containers_collections(collection_key_str: str) -> None:
"""
Celery task to update the "collections" field for containers in the given content library collection.
@@ -146,7 +136,6 @@ def update_library_containers_collections(collection_key_str: str) -> None:
@shared_task(base=LoggedTask, autoretry_for=(MeilisearchError, ConnectionError))
-@set_code_owner_attribute
def update_library_container_index_doc(container_key_str: str) -> None:
"""
Celery task to update the content index document for a library container
@@ -160,7 +149,6 @@ def update_library_container_index_doc(container_key_str: str) -> None:
@shared_task(base=LoggedTask, autoretry_for=(MeilisearchError, ConnectionError))
-@set_code_owner_attribute
def delete_library_container_index_doc(container_key_str: str) -> None:
"""
Celery task to delete the content index document for a library block
@@ -173,7 +161,6 @@ def delete_library_container_index_doc(container_key_str: str) -> None:
@shared_task(base=LoggedTask, autoretry_for=(MeilisearchError, ConnectionError))
-@set_code_owner_attribute
def delete_course_index_docs(course_key_str: str) -> None:
"""
Celery task to delete the content index documents for a Course
@@ -192,7 +179,6 @@ def delete_course_index_docs(course_key_str: str) -> None:
max_retries=3,
retry_backoff=True,
)
-@set_code_owner_attribute
def rebuild_index_incremental() -> None:
"""
Celery task to incrementally populate the Studio Meilisearch index.
diff --git a/openedx/core/djangoapps/content_libraries/tasks.py b/openedx/core/djangoapps/content_libraries/tasks.py
index daea33a8ced6..ef84f77dec1f 100644
--- a/openedx/core/djangoapps/content_libraries/tasks.py
+++ b/openedx/core/djangoapps/content_libraries/tasks.py
@@ -35,8 +35,6 @@
from django.core.files.base import ContentFile
from django.core.serializers.json import DjangoJSONEncoder
from edx_django_utils.monitoring import (
- set_code_owner_attribute,
- set_code_owner_attribute_from_module,
set_custom_attribute,
)
from opaque_keys import OpaqueKey
@@ -92,7 +90,6 @@
@shared_task(base=LoggedTask)
-@set_code_owner_attribute
def send_change_events_for_modified_entities(
learning_package_id: LearningPackage.ID,
change_list: list[dict], # we want list[ChangeLogRecordData], but that's not JSON serializable, so use dicts
@@ -228,7 +225,6 @@ def emit_collections_updated(library: ContentLibrary, entity_ids: list[Publishab
@shared_task(base=LoggedTask)
-@set_code_owner_attribute
def check_container_content_changes(
container_key_str: str,
old_version_id: int | None,
@@ -298,7 +294,6 @@ def check_container_content_changes(
@shared_task(base=LoggedTask)
-@set_code_owner_attribute
def send_collections_changed_events(
publishable_entity_ids: list[PublishableEntity.ID],
learning_package_id: LearningPackage.ID,
@@ -344,7 +339,6 @@ def send_collections_changed_events(
@shared_task(base=LoggedTask)
-@set_code_owner_attribute
def send_events_after_publish(publish_log_id: int, library_key_str: str) -> None:
"""
Send events to trigger actions like updating the search index, after we've
@@ -440,7 +434,6 @@ def generate_name(cls, arguments_dict) -> str:
return f'Updating {key} from library'
-# Note: The decorator @set_code_owner_attribute cannot be used here because the UserTaskMixin does stack
# inspection and can't handle additional decorators. So, wet set the code_owner attribute in the tasks' bodies instead.
@shared_task(base=LibrarySyncChildrenTask, bind=True)
@@ -456,7 +449,6 @@ def sync_from_library(
FIXME: this is related to legacy modulestore libraries and shouldn't be part of the
openedx.core.djangoapps.content_libraries app, which is the app for v2 libraries.
"""
- set_code_owner_attribute_from_module(__name__)
store = modulestore()
dest_block = store.get_item(BlockUsageLocator.from_string(dest_block_id))
_sync_children(
@@ -481,7 +473,6 @@ def duplicate_children(
FIXME: this is related to legacy modulestore libraries and shouldn't be part of the
openedx.core.djangoapps.content_libraries app, which is the app for v2 libraries.
"""
- set_code_owner_attribute_from_module(__name__)
store = modulestore()
# First, populate the destination block with children imported from the library.
# It's important that _sync_children does this at the currently-set version of the dest library
@@ -604,7 +595,6 @@ def generate_name(cls, arguments_dict) -> str:
@shared_task(base=LibraryBackupTask, bind=True)
-# Note: The decorator @set_code_owner_attribute cannot be used here because the UserTaskMixin
# does stack inspection and can't handle additional decorators.
def backup_library(self, user_id: int, library_key_str: str) -> None:
"""
@@ -616,7 +606,6 @@ def backup_library(self, user_id: int, library_key_str: str) -> None:
- Failed: Task failed and the export did not complete.
"""
ensure_cms("backup_library may only be executed in a CMS context")
- set_code_owner_attribute_from_module(__name__)
library_key = LibraryLocatorV2.from_string(library_key_str)
try:
@@ -721,7 +710,6 @@ def restore_library(self, user_id, storage_path):
Restore a learning package from a backup file.
"""
ensure_cms("restore_library may only be executed in a CMS context")
- set_code_owner_attribute_from_module(__name__)
TASK_LOGGER.info('Starting restore of learning package from %s', storage_path)
diff --git a/openedx/core/djangoapps/content_staging/tasks.py b/openedx/core/djangoapps/content_staging/tasks.py
index d676ad6acbcc..377ee5393919 100644
--- a/openedx/core/djangoapps/content_staging/tasks.py
+++ b/openedx/core/djangoapps/content_staging/tasks.py
@@ -7,7 +7,6 @@
from celery import shared_task
from celery_utils.logged_task import LoggedTask
-from edx_django_utils.monitoring import set_code_owner_attribute
from .data import CLIPBOARD_PURPOSE
from .models import StagedContent
@@ -16,7 +15,6 @@
@shared_task(base=LoggedTask)
-@set_code_owner_attribute
def delete_expired_clipboards(staged_content_ids: list[StagedContent.ID]):
"""
A Celery task to delete StagedContent clipboard entries that are no longer
diff --git a/openedx/core/djangoapps/content_tagging/tasks.py b/openedx/core/djangoapps/content_tagging/tasks.py
index 8f67f737c2d3..4a9930907f98 100644
--- a/openedx/core/djangoapps/content_tagging/tasks.py
+++ b/openedx/core/djangoapps/content_tagging/tasks.py
@@ -9,7 +9,6 @@
from celery_utils.logged_task import LoggedTask
from django.conf import settings
from django.contrib.auth import get_user_model
-from edx_django_utils.monitoring import set_code_owner_attribute
from opaque_keys.edx.keys import CourseKey, UsageKey
from opaque_keys.edx.locator import LibraryUsageLocatorV2
from openedx_tagging.models import Taxonomy
@@ -59,7 +58,6 @@ def _delete_tags(content_object: ContentKey) -> None:
@shared_task(base=LoggedTask)
-@set_code_owner_attribute
def update_course_tags(course_key_str: str) -> bool:
"""
Updates the automatically-managed tags for a course
@@ -85,7 +83,6 @@ def update_course_tags(course_key_str: str) -> bool:
@shared_task(base=LoggedTask)
-@set_code_owner_attribute
def delete_course_tags(course_key_str: str) -> bool:
"""
Delete the tags for a Course (when the course itself has been deleted).
@@ -107,7 +104,6 @@ def delete_course_tags(course_key_str: str) -> bool:
@shared_task(base=LoggedTask)
-@set_code_owner_attribute
def update_xblock_tags(usage_key_str: str) -> bool:
"""
Updates the automatically-managed tags for a XBlock
@@ -138,7 +134,6 @@ def update_xblock_tags(usage_key_str: str) -> bool:
@shared_task(base=LoggedTask)
-@set_code_owner_attribute
def delete_xblock_tags(usage_key_str: str) -> bool:
"""
Delete the tags for a XBlock (when the XBlock itself is deleted).
@@ -160,7 +155,6 @@ def delete_xblock_tags(usage_key_str: str) -> bool:
@shared_task(base=LoggedTask)
-@set_code_owner_attribute
def update_library_block_tags(usage_key_str: str, language_code: str) -> bool:
"""
Updates the automatically-managed tags for a content library block
@@ -183,7 +177,6 @@ def update_library_block_tags(usage_key_str: str, language_code: str) -> bool:
@shared_task(base=LoggedTask)
-@set_code_owner_attribute
def delete_library_block_tags(usage_key_str: str) -> bool:
"""
Delete the tags for a Library Block (when the Library Block itself is deleted).
diff --git a/openedx/core/djangoapps/course_apps/tasks.py b/openedx/core/djangoapps/course_apps/tasks.py
index 1448c6e3dfff..64e287510a02 100644
--- a/openedx/core/djangoapps/course_apps/tasks.py
+++ b/openedx/core/djangoapps/course_apps/tasks.py
@@ -4,7 +4,6 @@
from celery import shared_task
from celery.utils.log import get_task_logger
-from edx_django_utils.monitoring import set_code_owner_attribute
from opaque_keys.edx.keys import CourseKey
from opaque_keys.edx.locator import LibraryLocator
@@ -16,7 +15,6 @@
@shared_task(name='openedx.core.djangoapps.course_apps.tasks.cache_all_course_apps_status')
-@set_code_owner_attribute
def cache_all_course_apps_status():
"""
Create CourseAppStatus entries for all course apps, across all courses to speed up queries.
@@ -31,7 +29,6 @@ def cache_all_course_apps_status():
@shared_task(name='openedx.core.djangoapps.course_apps.tasks.update_course_apps_status')
-@set_code_owner_attribute
def update_course_apps_status(course_key_str: str):
"""
Create CourseAppStatus entries for apps available for the specified course.
diff --git a/openedx/core/djangoapps/credentials/tasks/v1/tasks.py b/openedx/core/djangoapps/credentials/tasks/v1/tasks.py
index 953d138cbfc9..62eb4a35a661 100644
--- a/openedx/core/djangoapps/credentials/tasks/v1/tasks.py
+++ b/openedx/core/djangoapps/credentials/tasks/v1/tasks.py
@@ -11,7 +11,6 @@
from django.conf import settings
from django.contrib.auth import get_user_model
from django.contrib.sites.models import Site
-from edx_django_utils.monitoring import set_code_owner_attribute
from MySQLdb import OperationalError
from opaque_keys.edx.keys import CourseKey
@@ -52,7 +51,6 @@
retry_backoff_max=600,
retry_jitter=True,
)
-@set_code_owner_attribute
def send_grade_to_credentials(
self,
username,
@@ -100,7 +98,6 @@ def send_grade_to_credentials(
@shared_task(base=LoggedTask, ignore_result=True)
-@set_code_owner_attribute
def handle_notify_credentials(options, course_keys):
"""
Celery task to handle the notify_credentials management command. Finds the relevant cert and grade records, then
@@ -425,7 +422,6 @@ def is_course_run_in_a_program(course_run_key):
@shared_task(base=LoggedTask, ignore_result=True)
-@set_code_owner_attribute
def backfill_date_for_all_course_runs():
"""
This task enqueues an `update_certificate_available_date_on_course_update` subtask for each course overview in the
diff --git a/openedx/core/djangoapps/credit/tasks.py b/openedx/core/djangoapps/credit/tasks.py
index a8227e504352..1d012a27571a 100644
--- a/openedx/core/djangoapps/credit/tasks.py
+++ b/openedx/core/djangoapps/credit/tasks.py
@@ -6,7 +6,6 @@
from celery import shared_task
from celery.utils.log import get_task_logger
from django.conf import settings
-from edx_django_utils.monitoring import set_code_owner_attribute
from opaque_keys import InvalidKeyError
from opaque_keys.edx.keys import CourseKey, UsageKey
@@ -20,7 +19,6 @@
@shared_task(default_retry_delay=settings.CREDIT_TASK_DEFAULT_RETRY_DELAY, max_retries=settings.CREDIT_TASK_MAX_RETRIES)
-@set_code_owner_attribute
def update_credit_course_requirements(course_id):
"""
Updates course requirements table for a course.
diff --git a/openedx/core/djangoapps/discussions/tasks.py b/openedx/core/djangoapps/discussions/tasks.py
index 4599f33454d4..747a088fa098 100644
--- a/openedx/core/djangoapps/discussions/tasks.py
+++ b/openedx/core/djangoapps/discussions/tasks.py
@@ -4,7 +4,6 @@
import logging
from celery import shared_task
-from edx_django_utils.monitoring import set_code_owner_attribute
from opaque_keys.edx.keys import CourseKey
from openedx_events.learning.data import CourseDiscussionConfigurationData, DiscussionTopicContext
from openedx_events.learning.signals import COURSE_DISCUSSIONS_CHANGED
@@ -20,7 +19,6 @@
@shared_task
-@set_code_owner_attribute
def update_discussions_settings_from_course_task(course_key_str: str, discussable_units=None):
"""
Celery task that creates or updates discussions settings for a course.
diff --git a/openedx/core/djangoapps/heartbeat/tasks.py b/openedx/core/djangoapps/heartbeat/tasks.py
index 0c18560755ef..16d6293fc36c 100644
--- a/openedx/core/djangoapps/heartbeat/tasks.py
+++ b/openedx/core/djangoapps/heartbeat/tasks.py
@@ -4,10 +4,8 @@
from celery import shared_task
-from edx_django_utils.monitoring import set_code_owner_attribute
@shared_task
-@set_code_owner_attribute
def sample_task():
return True
diff --git a/openedx/core/djangoapps/notifications/email/tasks.py b/openedx/core/djangoapps/notifications/email/tasks.py
index ded2edb5178f..3d3703317f2d 100644
--- a/openedx/core/djangoapps/notifications/email/tasks.py
+++ b/openedx/core/djangoapps/notifications/email/tasks.py
@@ -14,7 +14,6 @@
from django.utils.translation import override as translation_override
from edx_ace import ace
from edx_ace.recipient import Recipient
-from edx_django_utils.monitoring import set_code_owner_attribute
from openedx.core.djangoapps.notifications.email_notifications import EmailCadence
from openedx.core.djangoapps.notifications.models import (
@@ -338,7 +337,6 @@ def _enqueue_bulk_digest_tasks(uids, ctype, dtime):
@shared_task(bind=True, ignore_result=True, max_retries=3, default_retry_delay=300)
-@set_code_owner_attribute
def send_user_digest_email_task(self, user_id, cadence_type):
"""
Delayed Celery task to send a digest email to a single user.
@@ -719,7 +717,6 @@ def add_to_existing_buffer(notification: Notification) -> None:
@shared_task(bind=True, max_retries=3, default_retry_delay=60)
-@set_code_owner_attribute
def send_buffered_digest(
self,
user_id: int,
diff --git a/openedx/core/djangoapps/notifications/tasks.py b/openedx/core/djangoapps/notifications/tasks.py
index 4dc8c76b1f6a..7cca299a28a5 100644
--- a/openedx/core/djangoapps/notifications/tasks.py
+++ b/openedx/core/djangoapps/notifications/tasks.py
@@ -9,7 +9,6 @@
from celery.utils.log import get_task_logger
from django.conf import settings
from django.core.exceptions import ValidationError
-from edx_django_utils.monitoring import set_code_owner_attribute
from opaque_keys.edx.keys import CourseKey
from openedx.core.djangoapps.notifications.audience_filters import NotificationFilter
@@ -46,7 +45,6 @@
@shared_task(ignore_result=True)
-@set_code_owner_attribute
def delete_notifications(kwargs):
"""
Delete notifications
@@ -72,7 +70,6 @@ def delete_notifications(kwargs):
@shared_task(ignore_result=True)
-@set_code_owner_attribute
def delete_expired_notifications():
"""
This task deletes all expired notifications
@@ -100,7 +97,6 @@ def delete_expired_notifications():
# pylint: disable=too-many-statements
@shared_task
-@set_code_owner_attribute
def send_notifications(user_ids, course_key: str, app_name, notification_type, context, content_url):
"""
Send notifications to the users.
diff --git a/openedx/core/djangoapps/programs/tasks.py b/openedx/core/djangoapps/programs/tasks.py
index 43dce6f392a3..4c25b0a6c455 100644
--- a/openedx/core/djangoapps/programs/tasks.py
+++ b/openedx/core/djangoapps/programs/tasks.py
@@ -13,7 +13,6 @@
from django.contrib.auth import get_user_model
from django.contrib.sites.models import Site
from django.core.exceptions import ObjectDoesNotExist
-from edx_django_utils.monitoring import set_code_owner_attribute
from opaque_keys import InvalidKeyError
from opaque_keys.edx.keys import CourseKey
from requests.exceptions import HTTPError
@@ -271,7 +270,6 @@ def post_course_certificate_configuration(client, cert_config, certificate_avail
retry_backoff_max=600,
retry_jitter=True,
)
-@set_code_owner_attribute
def award_program_certificates(self, username): # pylint: disable=too-many-statements
"""
This task is designed to be called whenever a student's completion status changes with respect to one or more
@@ -421,7 +419,6 @@ def award_program_certificates(self, username): # pylint: disable=too-many-stat
retry_backoff_max=600,
retry_jitter=True,
)
-@set_code_owner_attribute
def update_credentials_course_certificate_configuration_available_date(
self, course_key, certificate_available_date=None
):
@@ -474,7 +471,6 @@ def update_credentials_course_certificate_configuration_available_date(
retry_backoff_max=600,
retry_jitter=True,
)
-@set_code_owner_attribute
def award_course_certificate(self, username, course_run_key):
"""
This task is designed to be called whenever a student GeneratedCertificate is updated, or when a course-run's
@@ -592,7 +588,6 @@ def award_course_certificate(self, username, course_run_key):
retry_backoff_max=600,
retry_jitter=True,
)
-@set_code_owner_attribute
def revoke_program_certificates(self, username, course_key): # pylint: disable=too-many-statements
"""
This task is designed to be called whenever a student's course certificate is revoked.
@@ -725,7 +720,6 @@ def revoke_program_certificates(self, username, course_key): # pylint: disable=
retry_backoff_max=600,
retry_jitter=True,
)
-@set_code_owner_attribute
def update_certificate_available_date_on_course_update(self, course_key):
"""
This task is designed to be enqueued whenever a course run's Certificate Display Behavior (CDB) or Certificate
diff --git a/openedx/core/djangoapps/schedules/tasks.py b/openedx/core/djangoapps/schedules/tasks.py
index a7d92055fa37..8e67c210e03a 100644
--- a/openedx/core/djangoapps/schedules/tasks.py
+++ b/openedx/core/djangoapps/schedules/tasks.py
@@ -16,8 +16,6 @@
from edx_ace.message import Message
from edx_ace.utils.date import deserialize, serialize
from edx_django_utils.monitoring import (
- set_code_owner_attribute,
- set_code_owner_attribute_from_module,
set_custom_attribute,
)
from eventtracking import tracker
@@ -46,7 +44,6 @@
@shared_task(base=LoggedPersistOnFailureTask, bind=True, default_retry_delay=30)
-@set_code_owner_attribute
def update_course_schedules(self, **kwargs): # pylint: disable=missing-function-docstring
course_key = CourseKey.from_string(kwargs['course_id'])
new_start_date = deserialize(kwargs['new_start_date_str'])
@@ -105,7 +102,6 @@ class BinnedScheduleMessageBaseTask(ScheduleMessageBaseTask):
@classmethod
def enqueue(cls, site, current_date, day_offset, override_recipient_email=None, override_middlewares=None): # pylint: disable=missing-function-docstring
- set_code_owner_attribute_from_module(__name__)
current_date = resolvers._get_datetime_beginning_of_day(current_date) # pylint: disable=protected-access
if not cls.is_enqueue_enabled(site):
@@ -132,7 +128,6 @@ def enqueue(cls, site, current_date, day_offset, override_recipient_email=None,
def run( # pylint: disable=arguments-differ
self, site_id, target_day_str, day_offset, bin_num, override_recipient_email=None, override_middlewares=None,
):
- set_code_owner_attribute_from_module(__name__)
site = Site.objects.select_related('configuration').get(id=site_id)
middlewares = [self.class_from_classpath(cls) for cls in override_middlewares] if override_middlewares else None
with emulate_http_request(site=site, middleware_classes=middlewares) as request:
@@ -157,7 +152,6 @@ def class_from_classpath(self, class_path):
@shared_task(base=LoggedTask, ignore_result=True)
-@set_code_owner_attribute
def _recurring_nudge_schedule_send(site_id, msg_str):
_schedule_send(
msg_str,
@@ -168,7 +162,6 @@ def _recurring_nudge_schedule_send(site_id, msg_str):
@shared_task(base=LoggedTask, ignore_result=True)
-@set_code_owner_attribute
def _upgrade_reminder_schedule_send(site_id, msg_str):
_schedule_send(
msg_str,
@@ -179,7 +172,6 @@ def _upgrade_reminder_schedule_send(site_id, msg_str):
@shared_task(base=LoggedTask, ignore_result=True)
-@set_code_owner_attribute
def _course_update_schedule_send(site_id, msg_str):
_schedule_send(
msg_str,
@@ -240,7 +232,6 @@ class ScheduleCourseNextSectionUpdate(ScheduleMessageBaseTask): # pylint: disab
@classmethod
def enqueue(cls, site, current_date, day_offset, override_recipient_email=None): # pylint: disable=missing-function-docstring
- set_code_owner_attribute_from_module(__name__)
target_datetime = (current_date - datetime.timedelta(days=day_offset))
if not cls.is_enqueue_enabled(site):
@@ -262,7 +253,6 @@ def enqueue(cls, site, current_date, day_offset, override_recipient_email=None):
)
def run(self, site_id, target_day_str, course_key, override_recipient_email=None): # pylint: disable=arguments-differ
- set_code_owner_attribute_from_module(__name__)
site = Site.objects.select_related('configuration').get(id=site_id)
with emulate_http_request(site=site):
_annotate_for_monitoring(message_types.CourseUpdate(), site, 0, target_day_str, -1)
diff --git a/openedx/core/djangoapps/service_status/tasks.py b/openedx/core/djangoapps/service_status/tasks.py
index 61b35d7a4cc5..6ba3cd33482c 100644
--- a/openedx/core/djangoapps/service_status/tasks.py
+++ b/openedx/core/djangoapps/service_status/tasks.py
@@ -6,11 +6,9 @@
import time
from celery import current_app as celery
-from edx_django_utils.monitoring import set_code_owner_attribute
@celery.task
-@set_code_owner_attribute
def delayed_ping(value, delay):
"""A simple tasks that replies to a message after a especified amount
of seconds.
diff --git a/openedx/core/djangoapps/user_authn/tasks.py b/openedx/core/djangoapps/user_authn/tasks.py
index b54e761dd25f..2d368c1d1c78 100644
--- a/openedx/core/djangoapps/user_authn/tasks.py
+++ b/openedx/core/djangoapps/user_authn/tasks.py
@@ -12,7 +12,6 @@
from edx_ace import ace
from edx_ace.errors import RecoverableChannelDeliveryError
from edx_ace.message import Message
-from edx_django_utils.monitoring import set_code_owner_attribute
from common.djangoapps.track import segment
from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers
@@ -23,7 +22,6 @@
@shared_task
-@set_code_owner_attribute
def check_pwned_password_and_send_track_event(
user_id, password,
internal_user=False,
@@ -50,7 +48,6 @@ def check_pwned_password_and_send_track_event(
@shared_task(bind=True, default_retry_delay=30, max_retries=2)
-@set_code_owner_attribute
def send_activation_email(self, msg_string, from_address=None, site_id=None):
"""
Sending an activation email to the user.
diff --git a/openedx/features/enterprise_support/tasks.py b/openedx/features/enterprise_support/tasks.py
index f41da3031076..248461a627de 100644
--- a/openedx/features/enterprise_support/tasks.py
+++ b/openedx/features/enterprise_support/tasks.py
@@ -6,7 +6,6 @@
import logging
from celery import shared_task
-from edx_django_utils.monitoring import set_code_owner_attribute
from enterprise.models import EnterpriseCourseEnrollment
from openedx.features.enterprise_support.utils import clear_data_consent_share_cache
@@ -15,7 +14,6 @@
@shared_task(name='openedx.features.enterprise_support.tasks.clear_enterprise_customer_data_consent_share_cache')
-@set_code_owner_attribute
def clear_enterprise_customer_data_consent_share_cache(enterprise_customer_uuid):
"""
clears data_sharing_consent_needed cache for whole enterprise
diff --git a/openedx/features/survey_report/tasks.py b/openedx/features/survey_report/tasks.py
index ff7fe2ac64f2..8e775db8571e 100644
--- a/openedx/features/survey_report/tasks.py
+++ b/openedx/features/survey_report/tasks.py
@@ -6,7 +6,6 @@
import logging
from celery import shared_task
-from edx_django_utils.monitoring import set_code_owner_attribute
from .api import generate_report
@@ -14,7 +13,6 @@
@shared_task(name='openedx.features.survey_report.tasks.generate_survey_report')
-@set_code_owner_attribute
def generate_survey_report():
"""
Tasks to generate a new survey report with non-sensitive data.
diff --git a/requirements/edx/semgrep.in b/requirements/edx/semgrep.in
deleted file mode 100644
index 0fc07d64532b..000000000000
--- a/requirements/edx/semgrep.in
+++ /dev/null
@@ -1,13 +0,0 @@
-# Requirements to run Semgrep code quality checks
-#
-# DON'T JUST ADD NEW DEPENDENCIES!!!
-#
-# If you open a pull request that adds a new dependency, you should:
-# * verify that the dependency has a license compatible with AGPLv3
-# * confirm that it has no system requirements beyond what we already install
-# * run "make upgrade" to update the detailed requirements files
-#
-
--c ../constraints.txt
-
-semgrep # Semgrep performs structural code searches
diff --git a/requirements/edx/semgrep.txt b/requirements/edx/semgrep.txt
deleted file mode 100644
index 51f2d11db551..000000000000
--- a/requirements/edx/semgrep.txt
+++ /dev/null
@@ -1,213 +0,0 @@
-#
-# This file is autogenerated by pip-compile with Python 3.12
-# by the following command:
-#
-# make upgrade
-#
-annotated-types==0.8.0
- # via pydantic
-anyio==4.14.2
- # via
- # httpx
- # mcp
- # sse-starlette
- # starlette
-attrs==26.1.0
- # via
- # glom
- # jsonschema
- # referencing
- # semgrep
-boltons==21.0.0
- # via
- # face
- # glom
- # semgrep
-bracex==3.0.1
- # via wcmatch
-certifi==2026.7.22
- # via
- # httpcore
- # httpx
- # requests
-cffi==2.1.0
- # via cryptography
-charset-normalizer==3.4.9
- # via requests
-click==8.4.2
- # via
- # click-option-group
- # semgrep
- # uvicorn
-click-option-group==0.5.9
- # via semgrep
-colorama==0.4.6
- # via semgrep
-cryptography==49.0.0
- # via pyjwt
-exceptiongroup==1.2.2
- # via semgrep
-face==26.0.1
- # via glom
-glom==25.12.0
- # via semgrep
-googleapis-common-protos==1.75.0
- # via opentelemetry-exporter-otlp-proto-http
-h11==0.16.0
- # via
- # httpcore
- # uvicorn
-httpcore==1.0.9
- # via httpx
-httpx==0.28.1
- # via mcp
-httpx-sse==0.4.3
- # via mcp
-idna==3.18
- # via
- # anyio
- # httpx
- # requests
-importlib-metadata==8.7.1
- # via opentelemetry-api
-jsonschema==4.25.1
- # via
- # mcp
- # semgrep
-jsonschema-specifications==2025.9.1
- # via jsonschema
-markdown-it-py==4.2.0
- # via rich
-mcp==1.23.3
- # via semgrep
-mdurl==0.1.2
- # via markdown-it-py
-opentelemetry-api==1.37.0
- # via
- # opentelemetry-exporter-otlp-proto-http
- # opentelemetry-instrumentation
- # opentelemetry-instrumentation-requests
- # opentelemetry-instrumentation-threading
- # opentelemetry-sdk
- # opentelemetry-semantic-conventions
- # semgrep
-opentelemetry-exporter-otlp-proto-common==1.37.0
- # via opentelemetry-exporter-otlp-proto-http
-opentelemetry-exporter-otlp-proto-http==1.37.0
- # via semgrep
-opentelemetry-instrumentation==0.58b0
- # via
- # opentelemetry-instrumentation-requests
- # opentelemetry-instrumentation-threading
-opentelemetry-instrumentation-requests==0.58b0
- # via semgrep
-opentelemetry-instrumentation-threading==0.58b0
- # via semgrep
-opentelemetry-proto==1.37.0
- # via
- # opentelemetry-exporter-otlp-proto-common
- # opentelemetry-exporter-otlp-proto-http
-opentelemetry-sdk==1.37.0
- # via
- # opentelemetry-exporter-otlp-proto-http
- # semgrep
-opentelemetry-semantic-conventions==0.58b0
- # via
- # opentelemetry-instrumentation
- # opentelemetry-instrumentation-requests
- # opentelemetry-sdk
-opentelemetry-util-http==0.58b0
- # via opentelemetry-instrumentation-requests
-packaging==26.2
- # via
- # opentelemetry-instrumentation
- # semgrep
-peewee==3.19.0
- # via semgrep
-protobuf==6.33.6
- # via
- # googleapis-common-protos
- # opentelemetry-proto
-pycparser==3.0
- # via cffi
-pydantic==2.13.4
- # via
- # mcp
- # pydantic-settings
-pydantic-core==2.46.4
- # via pydantic
-pydantic-settings==2.14.2
- # via mcp
-pygments==2.20.0
- # via rich
-pyjwt[crypto]==2.13.0
- # via
- # mcp
- # semgrep
-python-dotenv==1.2.2
- # via pydantic-settings
-python-multipart==0.0.32
- # via mcp
-referencing==0.37.0
- # via
- # jsonschema
- # jsonschema-specifications
-requests==2.34.2
- # via
- # opentelemetry-exporter-otlp-proto-http
- # semgrep
-rich==15.0.0
- # via semgrep
-rpds-py==2026.6.3
- # via
- # jsonschema
- # referencing
-ruamel-yaml==0.19.1
- # via semgrep
-ruamel-yaml-clib==0.2.15
- # via semgrep
-semantic-version==2.10.0
- # via semgrep
-semgrep==1.171.0
- # via -r requirements/edx/semgrep.in
-sse-starlette==3.4.6
- # via mcp
-starlette==1.3.1
- # via
- # mcp
- # sse-starlette
-tomli==2.4.1
- # via semgrep
-typing-extensions==4.16.0
- # via
- # anyio
- # mcp
- # opentelemetry-api
- # opentelemetry-exporter-otlp-proto-http
- # opentelemetry-sdk
- # opentelemetry-semantic-conventions
- # pydantic
- # pydantic-core
- # referencing
- # semgrep
- # starlette
- # typing-inspection
-typing-inspection==0.4.2
- # via
- # mcp
- # pydantic
- # pydantic-settings
-urllib3==2.7.0
- # via
- # requests
- # semgrep
-uvicorn==0.51.0
- # via mcp
-wcmatch==8.5.2
- # via semgrep
-wrapt==1.17.3
- # via
- # opentelemetry-instrumentation
- # opentelemetry-instrumentation-threading
-zipp==4.1.0
- # via importlib-metadata
diff --git a/test_root/semgrep/README.rst b/test_root/semgrep/README.rst
deleted file mode 100644
index 92fa16f1bf05..000000000000
--- a/test_root/semgrep/README.rst
+++ /dev/null
@@ -1,21 +0,0 @@
-Semgrep linters
-###############
-
-Linting rules for use with `semgrep`_ during CI checks on PRs.
-
-Status
-******
-
-This is an experimental approach to developing new linting rules. Semgrep provides by-example structural matching that can be easier to write and maintain than procedural code inspecting ASTs. If the approach works out, we can expand our use of Semgrep; if it becomes a problem for some reason, we can switch to adding pylint rules in edx-lint.
-
-Ignoring failures
-*****************
-
-If you need to tell semgrep to ignore a block of code, put a ``# nosemgrep`` comment on or before the first matched line.
-
-Documentation for writing new rules:
-
-- https://semgrep.dev/docs/writing-rules/rule-syntax/
-- https://semgrep.dev/docs/writing-rules/pattern-syntax/
-
-.. _semgrep: https://github.com/returntocorp/semgrep
diff --git a/test_root/semgrep/celery-code-owner.yml b/test_root/semgrep/celery-code-owner.yml
deleted file mode 100644
index a1693752d2ff..000000000000
--- a/test_root/semgrep/celery-code-owner.yml
+++ /dev/null
@@ -1,104 +0,0 @@
-rules:
- - id: celery-missing-code-owner-function
- # We can't link directly to the howto doc in question because
- # semgrep has a bug around long lines:
- # https://github.com/returntocorp/semgrep/issues/8608
- #
- # Here's the intended URL, for reference:
- # https://docs.openedx.org/projects/edx-django-utils/en/latest/monitoring/how_tos/add_code_owner_custom_attribute_to_an_ida.html#handling-celery-tasks
- message: |
- Celery tasks need to be decorated with `@set_code_owner_attribute`
- (from the `edx_django_utils.monitoring` module) in order for us
- to correctly track code-owners for errors and in other monitoring.
-
- For more information, see the Celery section of "Add Code_Owner
- Custom Attributes to an IDA" in the Monitoring How-Tos of
- .
- languages:
- - python
- patterns:
- # Find functions with decorators containing the substring "task"
- # in their name. This might end up with false positives, but
- # there are a lot of variations on how we decorate Celery tasks.
-
- # This pattern should match all decorators, whether or not
- # they're called as a function (both `@foo(...)` and `@foo`)
- # and whether or not there are other decorators above or below.
- - pattern-either:
- - pattern: |
- @$TASK
- def $F(...):
- ...
- - pattern: |
- @$TASK(...)
- def $F(...):
- ...
-
- # Restrict the decorators of interest to just ones with "task"
- # in the name.
- - metavariable-pattern:
- metavariable: $TASK
- patterns:
- - pattern-regex: >-
- [^\(]*task(\(|$)
-
- # Filter out all of the properly annotated functions, leaving
- # just the ones of interest.
- - pattern-not: |
- @set_code_owner_attribute
- def $F(...):
- ...
- # This is an alternative approach that we have needed in rare cases.
- - pattern-not: |
- def $F(...):
- ...
- set_code_owner_attribute_from_module(...)
-
- severity: WARNING
-
- # This is like celery-missing-code-owner-function but for the `run`
- # method of Task classes.
- - id: celery-missing-code-owner-class
- message: |
- Celery task classes need to decorate their `run` method with
- `@set_code_owner_attribute` (imported from `edx_django_utils.monitoring`)
- in order for us to correctly track code-owners for errors and in other
- monitoring. Alternatively, the `run` method can call
- `set_code_owner_attribute_from_module`.
-
- For more information, see the Celery section of "Add Code_Owner
- Custom Attributes to an IDA" in the Monitoring How-Tos of
- .
- languages:
- - python
- patterns:
- - pattern: |
- class $C(..., $SUPER, ...):
- def run(...):
- ...
- - metavariable-pattern:
- metavariable: $SUPER
- patterns:
- - pattern-regex: "Task$"
-
- - pattern-not: |
- class $C(..., $SUPER, ...):
-
- @set_code_owner_attribute
- def run(...):
- ...
-
- - pattern-not: |
- class $C(..., $SUPER, ...):
-
- @set_code_owner_attribute
- def run(...):
- ...
- - pattern-not: |
- class $C(..., $SUPER, ...):
-
- def run(...):
- ...
- set_code_owner_attribute_from_module(...)
-
- severity: WARNING
diff --git a/xmodule/modulestore/django.py b/xmodule/modulestore/django.py
index 82638265976f..0b3790008843 100644
--- a/xmodule/modulestore/django.py
+++ b/xmodule/modulestore/django.py
@@ -165,7 +165,6 @@ class SignalHandler:
from django.dispatch import receiver
from celery import shared_task
- from edx_django_utils.monitoring import set_code_owner_attribute
from xmodule.modulestore.django import modulestore, SignalHandler
@receiver(SignalHandler.course_published)
@@ -173,7 +172,6 @@ def listen_for_course_publish(sender, course_key, **kwargs):
do_my_expensive_update.delay(course_key)
@shared_task()
- @set_code_owner_attribute
def do_my_expensive_update(course_key):
# ...