So the straw man solution we've implemented for now looks like this. 
(Background: we have a settings.THREADLOCALS construct which serves in a 
capacity similar to Ned's global requests; also, our monkeypatch_method 
decorator does what you probably think it does.) First, we've a tiny bit of 
middleware:

from django.conf import settings

class RequestURIMiddleware:
    """
    Set the request URI in THREADLOCALS so that it can be used to comment
    SQL queries with what triggered them.
    """
    def process_request(self, request):
        settings.THREADLOCALS.request_uri = request.build_absolute_uri()

And then we've monkeypatched the cursor method on BaseDatabaseWrapper like 
so:

from django.conf import settings
from django.db.backends import BaseDatabaseWrapper, util
from patchers import monkeypatch_method
import traceback
 
class CommentingCursorWrapper(util.CursorDebugWrapper):
    def execute(self, sql, *args, **kwargs):
        """
        Before sending to the DB, this adds a comment to the SQL with notes 
about the query's origin
        """
        try:
            if getattr(settings, 'SQL_COMMENTS_ALWAYS_TRACEBACK', False):
                raise AttributeError
            # THREADLOCALS.request_uri is (usually) populated by 
RequestURIMiddleware
            origin_comment = ' /* Originated from request to 
{0}'.format(settings.THREADLOCALS.request_uri)
        except AttributeError:
            # If no URI available (e.g., Celery task), report the first 
non-Django point in the call stack:
            tb = reversed(traceback.format_stack()[:-1])  # walk it bottom-up, 
excluding this frame
            for frame in tb:
                if 'django' not in frame:
                    origin_comment = ' /* Originated 
at{0}'.format(frame.split('\n')[0])
                    break
        origin_comment = origin_comment.replace('%', '%%')
        origin_comment = origin_comment.replace('*/', '\*\/')
        sql += origin_comment + ' */'
        return self.cursor.execute(sql, *args, **kwargs)

 
@monkeypatch_method(django.db.backends.BaseDatabaseWrapper)
def cursor(self, *args, **kwargs):
    return CommentingCursorWrapper(cursor._original_cursor_function(self, 
*args, **kwargs), self)


So in short, we comment the SQL with the URI when it's available, and fall 
back to the (presumably more expensive to gather) traceback information 
when it's not.

This is just the monkeypatch we're throwing in to solve our immediate 
problem, but it'd be easy enough to convert into a patch. Before we do, any 
thoughts/criticisms of this approach?

Best,
Marty
http://www.mapmyfitness.com/profile/woodlee/

On Monday, October 22, 2012 11:23:47 PM UTC-5, Matt McClure wrote:
>
> Thanks, Russell. That's similar to the approach we were thinking of 
> implementing. Hopefully we'll have a straw man to share shortly. 
>
> Matt
>

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To view this discussion on the web visit 
https://groups.google.com/d/msg/django-developers/-/-X0AFXuzDv8J.
To post to this group, send email to django-developers@googlegroups.com.
To unsubscribe from this group, send email to 
django-developers+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/django-developers?hl=en.

Reply via email to