Skip to content

Commit 77306f5

Browse files
committed
refactor: aiohttp span attributes
1 parent 668f974 commit 77306f5

File tree

3 files changed

+195
-129
lines changed

3 files changed

+195
-129
lines changed

pdm.lock

Lines changed: 4 additions & 31 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/asgi_monitor/integrations/aiohttp.py

Lines changed: 55 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,7 @@
55

66
from aiohttp.web import Application, Request, Response, middleware
77
from aiohttp.web_exceptions import HTTPException, HTTPInternalServerError
8-
from multidict import CIMultiDictProxy # noqa: TCH002
98
from opentelemetry import trace
10-
from opentelemetry.instrumentation.asgi import collect_request_attributes
119
from opentelemetry.instrumentation.utils import http_status_to_status_code
1210
from opentelemetry.metrics import Meter, MeterProvider, get_meter_provider
1311
from opentelemetry.propagate import extract
@@ -32,75 +30,39 @@
3230
_OTEL_SCHEMA = "https://opentelemetry.io/schemas/1.11.0"
3331

3432

35-
_DURATION_ATTRS = [
36-
SpanAttributes.HTTP_METHOD,
37-
SpanAttributes.HTTP_HOST,
38-
SpanAttributes.HTTP_SCHEME,
39-
SpanAttributes.HTTP_STATUS_CODE,
40-
SpanAttributes.HTTP_FLAVOR,
41-
SpanAttributes.HTTP_SERVER_NAME,
42-
SpanAttributes.NET_HOST_NAME,
43-
SpanAttributes.NET_HOST_PORT,
44-
SpanAttributes.HTTP_ROUTE,
45-
]
46-
47-
_ACTIVE_REQUESTS_COUNT_ATTRS = [
48-
SpanAttributes.HTTP_METHOD,
49-
SpanAttributes.HTTP_HOST,
50-
SpanAttributes.HTTP_SCHEME,
51-
SpanAttributes.HTTP_FLAVOR,
52-
SpanAttributes.HTTP_SERVER_NAME,
53-
]
54-
55-
5633
class AiohttpGetter(Getter):
57-
def get(self, carrier: dict, key: str) -> list | None:
58-
headers: CIMultiDictProxy = carrier.headers # type: ignore[attr-defined]
59-
if not headers:
60-
return None
61-
return headers.getall(key, None)
34+
def get(self, carrier: Request, key: str) -> list[str] | None:
35+
headers = carrier.headers
36+
return headers.getall(key, None) if headers else None
6237

63-
def keys(self, carrier: dict) -> list:
38+
def keys(self, carrier: Request) -> list[str]:
6439
return list(carrier.keys())
6540

6641

67-
def _get_tracer(tracer_provider: TracerProvider | None = None) -> Tracer:
68-
return trace.get_tracer(
69-
__name__,
70-
tracer_provider=tracer_provider,
71-
schema_url=_OTEL_SCHEMA,
72-
)
73-
74-
75-
def _get_meter(
76-
name: str,
77-
meter_provider: MeterProvider | None = None,
78-
schema_url: str | None = None,
79-
) -> Meter:
80-
if meter_provider is None:
81-
meter_provider = get_meter_provider()
82-
return meter_provider.get_meter(name=name, schema_url=schema_url)
83-
84-
85-
def _parse_duration_attrs(req_attrs: dict[str, Any]) -> dict[str, Any]:
86-
duration_attrs = {}
87-
for attr_key in _DURATION_ATTRS:
88-
if req_attrs.get(attr_key) is not None:
89-
duration_attrs[attr_key] = req_attrs[attr_key]
90-
return duration_attrs
91-
92-
93-
def _parse_active_request_count_attrs(req_attrs: dict[str, Any]) -> dict[str, Any]:
94-
active_requests_count_attrs = {}
95-
for attr_key in _ACTIVE_REQUESTS_COUNT_ATTRS:
96-
if req_attrs.get(attr_key) is not None:
97-
active_requests_count_attrs[attr_key] = req_attrs[attr_key]
98-
return active_requests_count_attrs
99-
100-
101-
def _get_default_span_details(request: Request) -> tuple[str, dict]:
102-
span_name = request.path.strip() or f"HTTP {request.method}"
103-
return span_name, {}
42+
def _get_default_span_details(request: Request) -> tuple[str, dict[str, Any]]:
43+
span_attributes: dict[str, Any] = {
44+
SpanAttributes.HTTP_SCHEME: request.scheme,
45+
SpanAttributes.HTTP_HOST: request.host,
46+
SpanAttributes.NET_HOST_PORT: request.url.port,
47+
SpanAttributes.HTTP_FLAVOR: f"{request.version.major}.{request.version.minor}",
48+
SpanAttributes.HTTP_TARGET: request.path_qs,
49+
SpanAttributes.HTTP_URL: str(request.url),
50+
SpanAttributes.HTTP_METHOD: request.method,
51+
SpanAttributes.HTTP_SERVER_NAME: request.headers.get("Host", ""),
52+
SpanAttributes.HTTP_USER_AGENT: request.headers.get("User-Agent", ""),
53+
SpanAttributes.NET_PEER_IP: request.remote,
54+
}
55+
56+
if request.transport:
57+
span_attributes[SpanAttributes.NET_PEER_PORT] = request.transport.get_extra_info("peername")[1]
58+
if request.match_info.route and request.match_info.route.resource:
59+
route = request.match_info.route.resource.canonical
60+
span_attributes[SpanAttributes.HTTP_ROUTE] = route
61+
else:
62+
route = request.path
63+
span_attributes[SpanAttributes.HTTP_ROUTE] = route
64+
65+
return f"{request.method} {route or 'unknown'}", span_attributes
10466

