django-structlog 6.1.0.dev1__tar.gz → 7.0.0.dev1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (22) hide show
  1. {django-structlog-6.1.0.dev1/django_structlog.egg-info → django-structlog-7.0.0.dev1}/PKG-INFO +13 -2
  2. {django-structlog-6.1.0.dev1 → django-structlog-7.0.0.dev1}/README.rst +11 -0
  3. {django-structlog-6.1.0.dev1 → django-structlog-7.0.0.dev1}/django_structlog/__init__.py +1 -1
  4. {django-structlog-6.1.0.dev1 → django-structlog-7.0.0.dev1}/django_structlog/celery/receivers.py +13 -20
  5. {django-structlog-6.1.0.dev1 → django-structlog-7.0.0.dev1}/django_structlog/commands.py +2 -5
  6. {django-structlog-6.1.0.dev1 → django-structlog-7.0.0.dev1}/django_structlog/middlewares/request.py +82 -45
  7. {django-structlog-6.1.0.dev1 → django-structlog-7.0.0.dev1/django_structlog.egg-info}/PKG-INFO +13 -2
  8. {django-structlog-6.1.0.dev1 → django-structlog-7.0.0.dev1}/django_structlog.egg-info/requires.txt +1 -1
  9. {django-structlog-6.1.0.dev1 → django-structlog-7.0.0.dev1}/pyproject.toml +2 -2
  10. {django-structlog-6.1.0.dev1 → django-structlog-7.0.0.dev1}/LICENSE.rst +0 -0
  11. {django-structlog-6.1.0.dev1 → django-structlog-7.0.0.dev1}/MANIFEST.in +0 -0
  12. {django-structlog-6.1.0.dev1 → django-structlog-7.0.0.dev1}/django_structlog/app_settings.py +0 -0
  13. {django-structlog-6.1.0.dev1 → django-structlog-7.0.0.dev1}/django_structlog/apps.py +0 -0
  14. {django-structlog-6.1.0.dev1 → django-structlog-7.0.0.dev1}/django_structlog/celery/__init__.py +0 -0
  15. {django-structlog-6.1.0.dev1 → django-structlog-7.0.0.dev1}/django_structlog/celery/signals.py +0 -0
  16. {django-structlog-6.1.0.dev1 → django-structlog-7.0.0.dev1}/django_structlog/celery/steps.py +0 -0
  17. {django-structlog-6.1.0.dev1 → django-structlog-7.0.0.dev1}/django_structlog/middlewares/__init__.py +0 -0
  18. {django-structlog-6.1.0.dev1 → django-structlog-7.0.0.dev1}/django_structlog/signals.py +0 -0
  19. {django-structlog-6.1.0.dev1 → django-structlog-7.0.0.dev1}/django_structlog.egg-info/SOURCES.txt +0 -0
  20. {django-structlog-6.1.0.dev1 → django-structlog-7.0.0.dev1}/django_structlog.egg-info/dependency_links.txt +0 -0
  21. {django-structlog-6.1.0.dev1 → django-structlog-7.0.0.dev1}/django_structlog.egg-info/top_level.txt +0 -0
  22. {django-structlog-6.1.0.dev1 → django-structlog-7.0.0.dev1}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: django-structlog
3
- Version: 6.1.0.dev1
3
+ Version: 7.0.0.dev1
4
4
  Summary: Structured Logging for Django
5
5
  Author-email: Jules Robichaud-Gagnon <j.robichaudg+pypi@gmail.com>
6
6
  License: MIT
@@ -29,7 +29,7 @@ License-File: LICENSE.rst
29
29
  Requires-Dist: django>=3.2
30
30
  Requires-Dist: structlog>=21.4.0
31
31
  Requires-Dist: asgiref>=3.6.0
32
- Requires-Dist: django-ipware
32
+ Requires-Dist: django-ipware>=6.0.2
33
33
  Provides-Extra: celery
34
34
  Requires-Dist: celery>=5.1; extra == "celery"
35
35
  Provides-Extra: commands
@@ -399,6 +399,17 @@ Json file (\ ``logs/json.log``\ )
399
399
  Upgrade Guide
400
400
  =============
401
401
 
