-
Notifications
You must be signed in to change notification settings - Fork 18
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'main' into feat/scaffold-ui-test-user-on-demand
- Loading branch information
Showing
105 changed files
with
4,062 additions
and
2,231 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
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 |
---|---|---|
|
@@ -34,7 +34,7 @@ jobs: | |
- name: Install poetry | ||
env: | ||
POETRY_VERSION: "1.7.1" | ||
run: pip install poetry==${POETRY_VERSION} && poetry --version | ||
run: pip install poetry==${POETRY_VERSION} poetry-plugin-sort && poetry --version | ||
- name: Check poetry.lock aligns with pyproject.toml | ||
run: poetry check --lock | ||
- name: Install requirements | ||
|
@@ -67,7 +67,7 @@ jobs: | |
run: | | ||
cp -f .env.example .env | ||
- name: Checks for new endpoints against AWS WAF rules | ||
uses: cds-snc/notification-utils/.github/actions/[email protected].2 | ||
uses: cds-snc/notification-utils/.github/actions/[email protected].9 | ||
with: | ||
app-loc: '/github/workspace' | ||
app-libs: '/github/workspace/env/site-packages' | ||
|
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 |
---|---|---|
|
@@ -91,3 +91,5 @@ jinja_templates/ | |
cypress.env.json | ||
node_modules/ | ||
tests_cypress/cypress/videos/ | ||
|
||
.ruff_cache/ |
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
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,109 @@ | ||
import logging | ||
|
||
from aws_xray_sdk.core.context import Context | ||
from aws_xray_sdk.core.exceptions.exceptions import SegmentNotFoundException | ||
|
||
log = logging.getLogger(__name__) | ||
|
||
MISSING_SEGMENT_MSG = "cannot find the current segment/subsegment, please make sure you have a segment open" | ||
SUPPORTED_CONTEXT_MISSING = ("RUNTIME_ERROR", "LOG_ERROR", "LOG_WARNING", "IGNORE_ERROR") | ||
CXT_MISSING_STRATEGY_KEY = "AWS_XRAY_CONTEXT_MISSING" | ||
|
||
|
||
class NotifyContext(Context): | ||
""" | ||
This is a custom context class that has more sensitive logging levels | ||
than the default thread local context class. | ||
For example, if there is a check on the current segment, no errors would | ||
be logged but rather warn or info messages would be logged. | ||
The context parent class is the default storage one that works using | ||
a threadlocal. The same technical constraints and feature apply. | ||
""" | ||
|
||
def __init__(self, context_missing="LOG_WARNING"): | ||
super().__init__(context_missing) | ||
|
||
def put_segment(self, segment): | ||
""" | ||
Store the segment created by ``xray_recorder`` to the context. | ||
It overrides the current segment if there is already one. | ||
""" | ||
super().put_segment(segment) | ||
|
||
def end_segment(self, end_time=None): | ||
""" | ||
End the current active segment. | ||
:param float end_time: epoch in seconds. If not specified the current | ||
system time will be used. | ||
""" | ||
super().end_segment(end_time) | ||
|
||
def put_subsegment(self, subsegment): | ||
""" | ||
Store the subsegment created by ``xray_recorder`` to the context. | ||
If you put a new subsegment while there is already an open subsegment, | ||
the new subsegment becomes the child of the existing subsegment. | ||
""" | ||
super().put_subsegment(subsegment) | ||
|
||
def end_subsegment(self, end_time=None): | ||
""" | ||
End the current active segment. Return False if there is no | ||
subsegment to end. | ||
:param float end_time: epoch in seconds. If not specified the current | ||
system time will be used. | ||
""" | ||
return super().end_subsegment(end_time) | ||
|
||
def get_trace_entity(self): | ||
""" | ||
Return the current trace entity(segment/subsegment). If there is none, | ||
it behaves based on pre-defined ``context_missing`` strategy. | ||
If the SDK is disabled, returns a DummySegment | ||
""" | ||
return super().get_trace_entity() | ||
|
||
def set_trace_entity(self, trace_entity): | ||
""" | ||
Store the input trace_entity to local context. It will overwrite all | ||
existing ones if there is any. | ||
""" | ||
super().set_trace_entity(trace_entity) | ||
|
||
def clear_trace_entities(self): | ||
""" | ||
clear all trace_entities stored in the local context. | ||
In case of using threadlocal to store trace entites, it will | ||
clean up all trace entities created by the current thread. | ||
""" | ||
super().clear_trace_entities() | ||
|
||
def handle_context_missing(self): | ||
""" | ||
Called whenever there is no trace entity to access or mutate. | ||
""" | ||
if self.context_missing == "RUNTIME_ERROR": | ||
raise SegmentNotFoundException(MISSING_SEGMENT_MSG) | ||
elif self.context_missing == "LOG_ERROR": | ||
log.error(MISSING_SEGMENT_MSG) | ||
elif self.context_missing == "LOG_WARNING": | ||
log.warning(MISSING_SEGMENT_MSG) | ||
|
||
def _is_subsegment(self, entity): | ||
return super()._is_subsegment(entity) | ||
|
||
@property | ||
def context_missing(self): | ||
return self._context_missing | ||
|
||
@context_missing.setter | ||
def context_missing(self, value): | ||
if value not in SUPPORTED_CONTEXT_MISSING: | ||
log.warning("specified context_missing not supported, using default.") | ||
return | ||
|
||
self._context_missing = value |
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,79 @@ | ||
import logging | ||
|
||
from aws_xray_sdk.core import xray_recorder | ||
from aws_xray_sdk.core.utils import stacktrace | ||
from aws_xray_sdk.ext.util import construct_xray_header, inject_trace_header | ||
|
||
__all__ = ( | ||
"xray_after_task_publish", | ||
"xray_before_task_publish", | ||
"xray_task_failure", | ||
"xray_task_postrun", | ||
"xray_task_prerun", | ||
) | ||
|
||
logger = logging.getLogger("celery_aws_xray_sdk_extension") | ||
|
||
CELERY_NAMESPACE = "celery" | ||
|
||
|
||
def xray_before_task_publish( | ||
sender=None, headers=None, exchange=None, routing_key=None, properties=None, declare=None, retry_policy=None, **kwargs | ||
): | ||
logger.info(f"xray-celery: before publish: sender={sender}, headers={headers}, kwargs={kwargs}") | ||
headers = headers if headers else {} | ||
task_id = headers.get("id") | ||
current_segment = xray_recorder.current_segment() | ||
# Checks if there is a current segment to create a subsegment, | ||
# otherwise we might be in a starter task. The prerun handler will | ||
# create the segment for us down the road as it will be called after. | ||
if current_segment: | ||
subsegment = xray_recorder.begin_subsegment(name=sender, namespace="remote") | ||
if subsegment: | ||
subsegment.put_metadata("task_id", task_id, namespace=CELERY_NAMESPACE) | ||
inject_trace_header(headers, subsegment) | ||
else: | ||
logger.error( | ||
"xray-celery: Failed to create a X-Ray subsegment on task publish", extra={"celery": {"task_id": task_id}} | ||
) | ||
else: | ||
logger.warn(f"xray-celery: No parent segment found for task {task_id} when trying to create subsegment") | ||
|
||
|
||
def xray_after_task_publish(headers=None, body=None, exchange=None, routing_key=None, **kwargs): | ||
logger.info( | ||
f"xray-celery: after publish: headers={headers}, body={body}, exchange={exchange}, routing_key={routing_key}, kwargs={kwargs}" | ||
) | ||
if xray_recorder.current_subsegment(): | ||
xray_recorder.end_subsegment() | ||
else: | ||
logger.warn(f"xray-celery: Skipping subsegment closing after publish as no subsegment was found: {headers}") | ||
|
||
|
||
def xray_task_prerun(task_id=None, task=None, args=None, **kwargs): | ||
logger.info(f"xray-celery: prerun: task_id={task_id}, task={task}, kwargs={kwargs}") | ||
xray_header = construct_xray_header(task.request) | ||
segment = xray_recorder.begin_segment(name=task.name, traceid=xray_header.root, parent_id=xray_header.parent) | ||
segment.save_origin_trace_header(xray_header) | ||
segment.put_annotation("routing_key", task.request.properties["delivery_info"]["routing_key"]) | ||
segment.put_annotation("task_name", task.name) | ||
segment.put_metadata("task_id", task_id, namespace=CELERY_NAMESPACE) | ||
|
||
|
||
def xray_task_postrun(task_id=None, task=None, args=None, **kwargs): | ||
logger.info(f"xray-celery: postrun: kwargs={kwargs}") | ||
xray_recorder.end_segment() | ||
|
||
|
||
def xray_task_failure(task_id=None, exception=None, **kwargs): | ||
logger.info(f"xray-celery: failure: task_id={task_id}, e={exception}, kwargs={kwargs}") | ||
segment = xray_recorder.current_segment() | ||
if not segment: | ||
logger.error( | ||
"xray-celery: Failed to get the current segment on task failure", extra={"celery": {"task_id": kwargs.get("task_id")}} | ||
) | ||
return | ||
|
||
if exception: | ||
stack = stacktrace.get_stacktrace(limit=xray_recorder._max_trace_back) | ||
segment.add_exception(exception, stack) |
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,20 @@ | ||
from flask import Blueprint, current_app, jsonify | ||
from notifications_utils.clients.redis.cache_keys import CACHE_KEYS_ALL | ||
|
||
from app import redis_store | ||
from app.errors import register_errors | ||
from app.schemas import event_schema | ||
|
||
cache_blueprint = Blueprint("cache", __name__, url_prefix="/cache-clear") | ||
register_errors(cache_blueprint) | ||
|
||
|
||
@cache_blueprint.route("", methods=["POST"]) | ||
def clear(): | ||
try: | ||
max(redis_store.delete_cache_keys_by_pattern(pattern) for pattern in CACHE_KEYS_ALL) | ||
return jsonify(result="ok"), 201 | ||
except Exception as e: | ||
current_app.logger.error("Unable to clear the cache", exc_info=e) | ||
|
||
return jsonify({"error": "Unable to clear the cache"}), 500 |
Oops, something went wrong.