asyncpg: report unix socket connections as network.transport=unix - #4925
asyncpg: report unix socket connections as network.transport=unix#4925chuenchen309 wants to merge 2 commits into
Conversation
_hydrate_span_from_args set network.transport to "pipe" for a string _addr, which asyncpg uses exclusively for unix domain sockets. Semconv defines "pipe" as a named or anonymous pipe and "unix" as a unix domain socket, so the value was wrong for every socket-based connection. The redis instrumentation already reports "unix" for the same case. Only the new semconv value changes; net.transport keeps "other" under the default mode. Assisted-by: Claude Opus 5
Assisted-by: Claude Opus 5
|
Thanks for the PR, is there an issue filed for this or a reproducer? |
|
No issue filed — before opening I searched the tracker for both the identifiers ( Here's a reproducer against a real server, with the TCP connection as a control group so it's visible that only the unix-socket branch is affected. PostgreSQL 16.2 listening on both a unix socket and import asyncio, sys
import asyncpg
from opentelemetry.instrumentation.asyncpg import AsyncPGInstrumentor
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import SimpleSpanProcessor
from opentelemetry.sdk.trace.export.in_memory_span_exporter import InMemorySpanExporter
exporter = InMemorySpanExporter()
provider = TracerProvider()
provider.add_span_processor(SimpleSpanProcessor(exporter))
AsyncPGInstrumentor().instrument(tracer_provider=provider)
async def run(**kw):
conn = await asyncpg.connect(user="postgres", database="postgres", port=55433, **kw)
print(" Connection._addr =", repr(conn._addr))
await conn.execute("SELECT 1")
await conn.close()
def dump(label):
for s in exporter.get_finished_spans():
print(f" {label}:", {k: v for k, v in s.attributes.items()
if k.startswith(("network.", "net.", "server."))})
exporter.clear()
asyncio.run(run(host=sys.argv[1])); dump("unix")
asyncio.run(run(host="127.0.0.1")); dump("tcp")
Same command with this PR applied — only the I ran the other two modes on the patched tree as well, since this touches
One thing that turned up while checking, independent of whether this lands: the same "addr is a str ⇒ unix socket" branch exists in three instrumentations and they disagree. AI-assisted with agentic coding tools; all changes were reviewed and tested by me. |
Description
_hydrate_span_from_argsreportsnetwork.transportaspipewhen asyncpg'sConnection._addris a string. asyncpg uses a string_addrexclusively for unix domainsockets:
connect_utils.pybuilds the.s.PGSQL.<port>path for any host starting with/("UNIX socket name") and
__connect_addrbranches onisinstance(addr, str)to callloop.create_unix_connection().Semconv defines
pipeas "Named or anonymous pipe" andunixas "Unix domain socket", soevery socket-based connection reported the wrong transport under the new semconv. The redis
instrumentation already reports
unixfor the same case.Only the new semconv value changes —
net.transportkeepsotherunder the default mode,which also matches redis.
Type of change
How Has This Been Tested?
test_span_unix_socket_new_semconv. Without the one-line fix it fails withAssertionError: 'pipe' != 'unix'; with it, it passes.pytest instrumentation/opentelemetry-instrumentation-asyncpg/tests— 21 passed(20 before this PR).
ruff checkandruff format --checkclean.The existing
test_span_unix_socket_default_semconvonly covered the default mode, which iswhy this was not caught.
Does This PR Require a Core Repo Change?
Checklist: