|
| 1 | +import contextlib |
| 2 | +import logging |
| 3 | +from typing import TYPE_CHECKING, Any |
| 4 | + |
| 5 | +from aiohttp.web_log import AccessLogger |
| 6 | +from aiohttp.web_request import BaseRequest |
| 7 | +from aiohttp.web_response import StreamResponse |
| 8 | +from opentelemetry import trace |
| 9 | + |
| 10 | +if TYPE_CHECKING: |
| 11 | + from opentelemetry.trace import Span |
| 12 | + |
| 13 | +__all__ = ("TraceAccessLogger",) |
| 14 | + |
| 15 | + |
| 16 | +class TraceAccessLogger(AccessLogger): |
| 17 | + def log(self, request: BaseRequest, response: StreamResponse, time: float) -> None: |
| 18 | + if not self.logger.isEnabledFor(logging.INFO): |
| 19 | + # Avoid formatting the log line if it will not be emitted. |
| 20 | + return |
| 21 | + try: |
| 22 | + fmt_info = self._format_line(request, response, time) |
| 23 | + |
| 24 | + values = [] |
| 25 | + extra: dict[str, Any] = {} |
| 26 | + for key, value in fmt_info: |
| 27 | + values.append(value) |
| 28 | + |
| 29 | + if key.__class__ is str: |
| 30 | + extra[key] = value |
| 31 | + else: |
| 32 | + k1, k2 = key # type: ignore[misc] |
| 33 | + dct = extra.get(k1, {}) # type: ignore[has-type] |
| 34 | + dct[k2] = value # type: ignore[has-type] |
| 35 | + extra[k1] = dct # type: ignore[has-type] |
| 36 | + |
| 37 | + with contextlib.suppress(KeyError, ValueError): |
| 38 | + span: Span = request.span # type: ignore[attr-defined] |
| 39 | + ctx = span.get_span_context() |
| 40 | + service_name = trace.get_tracer_provider().resource.attributes["service.name"] # type: ignore[attr-defined] |
| 41 | + parent = getattr(span, "parent", None) |
| 42 | + |
| 43 | + extra["span_id"] = trace.format_span_id(ctx.span_id) |
| 44 | + extra["trace_id"] = trace.format_trace_id(ctx.trace_id) |
| 45 | + extra["service.name"] = service_name |
| 46 | + |
| 47 | + if parent: |
| 48 | + extra["parent_span_id"] = trace.format_span_id(parent.span_id) |
| 49 | + |
| 50 | + self.logger.info(self._log_format % tuple(values), extra=extra) |
| 51 | + except Exception: |
| 52 | + self.logger.exception("Error in logging") |
0 commit comments