Yeah, I don't think we'd try to do anything like that in our actual Django patch... the THREADLOCALS thing has worked well for us but I realize that's a pretty big shift to impose on others. If anything I think the patch might simply modify the existing CursorDebugWrapper to add the traceback-based comment based on DEBUG being True (and/or some other setting).
Also, we discovered a small bug in the above for cases where manual queries were being sent with semicolons already on them. MySQL was seeing it as two queries in the same cursor execution and raising a ProgrammingError. Just in case someone stumbles across this while Googling and wants to use this solution, here's the diff vs. the above code that fixes it: - sql += origin_comment + ' */' + sql = sql.rstrip(' ;') + sql = ''.join([sql, origin_comment, ' */']) On Wednesday, October 24, 2012 12:14:49 AM UTC-5, Àlex Pérez wrote: > > You are modifying the settings on runtime , that practise is not > recommended by django and personally i have had bad experience with that... > El 24/10/2012 00:26, "Marty Woodlee" <marty....@gmail.com <javascript:>> > escribió: > >> 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-d...@googlegroups.com<javascript:> >> . >> To unsubscribe from this group, send email to >> django-develop...@googlegroups.com <javascript:>. >> For more options, visit this group at >> http://groups.google.com/group/django-developers?hl=en. >> > -- 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/-/AqN0el31UrUJ. 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.