Django and Sentry

I recently started trialing Sentry and was seriously impressed with it. However, I had an issue where the number of performance events being sent to Sentry was enormous and with only testing by me and my three colleagues, we were generating in excess of 10, 000 events a day. Of course, there were some scanning events from random internet addresses and the like, but they were not responsible for the lion’s share of performance data.

Whilst the performance data is fantastic to have access to, it would have cost us a small fortune just to have the four of us on our platform, never mind the 70 users who have recently started using the platform.

Is there anyone here who is very familiar with Sentry and Django and perhaps knows how to use Sentry to ensure that one can stick to 100 000 performance data within a month?

Or perhaps it is the case that something seems off? Or perhaps I’m doing something wrong?

At the moment we have an income of precisely $0 and we don’t expect this to change until semester start after the European summer holidays.

Below you can find an example of the Sentry configuration I had.

Any ideas and advice is greatly appreciated.

Cheers,

C

import sentry_sdk
from sentry_sdk.integrations.django import DjangoIntegration

sentry_key = os.environ.get("SENTRY_KEY", None)
SENTRY_DSN = <hidden>
sentry_sdk.init(
    dsn=SENTRY_DSN,
    integrations=[DjangoIntegration()],
    traces_sample_rate=1.0,
    # If you wish to associate users to errors (assuming you are using
    # django.contrib.auth) you may enable sending PII data.
    send_default_pii=True,
    sample_rate=0.2  # send 20% of performance events
)

RAVEN_CONFIG = {
    "dsn": SENTRY_DSN,
}



# logging
LOGGING_CONFIG = None

logging.config.dictConfig(
    {
        "version": 1,
        "disable_existing_loggers": False,
        "formatters": {
            "console": {
                # exact format is not important, this is the minimum information
                "format": "%(asctime)s %(name)-12s %(levelname)-8s %(message)s",
            },
        },
        "handlers": {
            "sentry": {
                "level": "INFO",  # To capture more than ERROR, change to WARNING, INFO, etc.
                "class": "raven.contrib.django.raven_compat.handlers.SentryHandler",
                "tags": {"custom-tag": "x"},
            },
            "console": {"level": "DEBUG", "class": "logging.StreamHandler", "formatter": "console"},
        },
        "loggers": {
            # root logger
            "": {"level": "ERROR", "handlers": ["console"]},
            "config": {
                "level": "ERROR",
                "handlers": ["console"],
                # required to avoid double logging with root logger
                "propagate": False,
            },
            "raven": {"level": "DEBUG", "handlers": ["console"], "propagate": False},
            "sentry.errors": {"level": "DEBUG", "handlers": ["console"], "propagate": False},
            "populator": {
                "level": "INFO",
                "handlers": ["console"],
                # required to avoid double logging with root logger
                "propagate": False,
            },
        },
    }
)

So you have 10,000 performance events even with 20% sampling? This would mean you’re managing to do 50,000 requests a day. That’s a lot for 3 people - on average each of you performs a request every 1.7 seconds for 8 hours a day.

Do you have one particular view that consumes the majority of your requests, such is if you have a SPA which performs N+1 API requests? Perhaps changing that to sample much less often, or refactor it to use a bulk operation.

Hi Adam,

I should have mentioned that the sampling rate is something I adjusted after I came across my performance monitoring data. My apologies.

We do have an SPA which I guess has on average about 120 calls to the API when a user does a case. In terms of our app, a case is when a user starts a consultation of their patient (we’re an academic tool which simulates clinical and diagnostic veterinary science). With thorough clicking and probing one could get up towards 200 calls and if all four of us were testing the app extensively, well, there you go.

We do present the majority of the data required for the case with one API call. A lot of the data however is not available at the start of the case, for example, the results of running a blood test, or listening to the patient’s breathing. We also have to track which tests have been run and what body parts have probed, so the requests quickly add up.

I’m quite the test fanatic (who could I possible blame for that?) so I often run my tests locally, on dev and then in prod. That tells me that I need to limit sentry to just prod, which I can’t believe I hadn’t done - I had done it for Rollbar.

I really should have figured all this out on my own, but I guess I was just a bit stumped that we were reaching a limit on a paid service so easily when there was no one other than ourselves using the app. I thought that I was either doing something wrong or I had misunderstood something about how one was suppose to use Sentry and its performance feature. I’ll have a cup of tea and a biscuit before next posting here.

I know you have talked fondly of Sentry before, and as such, do you have any general pointers for Sentry and Django? I currently use Rollbar because it does a good job of catching exceptions and presenting them well in their GUI, not to mention the price. But when I saw what Sentry did, I did find myself getting a little excited.