10567

10668
def _set_status_code(span: trace.Span, status_code: int) -> None:
@@ -216,19 +178,21 @@ def build_tracing_middleware(config: TracingConfig) -> Callable[..., Coroutine]:
216178

217179
@middleware
218180
async def tracing_middleware(request: Request, handler: Callable) -> Any:
219-
span_name, additional_attributes = config.scope_span_details_extractor(request)
220-
221-
req_attrs = collect_request_attributes(request)
222-
duration_attrs = _parse_duration_attrs(req_attrs)
223-
active_requests_count_attrs = _parse_active_request_count_attrs(req_attrs)
181+
span_name, attributes = config.scope_span_details_extractor(request)
182+
active_requests_count_attrs = {
183+
SpanAttributes.HTTP_SERVER_NAME: attributes[SpanAttributes.HTTP_SERVER_NAME],
184+
SpanAttributes.HTTP_SCHEME: attributes[SpanAttributes.HTTP_SCHEME],
185+
SpanAttributes.HTTP_HOST: attributes[SpanAttributes.HTTP_HOST],
186+
SpanAttributes.HTTP_FLAVOR: attributes[SpanAttributes.HTTP_FLAVOR],
187+
SpanAttributes.HTTP_METHOD: attributes[SpanAttributes.HTTP_METHOD],
188+
}
189+
duration_attrs = {SpanAttributes.HTTP_ROUTE: attributes[SpanAttributes.HTTP_ROUTE]}
224190

225191
with tracer.start_as_current_span(
226192
span_name,
227193
context=extract(request, getter=getter),
228194
kind=trace.SpanKind.SERVER,
229195
) as span:
230-
attributes = collect_request_attributes(request)
231-
attributes.update(additional_attributes)
232196
span.set_attributes(attributes)
233197
start = default_timer()
234198
active_requests_counter.add(1, active_requests_count_attrs)
@@ -275,3 +239,21 @@ def setup_metrics(app: Application, config: MetricsConfig) -> None:
275239

276240
def setup_tracing(app: Application, config: TracingConfig) -> None:
277241
app.middlewares.append(build_tracing_middleware(config))
242+
243+
244+
def _get_tracer(tracer_provider: TracerProvider | None = None) -> Tracer:
245+
return trace.get_tracer(
246+
__name__,
247+
tracer_provider=tracer_provider,
248+
schema_url=_OTEL_SCHEMA,
249+
)
250+
251+
252+
def _get_meter(
253+
name: str,
254+
meter_provider: MeterProvider | None = None,
255+
schema_url: str | None = None,
256+
) -> Meter:
257+
if meter_provider is None:
258+
meter_provider = get_meter_provider()
259+
return meter_provider.get_meter(name=name, schema_url=schema_url)

0 commit comments

Comments
 (0)