-
Notifications
You must be signed in to change notification settings - Fork 3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: refactor code_owner code from edx-dajango-utils #838
Open
robrap
wants to merge
4
commits into
main
Choose a base branch
from
robrap/add-code-owner-monitoring
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
bd1cb6b
feat: original copy of code_owner code
robrap d9566de
feat: refactor code_owner code from edx-dajango-utils
robrap 4908ac8
fixup! Re-compile requirements for 3.11 on Linux (without `--upgrade`)
timmc-edx 1d3af1c
fixup! fix some quality failures
robrap File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
Datadog Monitoring | ||
################### | ||
|
||
When installed in the LMS as a plugin app, the ``datadog_monitoring`` app adds additional monitoring. | ||
|
||
This is where our code_owner_2 monitoring code lives, for example. |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
""" | ||
App for 2U-specific edx-platform Datadog monitoring. | ||
""" | ||
|
||
import logging | ||
|
||
from django.apps import AppConfig | ||
|
||
from .code_owner.utils import get_code_owner_from_module | ||
|
||
log = logging.getLogger(__name__) | ||
|
||
|
||
class DatadogMonitoringSpanProcessor: | ||
"""Datadog span processor that adds custom monitoring (e.g. code owner tags).""" | ||
|
||
def on_span_start(self, span): | ||
""" | ||
Adds custom monitoring at span creation time. | ||
|
||
Specifically, adds code owner span tag for celery run spans. | ||
""" | ||
if not span or not hasattr(span, 'name') or not hasattr(span, 'resource'): | ||
return | ||
|
||
if span.name == 'celery.run': | ||
# We can use this for celery spans, because the resource name is more predictable | ||
# and available from the start. For django requests, we'll instead continue to use | ||
# django middleware for setting code owner. | ||
get_code_owner_from_module(span.resource) | ||
|
||
def on_span_finish(self, span): | ||
pass | ||
|
||
def shutdown(self, _timeout): | ||
pass | ||
|
||
|
||
class DatadogMonitoring(AppConfig): | ||
""" | ||
Django application to handle 2U-specific Datadog monitoring. | ||
""" | ||
name = 'edx_arch_experiments.datadog_monitoring' | ||
|
||
# Mark this as a plugin app | ||
plugin_app = {} | ||
|
||
def ready(self): | ||
try: | ||
from ddtrace import tracer # pylint: disable=import-outside-toplevel | ||
|
||
tracer._span_processors.append(DatadogMonitoringSpanProcessor()) # pylint: disable=protected-access | ||
log.info("Attached DatadogMonitoringSpanProcessor") | ||
except ImportError: | ||
log.warning( | ||
"Unable to attach DatadogMonitoringSpanProcessor" | ||
" -- ddtrace module not found." | ||
) |
6 changes: 6 additions & 0 deletions
6
edx_arch_experiments/datadog_monitoring/code_owner/__init__.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
""" | ||
This directory should only be used internally. | ||
|
||
Its public API is exposed in the top-level monitoring __init__.py. | ||
See its README.rst for details. | ||
""" |
89 changes: 89 additions & 0 deletions
89
edx_arch_experiments/datadog_monitoring/code_owner/middleware.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
""" | ||
Middleware for code_owner_2 custom attribute | ||
""" | ||
import logging | ||
|
||
from django.urls import resolve | ||
from edx_django_utils.monitoring import set_custom_attribute | ||
|
||
from .utils import get_code_owner_from_module, is_code_owner_mappings_configured, set_code_owner_custom_attributes | ||
|
||
log = logging.getLogger(__name__) | ||
|
||
|
||
class CodeOwnerMonitoringMiddleware: | ||
""" | ||
Django middleware object to set custom attributes for the owner of each view. | ||
|
||
For instructions on usage, see: | ||
https://github.com/edx/edx-arch-experiments/blob/master/edx_arch_experiments/datadog_monitoring/docs/how_tos/add_code_owner_custom_attribute_to_an_ida.rst | ||
|
||
Custom attributes set: | ||
- code_owner_2: The owning team mapped to the current view. | ||
- code_owner_2_module: The module found from the request or current transaction. | ||
- code_owner_2_path_error: The error mapping by path, if code_owner_2 isn't found in other ways. | ||
|
||
""" | ||
def __init__(self, get_response): | ||
self.get_response = get_response | ||
|
||
def __call__(self, request): | ||
response = self.get_response(request) | ||
self._set_code_owner_attribute(request) | ||
return response | ||
|
||
def process_exception(self, request, exception): # pylint: disable=W0613 | ||
self._set_code_owner_attribute(request) | ||
|
||
def _set_code_owner_attribute(self, request): | ||
""" | ||
Sets the code_owner_2 custom attribute for the request. | ||
""" | ||
code_owner = None | ||
module = self._get_module_from_request(request) | ||
if module: | ||
code_owner = get_code_owner_from_module(module) | ||
|
||
if code_owner: | ||
set_code_owner_custom_attributes(code_owner) | ||
|
||
def _get_module_from_request(self, request): | ||
""" | ||
Get the module from the request path or the current transaction. | ||
|
||
Side-effects: | ||
Sets code_owner_2_module custom attribute, used to determine code_owner_2. | ||
If module was not found, may set code_owner_2_path_error custom attribute | ||
if applicable. | ||
|
||
Returns: | ||
str: module name or None if not found | ||
|
||
""" | ||
if not is_code_owner_mappings_configured(): | ||
return None | ||
|
||
module, path_error = self._get_module_from_request_path(request) | ||
if module: | ||
set_custom_attribute('code_owner_2_module', module) | ||
return module | ||
|
||
# monitor errors if module was not found | ||
if path_error: | ||
set_custom_attribute('code_owner_2_path_error', path_error) | ||
return None | ||
|
||
def _get_module_from_request_path(self, request): | ||
""" | ||
Uses the request path to get the view_func module. | ||
|
||
Returns: | ||
(str, str): (module, error_message), where at least one of these should be None | ||
|
||
""" | ||
try: | ||
view_func, _, _ = resolve(request.path) | ||
module = view_func.__module__ | ||
return module, None | ||
except Exception as e: # pragma: no cover, pylint: disable=broad-exception-caught | ||
return None, str(e) |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't this be
set_code_owner_attribute_from_module
?