def process_response(self, request, response): try: view = self.local.view time_taken = time.time() - self.local.start_time except AttributeError: # If, for whatever reason, the variables are not available, don't # do anything else. return response if time_taken < getattr(settings, 'DUMPSLOW_LONG_REQUEST_TIME', 1): return response client = redis.Redis( host=settings.REDIS_HOST, port=settings.REDIS_PORT, ) client.zadd( getattr(settings, 'DUMPSLOW_REDIS_KEY', 'dumpslow'), '%s\n%.3f' % (view, time_taken), self.local.start_time, ) # Clean up old values delete_after = parse_interval( getattr(settings, 'DUMPSLOW_DELETE_AFTER', '4w'), ) client.zremrangebyscore( getattr(settings, 'DUMPSLOW_REDIS_KEY', 'dumpslow'), 0, int(time.time()) - delete_after, ) # If it was really slow, email admins. Disabled by default. email_threshold = getattr(settings, 'DUMPSLOW_EMAIL_REQUEST_TIME', -1) if email_threshold > -1 and time_taken > email_threshold: include = True for email_exclude in getattr(settings, 'DUMPSLOW_EMAIL_EXCLUDES', []): if request.path.startswith(email_exclude): include = False break if include: subject = "SLOW PAGE: %s" % request.path message = "This page took %2.2f seconds to render for %s, which is over the threshold of %s.\n\n%s" % (time_taken, request.user, email_threshold, str(request)) try: mail_admins(subject, message) except Exception as e: # Ignore any errors sending mail in production if settings.DEBUG: raise e else: pass return response
def process_response(self, request, response): try: view = self.local.view time_taken = time.time() - self.local.start_time except AttributeError: # If, for whatever reason, the variables are not available, don't # do anything else. return response if time_taken < getattr(settings, 'DUMPSLOW_LONG_REQUEST_TIME', 1): return response client = redis.Redis( host=settings.REDIS_HOST, port=settings.REDIS_PORT, ) map_key = '%s\n%.3f' % (view, time_taken) mapping = { map_key: self.local.start_time } client.zadd( getattr(settings, 'DUMPSLOW_REDIS_KEY', 'dumpslow'), mapping, ) # Clean up old values delete_after = parse_interval( getattr(settings, 'DUMPSLOW_DELETE_AFTER', '4w'), ) client.zremrangebyscore( getattr(settings, 'DUMPSLOW_REDIS_KEY', 'dumpslow'), 0, int(time.time()) - delete_after, ) # If it was really slow, email admins. Disabled by default. email_threshold = getattr(settings, 'DUMPSLOW_EMAIL_REQUEST_TIME', sys.maxsize) if time_taken > email_threshold: mail_admins( "SLOW PAGE: %s" % request.path, "This page took %2.2f seconds to render, which is over the threshold " "threshold of %s.\n\n%s" % ( time_taken, email_threshold, str(request), ), ) return response
def process_response(self, request, response): try: view = self.local.view time_taken = time.time() - self.local.start_time except AttributeError: # If, for whatever reason, the variables are not available, don't # do anything else. return response if time_taken < getattr(settings, 'DUMPSLOW_LONG_REQUEST_TIME', 1): return response client = redis.Redis( host=settings.REDIS_HOST, port=settings.REDIS_PORT, ) map_key = '%s\n%.3f' % (view, time_taken) mapping = {map_key: self.local.start_time} client.zadd( getattr(settings, 'DUMPSLOW_REDIS_KEY', 'dumpslow'), mapping, ) # Clean up old values delete_after = parse_interval( getattr(settings, 'DUMPSLOW_DELETE_AFTER', '4w'), ) client.zremrangebyscore( getattr(settings, 'DUMPSLOW_REDIS_KEY', 'dumpslow'), 0, int(time.time()) - delete_after, ) # If it was really slow, email admins. Disabled by default. email_threshold = getattr(settings, 'DUMPSLOW_EMAIL_REQUEST_TIME', sys.maxsize) if time_taken > email_threshold: mail_admins( "SLOW PAGE: %s" % request.path, "This page took %2.2f seconds to render, which is over the threshold " "threshold of %s.\n\n%s" % ( time_taken, email_threshold, str(request), ), ) return response
def process_response(self, request, response): try: view_request = self.local.request view = self.local.view time_taken = time.time() - self.local.start_time except AttributeError: # If, for whatever reason, the variables are not available, don't # do anything else. return response if request != view_request: # Some responses "short-circuit" the process_view middleware, so we # need to verify that this is the same request as that encountered # by process_view. return response if time_taken < getattr(settings, "DUMPSLOW_LONG_REQUEST_TIME", 1): return response client = redis.Redis(host=settings.REDIS_HOST, port=settings.REDIS_PORT) client.zadd( getattr(settings, "DUMPSLOW_REDIS_KEY", "dumpslow"), "%s\n%.3f" % (view, time_taken), self.local.start_time ) # Clean up old values delete_after = parse_interval(getattr(settings, "DUMPSLOW_DELETE_AFTER", "4w")) client.zremrangebyscore(getattr(settings, "DUMPSLOW_REDIS_KEY", "dumpslow"), 0, int(time.time()) - delete_after) # If it was really slow, email admins. Disabled by default. email_threshold = getattr(settings, "DUMPSLOW_EMAIL_REQUEST_TIME", sys.maxint) if time_taken > email_threshold: mail_admins( "SLOW PAGE: %s" % request.path, "This page took %2.2f seconds to render, which is over the threshold " "threshold of %s.\n\n%s" % (time_taken, email_threshold, str(request)), ) return response
def handle(self, **options): def check_option(name, val): try: val = int(val) if val < 0: raise ValueError() return val except ValueError: raise CommandError( 'Invalid value for %s %r' % (name, val) ) except TypeError: pass limit = check_option('-t', options['limit']) max_duration = check_option('-m', options['max_duration']) after = options['after'] if after: try: after = int(time.time()) - parse_interval(after) except ValueError: raise CommandError('Invalid interval %r' % after) order = options['order'] if order not in ('at', 'count', 'average'): raise CommandError('Invalid sort order %r' % options['order']) client = redis.Redis( host=settings.REDIS_HOST, port=settings.REDIS_PORT, ) data = {} totals = {} hits = {} results = client.zrangebyscore( getattr(settings, 'DUMPSLOW_REDIS_KEY', 'dumpslow'), after, '+inf', ) for line in results: view, duration = line.split('\n', 1) duration = float(duration) if max_duration and duration >= max_duration: continue if order == 'at': try: data[view] += duration except KeyError: data[view] = duration elif order == 'count': try: data[view] += 1 except KeyError: data[view] = 1 elif order == 'average': try: totals[view] += duration hits[view] += 1 except KeyError: totals[view] = duration hits[view] = 1 data[view] = totals[view] / hits[view] items = data.items() del data items.sort(key=itemgetter(1), reverse=not options['reverse']) if limit is not None: items = items[:limit] print "", "View", print { 'count': 'Count', 'at': 'Accumulated time', 'average': 'Average time', }[order].rjust(66) print "", "=" * 71 for view, value in items: pad = 70 - len(view) print "", view, if order == 'at': print ("%2.2f" % value).rjust(pad) elif order == 'count': print str(value).rjust(pad) elif order == 'average': print ("%2.2f" % value).rjust(pad)
def handle(self, **options): def check_option(name, val): try: val = int(val) if val < 0: raise ValueError() return val except ValueError: raise CommandError('Invalid value for %s %r' % (name, val)) except TypeError: pass limit = check_option('-t', options['limit']) max_duration = check_option('-m', options['max_duration']) after = options['after'] if after: try: after = int(time.time()) - parse_interval(after) except ValueError: raise CommandError('Invalid interval %r' % after) order = options['order'] if order not in ('at', 'count', 'average'): raise CommandError('Invalid sort order %r' % options['order']) client = redis.Redis( host=settings.REDIS_HOST, port=settings.REDIS_PORT, ) data = {} results = client.zrangebyscore( getattr(settings, 'DUMPSLOW_REDIS_KEY', 'dumpslow'), after, '+inf', ) for line in results: view, duration = line.split(b'\n', 1) duration = float(duration) if max_duration and duration >= max_duration: continue try: data[view]['at'] += duration data[view]['count'] += 1 except KeyError: data[view] = {'at': duration, 'count': 1} data[view]['average'] = data[view]['at'] / data[view]['count'] items = sorted(data.items(), key=lambda item: item[1][order], reverse=not options['reverse']) del data if limit is not None: items = items[:limit] headers = ['View', 'Count', 'Accumulated time', 'Average time'] print( tabulate([[view, values['count'], values['at'], values['average']] for view, values in items], headers=headers))
def handle(self, **options): def check_option(name, val): try: val = int(val) if val < 0: raise ValueError() return val except ValueError: raise CommandError( 'Invalid value for %s %r' % (name, val) ) except TypeError: pass limit = check_option('-t', options['limit']) max_duration = check_option('-m', options['max_duration']) after = options['after'] if after: try: after = int(time.time()) - parse_interval(after) except ValueError: raise CommandError('Invalid interval %r' % after) order = options['order'] if order not in ('at', 'count', 'average'): raise CommandError('Invalid sort order %r' % options['order']) client = redis.Redis( host=settings.REDIS_HOST, port=settings.REDIS_PORT, ) data = {} results = client.zrangebyscore( getattr(settings, 'DUMPSLOW_REDIS_KEY', 'dumpslow'), after, '+inf', ) for line in results: view, duration = line.split(b'\n', 1) duration = float(duration) if max_duration and duration >= max_duration: continue try: data[view]['at'] += duration data[view]['count'] += 1 except KeyError: data[view] = {'at': duration, 'count': 1 } data[view]['average'] = data[view]['at'] / data[view]['count'] items = sorted(data.items(), key=lambda item: item[1][order], reverse=not options['reverse']) del data if limit is not None: items = items[:limit] headers=['View', 'Count', 'Accumulated time', 'Average time'] print(tabulate([[view, values['count'], values['at'], values['average']] for view, values in items], headers=headers))