If you attempt to register an extension with psycopg2 and happen to use the newrelic python client library you may get an error that looks like this
File "/opt/balanced/embedded/lib/python2.7/site-packages/psycopg2/_json.py", line 142, in register_default_json
loads=loads, oid=JSON_OID, array_oid=JSONARRAY_OID)
File "/opt/balanced/embedded/lib/python2.7/site-packages/psycopg2/_json.py", line 125, in register_json
register_type(JSON, not globally and conn_or_curs or None)
TypeError: argument 2 must be a connection, cursor or None
The issue you're running into is that newrelic decides to play god and replace the connection object with a proxy that it implements called ConnectionWrapper.
This is a problem because psycopg2 has some code that inspects the type of object in order to determine what how to register the extension.
Luckily SQLAlchemy checks for a handy method called _sqla_unwrap
which can be used to get the underlying connection and pass it to psycopg. I guess the engineers at newrelic didn't get around to testing this scenario and their code includes a bunch of anonymous classes so it's hard to inherit the object and patch it yourself. Here's how you can fix it yourself:
Write some code to patch the connection class
class NewRelicConnectionWrapperProxy(object):
def __init__(self, connect):
self.__connect = connect
def __call__(self, *args, **kwargs):
cxn = self.__connect(*args, **kwargs)
object.__setattr__(cxn, '_sqla_unwrap', cxn._nr_connection)
return cxn
Now, after you initialize the newrelic agent but before you initialize your database connection you can monkey patch everything:
import newrelic.agent
newrelic.agent.initialize(config_file, environment)
import psycopg2
psycopg2.connect = NewRelicConnectionWrapperProxy(psycopg2.connect)
That's all there is to it. I hope this is handy for someone.
To New Relic devs: If you fix this, please do not use anonymous classes, it's really hard to extend your code when you cannot inherit and override a class!
Thanks for the solution, but it only works with newrelic<=2.0.0.1. In newrelic>=2.10.0.8 there are a lot of new proxy/wrapper magic with
__setattr__
and__getattr__
definitions. In new versions thepsycopg.connection
is stored incxn.__wrapped__
property instead of_nr_connection
(as it was before). But there is still an issue with setattr: the statementraises the following exception:
Any ideas or suggestions on how to fix this?