Share on Twitter
Share on Facebook
Share on HackerNews

How Sentry uncovered an N+1 issue in djangoproject.com

Sentry recently launched Performance Issues, a feature to help developers discover and fix common performance problems in their projects. We tested this project internally and with alpha users, so when we finally turned it on for all Sentry users, we were delighted (and dismayed) to hear from Carlton Gibson, current Django fellow and great human, that Sentry had:

  1. Detected an N+1 problem in the code for http://djangoproject.com/
  2. Annoyed the heck out of Carlton and other Django maintainers with duplicate Sentry Issues for that same N+1 problem (sorry about that!)

tweet please

djangoproject.com’s N+1 problem

The site’s N+1 problem was in their docs version switcher, and the fix was pretty simple.

docs please

Version with N+1 problem:

@register.simple_tag(takes_context=True)
def get_all_doc_versions(context, url=None):
  """
  Get a list of all versions of this document to link to.
  Usage: {% get_all_doc_versions <url> as "varname" %}
  """
  lang = context.get('lang', 'en')
  versions = []

  # This causes an N+1 query!   for release in DocumentRelease.objects.filter(lang=lang):    version_root = get_doc_root(release.lang, release.version)
    if version_root.exists():
      doc_path = get_doc_path(version_root, url)
      if doc_path:
        versions.append(release.version)
  # Save the versions into the context
  versions = sorted(StrictVersion(x) for x in versions if x != 'dev')
  return [str(x) for x in versions] + ['dev']

Fixed version:

@register.simple_tag(takes_context=True)
def get_all_doc_versions(context, url=None):
  """
  Get a list of all versions of this document to link to.
  Usage: {% get_all_doc_versions <url> as "varname" %}
  """
  lang = context.get('lang', 'en')
  versions = []

  # This is fixed :D   for release in DocumentRelease.objects.select_related('release').filter(lang=lang):    version_root = get_doc_root(release.lang, release.version)
    if version_root.exists():
      doc_path = get_doc_path(version_root, url)
      if doc_path:
        versions.append(release.version)

  # Save the versions into the context
  versions = sorted(StrictVersion(x) for x in versions if x != 'dev')
  return [str(x) for x in versions] + ['dev']

Our duplicate issues bug

All developers write buggy code - even devs at Sentry. Carlton was able to resolve djangoproject.com’s N+1 issue, and with his feedback, we were also able to fix the bug in Sentry that was duplicating N+1 performance issues. You can learn more about our fix in the PR.

another tweet please

Performance issues

Sentry’s Performance Issues feature can currently detect N+1 issues in all Sentry-supported backend languages. If you’re already using Sentry for backend performance monitoring, to detect N+1 issues all you have to do is… nothing. Sentry will automatically detect N+1 problems by default.

Beyond N+1 issues, Sentry performance monitoring will identify slow transactions, spans that could be the bottleneck and how a slowdown in one part of your stack is affecting other parts of your application. Check out our docs to learn more about performance monitoring with Sentry.

Your code is broken. Let's Fix it.
Get Started

More from the Sentry blog

ChangelogDashboardsDiscoverDogfooding ChroniclesEcosystemError MonitoringEventsGuest PostsMobileMoonlightingOpen SourcePerformance MonitoringRelease HealthSDK UpdatesSentry

Do you like corporate newsletters?

Neither do we. Sign up anyway.

© 2022 • Sentry is a registered Trademark
of Functional Software, Inc.