What the heck went wrong?

5,785 views
5,650 views

Published on

Published in: Technology, Business

What the heck went wrong?

  1. 1. What the heck went wrong? Andy McKay andym on #django clearwind consulting andy@clearwind.ca @clearwind
  2. 2. debugging django
  3. 3. reporting errors
  4. 4. not a question of if...
  5. 5. development → production
  6. 6. development use the dev. server python manage.py runserver
  7. 7. development turn on debug DEBUG = True
  8. 8. development assert False
  9. 9. development a print print "some debugging statement"
  10. 10. development a print print "some debugging statement" print some_variable print type(some_variable)
  11. 11. there's a problem
  12. 12. development mod_wsgi IOError: sys.stdout access restricted by mod_wsgi WSGIRestrictStdout Off http://code.google.com/p/modwsgi/wiki/ApplicationIssues
  13. 13. logging http://www.flickr.com/photos/astro-dudes/1492818224/
  14. 14. development http://docs.python.org/library/logging.html import logging logging.basicConfig( level = logging.DEBUG, format = '%(asctime)s %(levelname)s %(message)s', )
  15. 15. development import logging log.debug("My brilliant debug message")
  16. 16. import logging development import logging.handlers if getattr(settings, "LOG_FILENAME", None): logger = logging.getLogger("django") handler = logging.handlers.RotatingFileHandler(settings.LOG_FILENAME) formatter = logging.Formatter("%(asctime)s - %(levelname)s - %(message)s") handler.setFormatter(formatter) logger.addHandler(handler) else: # so that if you don't have LOG_FILENAME defined, don't blow up class NullHandler(logging.Handler): def emit(self, record): pass logging.getLogger("django").addHandler(NullHandler())
  17. 17. development pdb http://docs.python.org/library/pdb.html
  18. 18. development import pdb; pdb.set_trace() Django version 1.2 pre-alpha, using settings 'test_profiler.settings' Development server is running at http://0.0.0.0:8000/ Quit the server with CONTROL-C. > /mnt/hgfs/sandboxes/test_profiler/profiler/middleware.py(12) process_response() -> url = request.get_full_path() (Pdb)
  19. 19. development l: shows lines of code at your current point n: execute the next line s: step into c: continue q: quit locals(): see what's in your current scope
  20. 20. development pdb is essential
  21. 21. there's a problem
  22. 22. development leave pdb in and your site...
  23. 23. development werkzeug debugger easy_install Werkzeug http://dev.pocoo.org/projects/werkzeug/wiki/UsingDebuggerWithDjango
  24. 24. development #!/usr/bin/env python from werkzeug import run_simple, DebuggedApplication from django.core.handlers.wsgi import WSGIHandler # This is only needed for Django versions < [7537]: def null_technical_500_response(request, exc_type, exc_value, tb): raise exc_type, exc_value, tb from django.views import debug debug.technical_500_response = null_technical_500_response if __name__ == '__main__': run_simple('localhost', 8080, DebuggedApplication(WSGIHandler(), True))
  25. 25. development
  26. 26. development unit tests
  27. 27. development django-debug-toolbar http://github.com/robhudson/django-debug-toolbar/tree/master
  28. 28. development rocks!
  29. 29. development MIDDLEWARE_CLASSES = ( [...snip] 'debug_toolbar.middleware.DebugToolbarMiddleware', ) INSTALLED_APPS = ( [...snip] 'debug_toolbar' ) INTERNAL_IPS = ('127.0.0.1',)
  30. 30. development
  31. 31. development cheaper and easier
  32. 32. staging continuous integration e.g: Teamcity, Integrity, buildbot, Tinderbox ... others are available
  33. 33. staging custom test runner TeamCity: http://bit.ly/geAA [..snip] if hasTeamcity and underTeamcity(): result = TeamcityTestRunner().run(suite) else: result = unittest.TextTestRunner(verbosity=verbosity).run(suite)
  34. 34. staging
  35. 35. production varies upon server mod_wsgi → http://code.google.com/p/modwsgi/wiki/DebuggingTechniques mod_python → http://yenaer.com/blog/2008/jan/12/debugging-modpython-scripts-apache-and-pdb
  36. 36. production errors http://docs.djangoproject.com/en/dev/howto/error-reporting/
  37. 37. production 404 and 500 (has to be in root url.conf) handler404 = 'mysite.views.custom_404' handler500 = 'mysite.views.custom_500' http://docs.djangoproject.com/en/dev/topics/http/views/
  38. 38. production emailed DEBUG = False ADMIN = ( ('Andy', 'andy@clearwind.ca'), )
  39. 39. production Traceback (most recent call last):  File "/usr/lib/python2.5/site-packages/django/core/handlers/base.py", line 86, in get_response    response = callback(request, *callback_args, **callback_kwargs)  File "/usr/lib/python2.5/site-packages/django/contrib/admin/sites.py", line 154, in root    return shortcut(request, *url.split('/')[1:])  File "/usr/lib/python2.5/site-packages/django/contrib/contenttypes/views.py", line 57, in shortcut    object_domain = Site.objects.get_current().domain  File "/usr/lib/python2.5/site-packages/django/contrib/sites/models.py", line 22, in get_current    current_site = self.get(pk=sid)  File "/usr/lib/python2.5/site-packages/django/db/models/manager.py", line 93, in get    return self.get_query_set().get(*args, **kwargs)  File "/usr/lib/python2.5/site-packages/django/db/models/query.py", line 298, in get    num = len(clone)  File "/usr/lib/python2.5/site-packages/django/db/models/query.py", line 154, in __len__    self._result_cache = list(self.iterator())  File "/usr/lib/python2.5/site-packages/django/db/models/query.py", line 269, in iterator    for row in self.query.results_iter():  File "/usr/lib/python2.5/site-packages/django/db/models/sql/query.py", line 206, in results_iter    for rows in self.execute_sql(MULTI):  File "/usr/lib/python2.5/site-packages/django/db/models/sql/query.py", line 1723, in execute_sql    cursor.execute(sql, params) ProgrammingError: relation "django_site" does not exist <WSGIRequest GET:<QueryDict: {}>, POST:<QueryDict: {}>, COOKIES:{'__utma': '90285002.4337325975145378300.1232037035.1233126418.1233185854.12', '__utmb': '90285002.2.10.1233185854', '__utmc': '90285002', '__utmz': '90285002.1232037035.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none)', 'sessionid': 'b139e8d00ed433fb5e6dff50a3956036'}, META:{'DOCUMENT_ROOT': '/htdocs', 'GATEWAY_INTERFACE': 'CGI/1.1', 'HTTP_ACCEPT': 'text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5', 'HTTP_ACCEPT_ENCODING': 'gzip, deflate', 'HTTP_ACCEPT_LANGUAGE': 'en-us', 'HTTP_CONNECTION': 'keep-alive', 'HTTP_COOKIE': '__utmz=90285002.1232037035.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none); __utma=90285002.4337325975145378300.1232037035.1233126418.1233185854.12; __utmc=90285002; __utmb=90285002.2.10.1233185854; sessionid=b139e8d00ed433fb5e6dff50a3956036', 'HTTP_HOST': 'www.areciboapp.com', 'HTTP_REFERER': 'http://www.areciboapp.com/arecibo-admin/singleblog/post/7/', 'HTTP_USER_AGENT': 'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_6; en-us) AppleWebKit/525.27.1 (KHTML, like Gecko) Version/3.2.1 Safari/525.27.1', 'PATH': '/usr/local/bin:/usr/bin:/bin', 'PATH_INFO': u'/arecibo-admin/r/18/7/', 'PATH_TRANSLATED': '/var/www/arecibo/django.wsgi/arecibo-admin/r/18/7/', 'QUERY_STRING': '', 'REMOTE_ADDR': '70.79.161.59', 'REMOTE_PORT': '63593', 'REQUEST_METHOD': 'GET', 'REQUEST_URI': '/arecibo-admin/r/18/7/', 'SCRIPT_FILENAME': '/var/www/arecibo/django.wsgi', 'SCRIPT_NAME': u'', 'SERVER_ADDR': '216.139.224.26', 'SERVER_ADMIN': '[no address given]', 'SERVER_NAME': 'www.areciboapp.com', 'SERVER_PORT': '80', 'SERVER_PROTOCOL': 'HTTP/1.1', 'SERVER_SIGNATURE': '<address>Apache/2.2.8 (Ubuntu) DAV/2 SVN/1.4.6 mod_python/3.3.1 Python/2.5.2 mod_ssl/2.2.8 OpenSSL/0.9.8g mod_wsgi/1.3 Server at www.areciboapp.com Port 80</address>n', 'SERVER_SOFTWARE': 'Apache/2.2.8 (Ubuntu) DAV/2 SVN/1.4.6 mod_python/3.3.1 Python/2.5.2 mod_ssl/2.2.8 OpenSSL/0.9.8g mod_wsgi/1.3', 'mod_wsgi.application_group': 'areciboapp.com|', 'mod_wsgi.callable_object': 'application', 'mod_wsgi.case_sensitivity': '1', 'mod_wsgi.listener_host': '', 'mod_wsgi.listener_port': '80', 'mod_wsgi.output_buffering': '0', 'mod_wsgi.process_group': 'www-data', 'mod_wsgi.reload_mechanism': '0', 'mod_wsgi.script_reloading': '1', 'wsgi.errors': <mod_wsgi.Log object at 0x8c0d620>, 'wsgi.input': <mod_wsgi.Input object at 0xb469958>, 'wsgi.multiprocess': True, 'wsgi.multithread': False, 'wsgi.run_once': False, 'wsgi.url_scheme': 'http', 'wsgi.version': (1, 0)}>
  40. 40. production arecibo http://www.areciboapp.com/ http://www.areciboapp.com/listener/docs/django/
  41. 41. production get account Install Arecibo library ARECIBO_PUBLIC_ACCOUNT_NUMBER = "xxxx"
  42. 42. production add to error from arecibo.wrapper import post def application_error(request): t = loader.get_template('500.html') uid = post(request, 500) c = RequestContext(request, {"uid": uid}) return HttpResponse(t.render(c), status=500)
  43. 43. production
  44. 44. honourable mentions django-db-log http://code.google.com/p/django-db-log/ "Logs Django exceptions to your database handler."
  45. 45. honourable mentions django-sql-profiler http://code.google.com/p/django-sql-profiler "Records every SQL query in Django in the database so that you can find slow queries in your site."
  46. 46. The error message is the Truth. The error message is God. James Bennett, earlier today. Andy McKay clearwind consulting andy@clearwind.ca @clearwind slides will be going on http://djangozen.com

×