Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Psycopg3 sync and async instrumentation #2146

Merged
merged 27 commits into from
Mar 19, 2024
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
cf404fa
* psycopg3 instrumentation including asynchronous instrumentation
reiktar Jan 31, 2024
dc78394
* Updating documents
reiktar Jan 31, 2024
b2d490d
* adding Pullrequest link to changelog
reiktar Jan 31, 2024
0b12d9b
* adding github workflow for psycopg3 instrumentation testing
reiktar Jan 31, 2024
f8c349c
* updates to pass PR checks
reiktar Feb 2, 2024
f4abf01
Merge branch 'main' into psycopg3-instrumentation
reiktar Feb 5, 2024
a897b6c
Merge branch 'main' into psycopg3-instrumentation
reiktar Feb 20, 2024
057504a
Merge branch 'main' into psycopg3-instrumentation
reiktar Mar 1, 2024
953a113
* refactor on package name psycopg insteead of psycopg3
reiktar Mar 1, 2024
dafc587
* updating Changlog to reflect the new PR scope
reiktar Mar 1, 2024
8731ff9
* Cleaning up as per comments in #2146
reiktar Mar 4, 2024
9098939
* WRAPT_DISABLE_EXTENSIONS is nolonger required
reiktar Mar 4, 2024
9d2f79b
Merge branch 'main' into psycopg3-instrumentation
reiktar Mar 4, 2024
02d2295
Merge branch 'main' into psycopg3-instrumentation
reiktar Mar 11, 2024
b812e01
Merge branch 'main' into psycopg3-instrumentation
reiktar Mar 13, 2024
d38532a
* move changelog entry to unreleased section
reiktar Mar 14, 2024
f1f1780
* move changelog entry to unreleased section
reiktar Mar 14, 2024
f577330
Merge branch 'main' into psycopg3-instrumentation
reiktar Mar 14, 2024
8c95c88
* remove lingering newline
reiktar Mar 14, 2024
09890a4
* lingering refrerence to Psycopg3Instrumentor (hold over from the or…
reiktar Mar 14, 2024
dca2adb
Merge branch 'main' into psycopg3-instrumentation
lzchen Mar 14, 2024
6025de9
* linting + black
reiktar Mar 15, 2024
08e0c50
* Contribute.MD should point out that manually running black must use…
reiktar Mar 15, 2024
55b6f55
* isort and pylint disagrees on where to have the pylint options. Thi…
reiktar Mar 18, 2024
3543b7b
Merge branch 'main' into psycopg3-instrumentation
reiktar Mar 18, 2024
ee377d6
Merge branch 'main' into psycopg3-instrumentation
ocelotl Mar 18, 2024
9c450f4
Merge branch 'main' into psycopg3-instrumentation
lzchen Mar 19, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Added

- `opentelemtetry-instrumentation-psycopg3` Async Instrumentation for psycopg 3.x
reiktar marked this conversation as resolved.
Show resolved Hide resolved
([#2146](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2146))
- `opentelemetry-instrumentation-psycopg` Initial release for psycopg 3.x

## Version 1.22.0/0.43b0 (2023-12-14)

### Added

- `opentelemetry-instrumentation-asyncio` Add support for asyncio
([#1919](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1943))
- `opentelemetry-instrumentation` Added Otel semantic convention opt-in mechanism
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@
from typing import Collection

import psycopg
from psycopg import AsyncCursor as pg_async_cursor
from psycopg import Cursor as pg_cursor # pylint: disable=no-name-in-module
from psycopg.sql import Composed # pylint: disable=no-name-in-module

Expand Down Expand Up @@ -151,9 +152,36 @@ def _instrument(self, **kwargs):
commenter_options=commenter_options,
)

dbapi.wrap_connect(
__name__,
psycopg.Connection,
"connect",
self._DATABASE_SYSTEM,
self._CONNECTION_ATTRIBUTES,
version=__version__,
tracer_provider=tracer_provider,
db_api_integration_factory=DatabaseApiIntegration,
enable_commenter=enable_sqlcommenter,
commenter_options=commenter_options,
)
dbapi.wrap_connect(
__name__,
psycopg.AsyncConnection,
"connect",
self._DATABASE_SYSTEM,
self._CONNECTION_ATTRIBUTES,
version=__version__,
tracer_provider=tracer_provider,
db_api_integration_factory=DatabaseApiAsyncIntegration,
enable_commenter=enable_sqlcommenter,
commenter_options=commenter_options,
)

def _uninstrument(self, **kwargs):
""" "Disable Psycopg instrumentation"""
dbapi.unwrap_connect(psycopg, "connect")
dbapi.unwrap_connect(psycopg.Connection, "connect")
dbapi.unwrap_connect(psycopg.AsyncConnection, "connect")

# TODO(owais): check if core dbapi can do this for all dbapi implementations e.g, pymysql and mysql
@staticmethod
Expand Down Expand Up @@ -204,6 +232,26 @@ def wrapped_connection(
return connection


class DatabaseApiAsyncIntegration(dbapi.DatabaseApiIntegration):
async def wrapped_connection(
self,
connect_method: typing.Callable[..., typing.Any],
args: typing.Tuple[typing.Any, typing.Any],
kwargs: typing.Dict[typing.Any, typing.Any],
):
"""Add object proxy to connection object."""
base_cursor_factory = kwargs.pop("cursor_factory", None)
new_factory_kwargs = {"db_api": self}
if base_cursor_factory:
new_factory_kwargs["base_factory"] = base_cursor_factory
kwargs["cursor_factory"] = _new_cursor_async_factory(
**new_factory_kwargs
)
connection = await connect_method(*args, **kwargs)
self.get_connection_attributes(connection)
return connection


class CursorTracer(dbapi.CursorTracer):
def get_operation_name(self, cursor, args):
if not args:
Expand Down Expand Up @@ -259,3 +307,36 @@ def callproc(self, *args, **kwargs):
)

return TracedCursorFactory


def _new_cursor_async_factory(
db_api=None, base_factory=None, tracer_provider=None
):
if not db_api:
db_api = DatabaseApiAsyncIntegration(
__name__,
Psycopg3Instrumentor._DATABASE_SYSTEM,
connection_attributes=Psycopg3Instrumentor._CONNECTION_ATTRIBUTES,
version=__version__,
tracer_provider=tracer_provider,
)
base_factory = base_factory or pg_async_cursor
_cursor_tracer = CursorTracer(db_api)

class TracedCursorAsyncFactory(base_factory):
async def execute(self, *args, **kwargs):
return await _cursor_tracer.traced_execution(
self, super().execute, *args, **kwargs
)

async def executemany(self, *args, **kwargs):
return await _cursor_tracer.traced_execution(
self, super().executemany, *args, **kwargs
)

async def callproc(self, *args, **kwargs):
return await _cursor_tracer.traced_execution(
self, super().callproc, *args, **kwargs
)

return TracedCursorAsyncFactory
Loading
Loading