4545will exclude requests such as ``https://site/client/123/info`` and ``https://site/xyz/healthcheck``.
4646
4747Request attributes
48- ********************
48+ ******************
4949To extract attributes from Django's request object and use them as span attributes, set the environment variable
5050``OTEL_PYTHON_DJANGO_TRACED_REQUEST_ATTRS`` to a comma delimited list of request attribute names.
5151
5757
5858will extract the ``path_info`` and ``content_type`` attributes from every traced request and add them as span attributes.
5959
60- Django Request object reference: https://docs.djangoproject.com/en/3.1 /ref/request-response/#attributes
60+ * ` Django Request object reference < https://docs.djangoproject.com/en/5.2 /ref/request-response/#attributes>`_
6161
6262Request and Response hooks
63- ***************************
63+ **************************
6464This instrumentation supports request and response hooks. These are functions that get called
6565right after a span is created for a request and right before the span is finished for the response.
6666The hooks can be configured as follows:
@@ -77,8 +77,76 @@ def response_hook(span, request, response):
7777
7878 DjangoInstrumentor().instrument(request_hook=request_hook, response_hook=response_hook)
7979
80- Django Request object: https://docs.djangoproject.com/en/3.1/ref/request-response/#httprequest-objects
81- Django Response object: https://docs.djangoproject.com/en/3.1/ref/request-response/#httpresponse-objects
80+ * `Django Request object <https://docs.djangoproject.com/en/5.2/ref/request-response/#httprequest-objects>`_
81+ * `Django Response object <https://docs.djangoproject.com/en/5.2/ref/request-response/#httpresponse-objects>`_
82+
83+ Adding attributes from middleware context
84+ #########################################
85+ In many Django applications, certain request attributes become available only *after*
86+ specific middlewares have executed. For example:
87+
88+ - ``django.contrib.auth.middleware.AuthenticationMiddleware`` populates ``request.user``
89+ - ``django.contrib.sites.middleware.CurrentSiteMiddleware`` populates ``request.site``
90+
91+ Because the OpenTelemetry instrumentation creates the span **before** Django middlewares run,
92+ these attributes are **not yet available** in the ``request_hook`` stage.
93+
94+ Therefore, such attributes should be safely attached in the **response_hook**, which executes
95+ after Django finishes processing the request (and after all middlewares have completed).
96+
97+ Example: Attaching the authenticated user and current site to the span:
98+
99+ .. code:: python
100+
101+ def response_hook(span, request, response):
102+ # Attach user information if available
103+ if request.user.is_authenticated:
104+ span.set_attribute("enduser.id", request.user.pk)
105+ span.set_attribute("enduser.username", request.user.get_username())
106+
107+ # Attach current site (if provided by CurrentSiteMiddleware)
108+ if hasattr(request, "site"):
109+ span.set_attribute("site.id", getattr(request.site, "pk", None))
110+ span.set_attribute("site.domain", getattr(request.site, "domain", None))
111+
112+ DjangoInstrumentor().instrument(response_hook=response_hook)
113+
114+ This ensures that middleware-dependent context (like user or site information) is properly
115+ recorded once Django’s middleware stack has finished execution.
116+
117+ Custom Django middleware can also attach arbitrary data to the ``request`` object,
118+ which can later be included as span attributes in the ``response_hook``.
119+
120+ * `Django middleware reference <https://docs.djangoproject.com/en/5.2/topics/http/middleware/>`_
121+
122+ Best practices
123+ ##############
124+ - Use **response_hook** (not request_hook) when accessing attributes added by Django middlewares.
125+ - Common middleware-provided attributes include:
126+
127+ - ``request.user`` (AuthenticationMiddleware)
128+ - ``request.site`` (CurrentSiteMiddleware)
129+
130+ - Avoid adding large or sensitive data (e.g., passwords, session tokens, PII) to spans.
131+ - Use **namespaced attribute keys**, e.g., ``enduser.*``, ``site.*``, or ``custom.*``, for clarity.
132+ - Hooks should execute quickly — avoid blocking or long-running operations.
133+ - Hooks can be safely combined with OpenTelemetry **Context propagation** or **Baggage**
134+ for consistent tracing across services.
135+
136+ * `OpenTelemetry semantic conventions <https://opentelemetry.io/docs/specs/semconv/http/http-spans/>`_
137+
138+ Middleware execution order
139+ ##########################
140+ In Django’s request lifecycle, the OpenTelemetry `request_hook` is executed before
141+ the first middleware runs. Therefore:
142+
143+ - At `request_hook` time → only the bare `HttpRequest` object is available.
144+ - After middlewares → `request.user`, `request.site` etc. become available.
145+ - At `response_hook` time → all middlewares (including authentication and site middlewares)
146+ have already run, making it the correct place to attach these attributes.
147+
148+ Developers who need to trace attributes from middlewares should always use `response_hook`
149+ to ensure complete and accurate span data.
82150
83151Capture HTTP request and response headers
84152*****************************************
0 commit comments