402
+ .. _upgrade_7.0:
403
+
404
+ Upgrading to 7.0+
405
+ ^^^^^^^^^^^^^^^^^
406
+
407
+ The dependency `django-ipware <https://github.com/un33k/django-ipware>`_ was upgraded to version 6. This library is used to retrieve the request's ip address.
408
+
409
+ Version 6 may have some `breaking changes <https://github.com/un33k/django-ipware/compare/v5.0.2...v6.0.2#diff-b335630551682c19a781afebcf4d07bf978fb1f8ac04c6bf87428ed5106870f5R97>`_ if you did customizations.
410
+
411
+ It should not affect most of the users but if you did some customizations, you might need to update your configurations.
412
+
402
413
  .. _upgrade_6.0:
403
414
 
404
415
  Upgrading to 6.0+
@@ -362,6 +362,17 @@ Json file (\ ``logs/json.log``\ )
362
362
  Upgrade Guide
363
363
  =============
364
364
 
365
+ .. _upgrade_7.0:
366
+
367
+ Upgrading to 7.0+
368
+ ^^^^^^^^^^^^^^^^^
369
+
370
+ The dependency `django-ipware <https://github.com/un33k/django-ipware>`_ was upgraded to version 6. This library is used to retrieve the request's ip address.
371
+
372
+ Version 6 may have some `breaking changes <https://github.com/un33k/django-ipware/compare/v5.0.2...v6.0.2#diff-b335630551682c19a781afebcf4d07bf978fb1f8ac04c6bf87428ed5106870f5R97>`_ if you did customizations.
373
+
374
+ It should not affect most of the users but if you did some customizations, you might need to update your configurations.
375
+
365
376
  .. _upgrade_6.0:
366
377
 
367
378
  Upgrading to 6.0+
@@ -4,6 +4,6 @@
4
4
 
5
5
  name = "django_structlog"
6
6
 
7
- VERSION = (6, 1, 0, "dev1")
7
+ VERSION = (7, 0, 0, "dev1")
8
8
 
9
9
  __version__ = ".".join(str(v) for v in VERSION)
@@ -1,4 +1,16 @@
1
1
  import structlog
2
+ from celery import current_app
3
+ from celery.signals import (
4
+ before_task_publish,
5
+ after_task_publish,
6
+ task_prerun,
7
+ task_retry,
8
+ task_success,
9
+ task_failure,
10
+ task_revoked,
11
+ task_unknown,
12
+ task_rejected,
13
+ )
2
14
 
3
15
  from . import signals
4
16
 
@@ -19,9 +31,7 @@ class CeleryReceiver:
19
31
  routing_key=None,
20
32
  **kwargs,
21
33
  ):
22
- import celery
23
-
24
- if celery.current_app.conf.task_protocol < 2:
34
+ if current_app.conf.task_protocol < 2:
25
35
  return
26
36
 
27
37
  context = structlog.contextvars.get_merged_contextvars(logger)
@@ -128,27 +138,10 @@ class CeleryReceiver:
128
138
  )
129
139
 
130
140
  def connect_signals(self):
131
- from celery.signals import (
132
- before_task_publish,
133
- after_task_publish,
134
- )
135
-
136
141
  before_task_publish.connect(self.receiver_before_task_publish)
137
142
  after_task_publish.connect(self.receiver_after_task_publish)
138
143
 
139
144
  def connect_worker_signals(self):
140
- from celery.signals import (
141
- before_task_publish,
142
- after_task_publish,
143
- task_prerun,
144
- task_retry,
145
- task_success,
146
- task_failure,
147
- task_revoked,
148
- task_unknown,
149
- task_rejected,
150
- )
151
-
152
145
  before_task_publish.connect(self.receiver_before_task_publish)
153
146
  after_task_publish.connect(self.receiver_after_task_publish)
154
147
  task_prerun.connect(self.receiver_task_prerun)
@@ -1,6 +1,8 @@
1
1
  import structlog
2
2
  import uuid
3
3
 
4
+ from django_extensions.management.signals import pre_command, post_command
5
+
4
6
  logger = structlog.getLogger(__name__)
5
7
 
6
8
 
@@ -32,10 +34,5 @@ class DjangoCommandReceiver:
32
34
  structlog.contextvars.reset_contextvars(**tokens)
33
35
 
34
36
  def connect_signals(self):
35
- try:
36
- from django_extensions.management.signals import pre_command, post_command
37
- except ModuleNotFoundError: # pragma: no cover
38
- return
39
-
40
37
  pre_command.connect(self.pre_receiver)
41
38
  post_command.connect(self.post_receiver)
@@ -1,10 +1,11 @@
1
+ import asyncio
1
2
  import logging
2
3
  import uuid
3
4
 
4
5
  import structlog
5
6
  from asgiref.sync import iscoroutinefunction, markcoroutinefunction
