-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: refactor code_owner code from edx-dajango-utils (#838)
Initial rollout of moving code_owner monitoring code from edx-django-utils to this plugin. - Adds near duplicate of code owner middleware from edx-django-utils. - Adds code owner span tags for celery using Datadog span processing of celery.run spans. - Uses temporary span tags names using `_2`, like `code_owner_2`, for rollout and comparison with the original span tags. - Span tag code_owner_2_module includes the task name, where the original code_owner_module does not. In both cases, the code owner is computed the same, because it is based on a prefix match. See #784
- Loading branch information
Showing
32 changed files
with
1,458 additions
and
114 deletions.
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,19 @@ | ||
""" | ||
App for 2U-specific edx-platform Datadog monitoring. | ||
""" | ||
from django.apps import AppConfig | ||
|
||
|
||
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): | ||
# Implicitly connect signal handlers decorated with @receiver | ||
# pylint: disable=import-outside-toplevel,unused-import | ||
from edx_arch_experiments.datadog_monitoring.signals import handlers |
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. | ||
""" |
26 changes: 26 additions & 0 deletions
26
edx_arch_experiments/datadog_monitoring/code_owner/datadog.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,26 @@ | ||
""" | ||
Datadog span processor for celery span code owners. | ||
""" | ||
from .utils import set_code_owner_attribute_from_module | ||
|
||
|
||
class CeleryCodeOwnerSpanProcessor: | ||
""" | ||
Datadog span processor that adds celery code owner span tags. | ||
""" | ||
|
||
def on_span_start(self, span): | ||
""" | ||
Adds code owner span tag for celery run spans at span creation. | ||
""" | ||
if getattr(span, 'name', None) == '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. | ||
set_code_owner_attribute_from_module(span.resource) | ||
|
||
def on_span_finish(self, span): | ||
pass | ||
|
||
def shutdown(self, _timeout): | ||
pass |
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.