-
Notifications
You must be signed in to change notification settings - Fork 820
Closed
Labels
bugSomething isn't workingSomething isn't working
Description
Describe your environment
OS: Debian Trixie (13)
Python version: 3.13
Package version: 0.58b0
What happened?
I was trying to hunt down the source of a mysterious error on my server startup.
I finally narrowed it down to opentelemetry-instrumentation-psycopg, with error:
File "/opt/python/lib/python3.13/site-packages/opentelemetry/instrumentation/dbapi/__init__.py", line 317, in __init__
self.commenter_data = self.calculate_commenter_data()
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^
File "/opt/python/lib/python3.13/site-packages/opentelemetry/instrumentation/dbapi/__init__.py", line 356, in calculate_commenter_data
libpq_version = self.connect_module.pq.__build_version__
^^^^^^^^^^^^^^^^^^^^^^
AttributeError: type object 'AsyncConnection' has no attribute 'pq'
The relevant part of code is:
Lines 352 to 357 in 4ae8662
| if self.database_system == "postgresql": | |
| if hasattr(self.connect_module, "__libpq_version__"): | |
| libpq_version = self.connect_module.__libpq_version__ | |
| else: | |
| libpq_version = self.connect_module.pq.__build_version__ | |
| commenter_data.update({"libpq_version": libpq_version}) |
I'm not sure if either:
- psycopg (3) doesn't correctly implement the
pgattribute of the AsyncConnector class, or .pgisn't valid in the Python DBAPI 2.0 spec
psycopg2 previously had libpq_version to access on the connection object, so this worked fine.
psycopg has a few equivalent attributes on the top level module, instead of the connection object.
Steps to Reproduce
As part of FastAPI web server:
database.py
from typing import Union
import logging
import psycopg
log = logging.getLogger(__name__)
def create_connection(db: Union[str, psycopg.Connection]) -> psycopg.Connection:
"""Get db connection from existing psycopg connection, or URL string.
Args:
db (str, psycopg.Connection):
string or existing db connection.
If `db` is a string, a new connection is generated.
If `db` is a psycopg connection, the connection is reused.
Returns:
conn: DBAPI connection object to generate cursors from.
"""
if isinstance(db, psycopg.Connection):
conn = db
elif isinstance(db, str):
conn = psycopg.connect(db)
else:
msg = "The `db` variable is not a valid string or psycopg connection."
log.error(msg)
raise ValueError(msg)
return connmain.py
@asynccontextmanager
async def lifespan(
app: FastAPI, # dead: disable
) -> AsyncIterator[None]:
"""FastAPI startup/shutdown event."""
log.debug("Starting up FastAPI server")
# Create a pooled db connection and make available in lifespan state
# https://asgi.readthedocs.io/en/latest/specs/lifespan.html#lifespan-state
# NOTE to use within a request (this is wrapped in database.py already):
# from typing import cast
# db_pool = cast(AsyncConnectionPool, request.state.db_pool)
# async with db_pool.connection() as conn:
db_pool = get_db_connection_pool()
log.debug("Opening database connection pool for server")
await db_pool.open()
log.debug("Database pool opened, attaching to lifespan")
yield {"db_pool": db_pool}
# Shutdown events
log.debug("Shutting down FastAPI server")
await db_pool.close()Expected Result
- The instrumentation should either succeed connecting to the database driver, else fail gracefully.
- There should be some error handling here at the very least, and perhaps a warning log.
Actual Result
- Currently the error is not caught, so it halts server startup and causes an infinite loop.
Additional context
No response
Would you like to implement a fix?
None
Tip
React with 👍 to help prioritize this issue. Please use comments to provide useful context, avoiding +1 or me too, to help us triage it. Learn more here.
Metadata
Metadata
Assignees
Labels
bugSomething isn't workingSomething isn't working