6
7
  from django.core.exceptions import PermissionDenied
7
- from django.http import Http404
8
+ from django.http import Http404, StreamingHttpResponse
8
9
  from asgiref import sync
9
10
 
10
11
  from .. import signals
@@ -20,13 +21,69 @@ def get_request_header(request, header_key, meta_key):
20
21
  return request.META.get(meta_key)
21
22
 
22
23
 
23
- class BaseRequestMiddleWare:
24
+ def sync_streaming_content_wrapper(streaming_content, context):
25
+ with structlog.contextvars.bound_contextvars(**context):
26
+ logger.info("streaming_started")
27
+ try:
28
+ for chunk in streaming_content:
29
+ yield chunk
30
+ except Exception:
31
+ logger.exception("streaming_failed")
32
+ else:
33
+ logger.info("streaming_finished")
34
+
35
+
36
+ async def async_streaming_content_wrapper(streaming_content, context):
37
+ with structlog.contextvars.bound_contextvars(**context):
38
+ logger.info("streaming_started")
39
+ try:
40
+ async for chunk in streaming_content:
41
+ yield chunk
42
+ except asyncio.CancelledError:
43
+ logger.warning("streaming_cancelled")
44
+ raise
45
+ except Exception:
46
+ logger.exception("streaming_failed")
47
+ else:
48
+ logger.info("streaming_finished")
49
+
50
+
51
+ class RequestMiddleware:
52
+ """``RequestMiddleware`` adds request metadata to ``structlog``'s logger context automatically.
53
+
54
+ >>> MIDDLEWARE = [
55
+ ... # ...
56
+ ... 'django_structlog.middlewares.RequestMiddleware',
57
+ ... ]
58
+
59
+ """
60
+
61
+ sync_capable = True
62
+ async_capable = True
63
+
24
64
  def __init__(self, get_response):
25
65
  self.get_response = get_response
66
+ if iscoroutinefunction(self.get_response):
67
+ markcoroutinefunction(self)
68
+
69
+ def __call__(self, request):
70
+ if iscoroutinefunction(self):
71
+ return self.__acall__(request)
72
+ self.prepare(request)
73
+ response = self.get_response(request)
74
+ self.handle_response(request, response)
75
+ return response
76
+
77
+ async def __acall__(self, request):
78
+ await sync.sync_to_async(self.prepare)(request)
79
+ response = await self.get_response(request)
80
+ await sync.sync_to_async(self.handle_response)(request, response)
81
+ return response
26
82
 
27
83
  def handle_response(self, request, response):
28
84
  if not hasattr(request, "_raised_exception"):
29
85
  self.bind_user_id(request)
86
+ context = structlog.contextvars.get_merged_contextvars(logger)
30
87
  signals.bind_extra_request_finished_metadata.send(
31
88
  sender=self.__class__,
32
89
  request=request,
@@ -45,6 +102,19 @@ class BaseRequestMiddleWare:
45
102
  code=response.status_code,
46
103
  request=self.format_request(request),
47
104
  )
105
+ if isinstance(response, StreamingHttpResponse):
106
+ streaming_content = response.streaming_content
107
+ try:
108
+ iter(streaming_content)
109
+ except TypeError:
110
+ response.streaming_content = async_streaming_content_wrapper(
111
+ streaming_content, context
112
+ )
113
+ else:
114
+ response.streaming_content = sync_streaming_content_wrapper(
115
+ streaming_content, context
116
+ )
117
+
48
118
  else:
49
119
  exception = getattr(request, "_raised_exception")
50
120
  delattr(request, "_raised_exception")
@@ -85,6 +155,16 @@ class BaseRequestMiddleWare:
85
155
  def format_request(request):
86
156
  return f"{request.method} {request.get_full_path()}"
87
157
 
158
+ @staticmethod
159
+ def bind_user_id(request):
160
+ if hasattr(request, "user") and request.user is not None:
161
+ user_id = None
162
+ if hasattr(request.user, "pk"):
163
+ user_id = request.user.pk
164
+ if isinstance(user_id, uuid.UUID):
165
+ user_id = str(user_id)
166
+ structlog.contextvars.bind_contextvars(user_id=user_id)
167
+
88
168
  def process_exception(self, request, exception):
89
169
  if isinstance(exception, (Http404, PermissionDenied)):
90
170
  # We don't log an exception here, and we don't set that we handled
@@ -105,46 +185,3 @@ class BaseRequestMiddleWare:
105
185
  code=500,
