|
11 | 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12 | 12 | # See the License for the specific language governing permissions and
|
13 | 13 | # limitations under the License.
|
| 14 | +# pylint: disable=too-many-locals |
14 | 15 |
|
15 | 16 | """
|
16 | 17 | The opentelemetry-instrumentation-asgi package provides an ASGI middleware that can be used
|
@@ -110,7 +111,12 @@ def client_response_hook(span: Span, message: dict):
|
110 | 111 | from opentelemetry.propagate import extract
|
111 | 112 | from opentelemetry.propagators.textmap import Getter, Setter
|
112 | 113 | from opentelemetry.semconv.trace import SpanAttributes
|
113 |
| -from opentelemetry.trace import Span, set_span_in_context |
| 114 | +from opentelemetry.trace import ( |
| 115 | + INVALID_SPAN, |
| 116 | + Span, |
| 117 | + SpanKind, |
| 118 | + set_span_in_context, |
| 119 | +) |
114 | 120 | from opentelemetry.trace.status import Status, StatusCode
|
115 | 121 | from opentelemetry.util.http import remove_url_credentials
|
116 | 122 |
|
@@ -321,39 +327,48 @@ async def __call__(self, scope, receive, send):
|
321 | 327 | if self.excluded_urls and self.excluded_urls.url_disabled(url):
|
322 | 328 | return await self.app(scope, receive, send)
|
323 | 329 |
|
324 |
| - token = context.attach(extract(scope, getter=asgi_getter)) |
325 |
| - server_span_name, additional_attributes = self.default_span_details( |
326 |
| - scope |
327 |
| - ) |
| 330 | + token = ctx = span_kind = None |
| 331 | + |
| 332 | + if trace.get_current_span() is INVALID_SPAN: |
| 333 | + ctx = extract(scope, getter=asgi_getter) |
| 334 | + token = context.attach(ctx) |
| 335 | + span_kind = SpanKind.SERVER |
| 336 | + else: |
| 337 | + ctx = context.get_current() |
| 338 | + span_kind = SpanKind.INTERNAL |
| 339 | + |
| 340 | + span_name, additional_attributes = self.default_span_details(scope) |
328 | 341 |
|
329 | 342 | try:
|
330 | 343 | with self.tracer.start_as_current_span(
|
331 |
| - server_span_name, |
332 |
| - kind=trace.SpanKind.SERVER, |
333 |
| - ) as server_span: |
334 |
| - if server_span.is_recording(): |
| 344 | + span_name, |
| 345 | + context=ctx, |
| 346 | + kind=span_kind, |
| 347 | + ) as current_span: |
| 348 | + if current_span.is_recording(): |
335 | 349 | attributes = collect_request_attributes(scope)
|
336 | 350 | attributes.update(additional_attributes)
|
337 | 351 | for key, value in attributes.items():
|
338 |
| - server_span.set_attribute(key, value) |
| 352 | + current_span.set_attribute(key, value) |
339 | 353 |
|
340 | 354 | if callable(self.server_request_hook):
|
341 |
| - self.server_request_hook(server_span, scope) |
| 355 | + self.server_request_hook(current_span, scope) |
342 | 356 |
|
343 | 357 | otel_receive = self._get_otel_receive(
|
344 |
| - server_span_name, scope, receive |
| 358 | + span_name, scope, receive |
345 | 359 | )
|
346 | 360 |
|
347 | 361 | otel_send = self._get_otel_send(
|
348 |
| - server_span, |
349 |
| - server_span_name, |
| 362 | + current_span, |
| 363 | + span_name, |
350 | 364 | scope,
|
351 | 365 | send,
|
352 | 366 | )
|
353 | 367 |
|
354 | 368 | await self.app(scope, otel_receive, otel_send)
|
355 | 369 | finally:
|
356 |
| - context.detach(token) |
| 370 | + if token: |
| 371 | + context.detach(token) |
357 | 372 |
|
358 | 373 | def _get_otel_receive(self, server_span_name, scope, receive):
|
359 | 374 | @wraps(receive)
|
|
0 commit comments