Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Django best practices for logging and signals

flywindy
April 23, 2015

Django best practices for logging and signals

Two Scoops of Django - Best Practices for Django 1.6
Ch. 24: Logging: What's It For, Anyway?
Ch. 25: Signals: Use Cases and Avoidance Techniques

flywindy

April 23, 2015
Tweet

More Decks by flywindy

Other Decks in Technology

Transcript

  1. Best Practices for Django 1.6 TWO SCOOPS OF DJANGO Ch.

    24: Logging: What's It For, Anyway? Ch. 25: Signals: Use Cases and Avoidance Techniques Michelle Leu @flywindy 2015/04/21
  2. ABOUT THIS BOOK • Best practices • Django 1.6 •

    Not really for new comer • Author: • Daniel Greenfeld & Audrey Roy • Django Packages 2
  3. LOGGING • Django uses Python’s builtin logging module to perform

    system logging. • Application Logs vs. Other Logs • App logs: any log file containing data logged from your Python web application • Why Bother With Logging? • debug, tracking, security… 4
  4. Log Catastrophes With CRITICAL LOG LEVEL Use the CRITICAL log

    level only when something catastrophic occurs that requires urgent attention.
 5
  5. Log Production Errors With ERROR LOG LEVEL Use the ERROR

    log level whenever you need to log an error that is worthy of being emailed to you or your site admins. 6
  6. Log Production Errors With ERROR LOG LEVEL 7 logger.error("Internal  Server

     Error:  %s",            request.path,            exc_info=exc_info,            extra={                    "status_code":  500,                    "request":  request            }     )  
  7. Log Lower-Priority Problems With WARNING LOG LEVEL This level is

    good for logging events that are unusual and potentially bad, but not as bad as ERROR-level events. 8
  8. Log Lower-Priority Problems With WARNING LOG LEVEL 9 logger.warning("Forbidden  (%s):

     %s",                                  REASON_NO_CSRF_COOKIE,                                  request.path,            extra={                    "status_code":  403,                    "request":  request,            }     )  
  9. Log Useful State Information With INFO LOG LEVEL Use this

    level to log any details that may be particularly important when analysis is needed. 10
  10. Log Debug-Related Messages to DEBUG LOG LEVEL In development, we

    recommend using DEBUG and occasionally INFO level logging wherever you’d consider throwing a print statement into your code for debugging 11
  11. LOG TRACEBACKS • Python’s logging module supports this: • Logger.exception()

    automatically includes the traceback and logs at ERROR level. • For other log levels, use the optional exc_info keyword argument. 12
  12. ONE LOGGER PER MODULE • Whenever you use logging in

    another module, don’t import and reuse a logger from elsewhere. Instead, define a new logger specific to the module. • What this gives you is the ability to turn on and off only the specific loggers that you currently need. 13
  13. LOG LOCALLY • Default settings file is configured to email

    ERROR and higher log messages to whomever you list in ADMINS. • Writing logs of level INFO and higher to rotating log files on disk. 14
  14. Sentry THIRD-PARTY TOOLS Sentry is a modern error logging and

    aggregation platform.
 The primary implementation is in Python, but it contains a full API for sending events from any language, in any application. 15
  15. SENTRY 1. pip install raven 2. Django configuration 3. python

    manage.py raven test
 
 ~demo~ 16 #  settings.py   #  ...   #  Set  your  DSN  value   RAVEN_CONFIG  =  {          'dsn':  'SENTRY_DSN',   }   #  Add  raven  to  the  list  of  installed  apps   INSTALLED_APPS  =  INSTALLED_APPS  +  (          #  ...          'raven.contrib.django.raven_compat',   )
  16. OTHER TIPS • Colorizing your log output helps you spot

    important messages at a glance. Ex: logutils • loggly.com (http://loggly.com/) simplifies log management and provides excellent query tools. • PagerDuty (http://www.pagerduty.com/) alert you and your team repeatedly until you’ve taken action. 17
  17. Don’t wait until it’s too late to add logging. SUMMARY

    You’ll be grateful for your logs if and when your site fails. 18
  18. WHAT IS SIGNALS • Django includes a “signal dispatcher” which

    helps allow decoupled applications get notified when actions occur elsewhere in the framework. 22 Sender Receiver Receiver Receiver !
  19. WHAT IS SIGNALS • Django provides a set of built-in

    signals. These include some useful notifications: • django.db.models.signals.pre_save & django.db.models.signals.post_save • django.db.models.signals.m2m_changed • django.core.signals.request_started & django.core.signals.request_finished 23
  20. Use signals as a last resort. WHY NOT? • Signals

    are being dispatched everywhere and hopefully getting received somewhere. • Not like Celery, Signals are synchronous and blocking. 24
  21. WHEN TO USE • Your signal receiver needs to make

    changes to more than one model. • You want to dispatch the same signal from multiple apps and have them handled the same way by a common receiver. • You want to invalidate a cache after a model save. • You have an unusual scenario that needs a callback, and there’s no other way to handle it besides using a signal. 25
  22. WHEN TO AVOID • The signal relates to one particular

    model and can be moved into one of that model’s methods, possibly called by save(). • The signal can be replaced with a custom model manager method. • The signal relates to a particular view and can be moved into that view. 26
  23. \ 29 #  events/managers.py     from  django.db  import  models

            class  EventManager(models.Manager):                def  create_event(self,                            title,                            start,                            end,                            creator):                    event  =  self.model(title=title,                                            start=start,                                            end=end,                                            creator=creator)                    event.notify_admins()                    return  event #  events/models.py     #  ...   from  model_utils.models  import  TimeStampedModel     from  .managers  import  EventManager         MSG  =  "{user}  submitted  a  new  event!"         class  Event(TimeStampedModel):                      #  ...          title  =  models.CharField(max_length=100)            #  ...                objects  =  EventManager()            def  notify_admins(self):                    #  create  the  subject                    creator  =  self.creator                    subject  =  MSG.format(user=creator.get_full_name())                        #  create  the  message                    message  =  """TITLE:  {title}                    START:  {start}                    END:  {end}""".format(title=self.title,                                                            start=self.start,                                                            end=self.end)                        #  Send  to  the  admins!                    mail_admins(subject=subject,                            message=message,                            fail_silently=False) Instead of calling create(), we call a create_event() method.
  24. AVOIDANCE TECHNIQUES 30 • Validate Your Model Elsewhere • If

    validating through a ModelForm, try overriding your model’s clean() method instead. • Override Your Model’s Save or Delete Method Instead