-
Notifications
You must be signed in to change notification settings - Fork 650
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
Adding psycopg2 integration #298
Adding psycopg2 integration #298
Conversation
ext/opentelemetry-ext-postgresql/tests/test_postgresql_integration.py
Outdated
Show resolved
Hide resolved
|
||
wrapt.wrap_function_wrapper(psycopg2, "connect", wrap) | ||
|
||
class TraceCursor(pgcursor): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why doesn't this use opentelemetry-ext-dbapi from #264? Did you run into the issue I described in https://github.com/open-telemetry/opentelemetry-python/pull/264/files#r348452864? In any case, instead of deriving from pgcursor, you might want to use a wrapt ObjectProxy https://wrapt.readthedocs.io/en/latest/wrappers.html#object-proxy. That way, you could implement a generic solution. Or you could add support for such cursor_factory instrumentations to ext-dbapi.
Another question: What happens if the user manually specifies/sets cursor_factory? Will either our or the user's cursor_factory be ignored?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I based this in current OpenCensus implementation and started working with this before adding dbapi in other PR, makes sense to reuse it as much as possible, cursor_factory in fact will be overriden like you mentioned and is current behavior in OpenCensus, filed a bug for it in OpenCensus and ensure it doesn't happen here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
cursor_factory is a not thing in the Python DB API specification, so I guess it doesn't makes sense to add it in dbapi ext, dbapi ext is currently wrapping connect method, the actual connection and the cursor, in psycopg all of these are implemented in C except connect, that is why we are hooking up to the cursor_factory, so I'm still not sure how we can reuse dbapi ext here, any suggestion would be appreciated.
Using ObjectProxy instead of pgcursor sounds like a good approach
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this could be an extension of the DBAPI PR. looking at the chunk that actually starts a span and sets values, it's very similar to the DBApi functionality.
Although one caveat as a con is the fact that the API is slightly different in that psycopg2 accepts sql.SQL objects rather than just strings, but that could reconciled with a light wrapper on all of them.
ultimately this is an auto-instrumentation though, so as long as we don't expose APIs that people may rely on, we can probably feel safe marking this as a potential refactor.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated the code to use dbapi ext as much as possible, including span attributes related to connection population and actual span creation functionality
ext/opentelemetry-ext-postgresql/src/opentelemetry/ext/postgresql/__init__.py
Outdated
Show resolved
Hide resolved
I would like to reuse dbapi package being added here #264, I will update this PR once is available |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall code looks good, things that are blockers IMO are:
- no basic unit test
- no handling of more complex objects as the first argument of the execute call, which will lead to a casting exception.
# limitations under the License. | ||
# | ||
[metadata] | ||
name = opentelemetry-ext-postgresql |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is this the right name for the package? I guess there's a few different DBAPI options available: https://docs.sqlalchemy.org/en/13/dialects/postgresql.html
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated to psycopg2
ext/opentelemetry-ext-postgresql/src/opentelemetry/ext/postgresql/__init__.py
Outdated
Show resolved
Hide resolved
ext/opentelemetry-ext-postgresql/src/opentelemetry/ext/postgresql/__init__.py
Outdated
Show resolved
Hide resolved
ext/opentelemetry-ext-postgresql/src/opentelemetry/ext/postgresql/__init__.py
Outdated
Show resolved
Hide resolved
|
||
wrapt.wrap_function_wrapper(psycopg2, "connect", wrap) | ||
|
||
class TraceCursor(pgcursor): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this could be an extension of the DBAPI PR. looking at the chunk that actually starts a span and sets values, it's very similar to the DBApi functionality.
Although one caveat as a con is the fact that the API is slightly different in that psycopg2 accepts sql.SQL objects rather than just strings, but that could reconciled with a light wrapper on all of them.
ultimately this is an auto-instrumentation though, so as long as we don't expose APIs that people may rely on, we can probably feel safe marking this as a potential refactor.
@toumorokoshi and @Oberon00 I updated this to consume dbapi ext, added basic integration test, this would be super easy to test with functional tests similar to #340 would be happy to add them using similar approach, let me know if you have more feedback |
Codecov Report
@@ Coverage Diff @@
## master #298 +/- ##
=========================================
+ Coverage 84.82% 85.13% +0.3%
=========================================
Files 38 38
Lines 1839 1911 +72
Branches 217 225 +8
=========================================
+ Hits 1560 1627 +67
- Misses 214 219 +5
Partials 65 65
Continue to review full report at Codecov.
|
with mock.patch("psycopg2.connect"): | ||
trace_integration(tracer) | ||
cnx = psycopg2.connect(database="test") | ||
self.assertIsNotNone(cnx.cursor_factory) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe the test for trace_integration
should include to see if the functions are successfully decorated.
As well, the query functions themselves and the Cursor
should also have tests.
See OpenCensus
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm only decorating the connect method and this will add the cursor factory, not sure if wrapt will add some "decorated" property, psycopg2 internally will instantiate PsycopgTraceCursor that just call dbapi traced_execution that is already tested, unit tests are hard in here because if the mixed Python/c execution, I believe functional tests would be way more useful and easier to implement, did't want to add them yet until #340 is complete and people are ok with that kind of approach
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM save the basic unit tests.
@hectorhdzg FYI [#360] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM! Sounds good on deeper testing when the functional testing pattern is added in.
@hectorhdzg looks good! Can you resolve conflicts (looks like there was some styling stuff on the readmes that conflict with master) and then I can merge? |
Took OpenCensus implementation as starting point for this one, we store more properties in traces now and we use tracer provided during trace_integration method
https://github.com/census-instrumentation/opencensus-python/tree/master/contrib/opencensus-ext-postgresql
psycopg docs
http://initd.org/psycopg/docs/index.html
#265