106
186
  request=self.format_request(request),
107
187
  )
108
-
109
- @staticmethod
110
- def bind_user_id(request):
111
- if hasattr(request, "user") and request.user is not None:
112
- user_id = None
113
- if hasattr(request.user, "pk"):
114
- user_id = request.user.pk
115
- if isinstance(user_id, uuid.UUID):
116
- user_id = str(user_id)
117
- structlog.contextvars.bind_contextvars(user_id=user_id)
118
-
119
-
120
- class RequestMiddleware(BaseRequestMiddleWare):
121
- """``RequestMiddleware`` adds request metadata to ``structlog``'s logger context automatically.
122
-
123
- >>> MIDDLEWARE = [
124
- ... # ...
125
- ... 'django_structlog.middlewares.RequestMiddleware',
126
- ... ]
127
-
128
- """
129
-
130
- sync_capable = True
131
- async_capable = True
132
-
133
- def __init__(self, get_response):
134
- super().__init__(get_response)
135
- if iscoroutinefunction(self.get_response):
136
- markcoroutinefunction(self)
137
-
138
- def __call__(self, request):
139
- if iscoroutinefunction(self):
140
- return self.__acall__(request)
141
- self.prepare(request)
142
- response = self.get_response(request)
143
- self.handle_response(request, response)
144
- return response
145
-
146
- async def __acall__(self, request):
147
- await sync.sync_to_async(self.prepare)(request)
148
- response = await self.get_response(request)
149
- await sync.sync_to_async(self.handle_response)(request, response)
150
- return response
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: django-structlog
3
- Version: 6.1.0.dev1
3
+ Version: 7.0.0.dev1
4
4
  Summary: Structured Logging for Django
5
5
  Author-email: Jules Robichaud-Gagnon <j.robichaudg+pypi@gmail.com>
6
6
  License: MIT
@@ -29,7 +29,7 @@ License-File: LICENSE.rst
29
29
  Requires-Dist: django>=3.2
30
30
  Requires-Dist: structlog>=21.4.0
31
31
  Requires-Dist: asgiref>=3.6.0
32
- Requires-Dist: django-ipware
32
+ Requires-Dist: django-ipware>=6.0.2
33
33
  Provides-Extra: celery
34
34
  Requires-Dist: celery>=5.1; extra == "celery"
35
35
  Provides-Extra: commands
@@ -399,6 +399,17 @@ Json file (\ ``logs/json.log``\ )
399
399
  Upgrade Guide
400
400
  =============
401
401
 
402
+ .. _upgrade_7.0:
403
+
404
+ Upgrading to 7.0+
405
+ ^^^^^^^^^^^^^^^^^
406
+
407
+ The dependency `django-ipware <https://github.com/un33k/django-ipware>`_ was upgraded to version 6. This library is used to retrieve the request's ip address.
408
+
409
+ Version 6 may have some `breaking changes <https://github.com/un33k/django-ipware/compare/v5.0.2...v6.0.2#diff-b335630551682c19a781afebcf4d07bf978fb1f8ac04c6bf87428ed5106870f5R97>`_ if you did customizations.
410
+
411
+ It should not affect most of the users but if you did some customizations, you might need to update your configurations.
412
+
402
413
  .. _upgrade_6.0:
403
414
 
404
415
  Upgrading to 6.0+
@@ -1,7 +1,7 @@
1
1
  django>=3.2
2
2
  structlog>=21.4.0
3
3
  asgiref>=3.6.0
4
- django-ipware
4
+ django-ipware>=6.0.2
5
5
 
6
6
  [celery]
7
7
  celery>=5.1
@@ -16,7 +16,7 @@ build-backend = "setuptools.build_meta"
16
16
  "django>=3.2",
17
17
  "structlog>=21.4.0",
18
18
  "asgiref>=3.6.0",
19
- "django-ipware",
19
+ "django-ipware>=6.0.2",
20
20
  ]
21
21
  classifiers = [
22
22
  "Development Status :: 5 - Production/Stable",
@@ -129,7 +129,7 @@ build-backend = "setuptools.build_meta"
129
129
  django32: Django >=3.2, <4.0
130
130
  django41: Django >=4.1, <4.2
131
131
  django42: Django >=4.2, <5.0
132
- django50: Django ==5.0a1
132
+ django50: Django >=5.0, <5.1
133
133
  -r{toxinidir}/requirements/ci.txt
134
134
 
135
135
  commands = pytest --cov=./test_app --cov=./django_structlog --cov-append test_app