Skip to content

Commit

Permalink
Add correct metadata when task is revoked
Browse files Browse the repository at this point in the history
Closes #317
  • Loading branch information
jrobichaud committed Sep 26, 2023
1 parent 42a0e8d commit a3209e4
Show file tree
Hide file tree
Showing 7 changed files with 70 additions and 2 deletions.
1 change: 1 addition & 0 deletions config/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ def uncaught_exception_view(request):
re_path(
r"^about/", TemplateView.as_view(template_name="pages/about.html"), name="about"
),
re_path(r"^revoke_task", views.revoke_task, name="revoke_task"),
# Django Admin, use {% url 'admin:index' %}
re_path(settings.ADMIN_URL, admin.site.urls),
# User management
Expand Down
10 changes: 9 additions & 1 deletion django_structlog/celery/receivers.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,16 @@ def receiver_task_failure(
def receiver_task_revoked(
request=None, terminated=None, signum=None, expired=None, **kwargs
):
metadata = getattr(request, "__django_structlog__", {}).copy()
metadata["task_id"] = request.id
metadata["task"] = request.task

logger.warning(
"task_revoked", terminated=terminated, signum=signum, expired=expired
"task_revoked",
terminated=terminated,
signum=signum,
expired=expired,
**metadata,
)


Expand Down
6 changes: 6 additions & 0 deletions django_structlog_demo_project/home/tests/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,9 @@ class TestAsyncView:
async def test(self):
response = await views.async_view(None)
assert response.status_code == 200


class TestRevocableTask:
def test(self):
response = views.revoke_task(None)
assert response.status_code == 201
7 changes: 7 additions & 0 deletions django_structlog_demo_project/home/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
successful_task,
failing_task,
nesting_task,
revocable_task,
)

logger = structlog.get_logger(__name__)
Expand Down Expand Up @@ -35,6 +36,12 @@ def log_with_standard_logger(request):
return HttpResponse(status=200)


def revoke_task(request):
async_result = revocable_task.delay()
async_result.revoke(terminate=True)
return HttpResponse(status=201)


async def async_view(request):
for num in range(1, 2):
await asyncio.sleep(1)
Expand Down
18 changes: 18 additions & 0 deletions django_structlog_demo_project/taskapp/celery.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import asyncio
import functools
import logging
import logging.config
import os
Expand Down Expand Up @@ -65,6 +67,22 @@ def successful_task(foo=None):
logger.info("This is a successful task")


def async_to_sync(func):
@functools.wraps(func)
def wrapped(*args, **kwargs):
return asyncio.run(func(*args, **kwargs))

return wrapped


@shared_task
@async_to_sync
async def revocable_task():
logger = structlog.getLogger(__name__)
logger.info("This is a revocable task")
await asyncio.sleep(1000)


@shared_task
def failing_task(foo=None, **kwargs):
raise Exception("This is a failed task")
Expand Down
7 changes: 7 additions & 0 deletions django_structlog_demo_project/templates/pages/home.html
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,13 @@
<button type="submit" form="form5">Standard logger</button>
</div>

<div>
<form action="{% url 'revoke_task' %}" method="post" id="form6" target="dummyframe">
{% csrf_token %}
</form>
<button type="submit" form="form6">Revoke task</button>
</div>

<div>
<form action="{% url 'async_view' %}" method="post" id="form6" target="dummyframe">
{% csrf_token %}
Expand Down
23 changes: 22 additions & 1 deletion test_app/tests/celery/test_receivers.py
Original file line number Diff line number Diff line change
Expand Up @@ -347,10 +347,23 @@ def test_receiver_task_failure_with_throws(self):
self.assertEqual(expected_exception, record.msg["error"])

def test_receiver_task_revoked(self):
expected_request_uuid = "00000000-0000-0000-0000-000000000000"
task_id = "11111111-1111-1111-1111-111111111111"
expected_user_id = "1234"
expected_task_name = "task_name"
request = Mock()
request.__django_structlog__ = {
"request_id": expected_request_uuid,
"user_id": expected_user_id,
}
request.task = expected_task_name
request.id = task_id
with self.assertLogs(
logging.getLogger("django_structlog.celery.receivers"), logging.WARNING
) as log_results:
receivers.receiver_task_revoked(terminated=True, signum=1, expired=False)
receivers.receiver_task_revoked(
request=request, terminated=True, signum=1, expired=False
)

self.assertEqual(1, len(log_results.records))
record = log_results.records[0]
Expand All @@ -362,6 +375,14 @@ def test_receiver_task_revoked(self):
self.assertEqual(1, record.msg["signum"])
self.assertIn("expired", record.msg)
self.assertFalse(record.msg["expired"])
self.assertIn("task_id", record.msg)
self.assertEqual(task_id, record.msg["task_id"])
self.assertIn("task", record.msg)
self.assertEqual(expected_task_name, record.msg["task"])
self.assertIn("request_id", record.msg)
self.assertEqual(expected_request_uuid, record.msg["request_id"])
self.assertIn("user_id", record.msg)
self.assertEqual(expected_user_id, record.msg["user_id"])

def test_receiver_task_unknown(self):
expected_message = "foo"
Expand Down

0 comments on commit a3209e4

Please sign in to comment.