Settings, Sentry and Tests

Hi All,

I was recently inspired to clean up my settings file by a Twitter exchange involving a few of this forum’s members. I’ve been meaning to do this for quite some time, so I plunged head first into the task. I’ve set out to remove as many if statements as possible. I don’t want to have multiple settings files if I can avoid it and ideally I don’t want if statements in my settings file as I’m of the opinion that the file then becomes a combination of configuration and implementation file. I’d rather just keep it purely as a configuration file or as close to the idea of configuration file as possible.

The only sticking point I have at the moment is the initialisation of Rollbar and Sentry (I’m trialling Sentry), which I do not want initialised when running my test suite. I run my test suite every time my app is deployed to our production and development servers, and until recently, I had a complete copy of my project’s setting file minus the Rollbar and Sentry stuff as my test settings file. Such duplication is annoying to maintain, at least in my opinion.

I deploy using Dokku which runs my code in a Docker container. I run my tests in the same container as my production code (I have several nodes for redundancy) to ensure that production behaves as expected, but this means that the env vars are the same for my tests as they are for my production code and hence, are set to initialise Sentry and Rollbar.

Disabling Rollbar is trivial enough:

settings.ROLLBAR["enabled"] = False

but disabling Sentry is what is giving me some grief.

What I have done is:

I have an ENV var SENTRY which should be able to turn Sentry and Rollbar on or off and an if statement to intialise Sentry if SENTRY is True

SENTRY = os.getenv("SENTRY", default='False').lower() in ('true', '1', 't')

if SENTRY:
    import rollbar
    # do Sentry and Rollbar stuff

I thought, and appears somewhat daftly, that I could use a test_settings file which looks like this:

from . import settings
settings.ROLLBAR["enabled"] = False
settings.SENTRY = False

But this doesn’t work as I’ve just called my primary settings file which initialised Sentry.

So my question is to those of you who have a single settings file and use some sort of monitoring such as Rollbar and Sentry, how for the love of space have you solved this challenge? Do you have a strategy to not use Sentry when running your tests? Have you a clever way to avoid having multiple configuration files? Have you managed to avoid an if statement determining whether Sentry should be initialised? Or perhaps you just don’t run your tests on your production servers?

As always, any ideas and help are much appreciated.

All the best,

Conor

I use a single settings file with this strategy which I blogged about: Disable Instrumentation Packages during Tests - Adam Johnson

Once sentry is inited, you can’t undo it. So you can’t set the SENTRY variable back and undo what was in the if SENTRY block, in the second settings file.

Oh hell no, never, the risk of accidentally a whole production database is way too high!

While not an exact parallel, we’ve accepted the reality of conditionals within the settings file for the sake of reducing the number of configuration files necessary.

We’ve adopted the general principle that the Django settings file is code-with-a-purpose. Otherwise, Django could implement (or have implemented) something more basic like an ini/json/yaml/xml configuration format instead of providing for “code-in-settings”.

So we have conditionals around use of DEBUG, Django-debug-toolbar, CAS, and in some cases, access to certain external data sources. This allows us to have one settings file and ‘n’ number of environment files for custom combinations, affecting various features as logging configurations and authentication URLs.
(I’ll concede that the environment files could be considered “settings files”, leading to an “n+1” issue for configurations :slight_smile: , but overall it really works for us.)

Cheers Adam. It was your post from which I stole the ROLLBAR["enabled"] - cheers.

Had some bad experiences or just sensible cautiousness? But yes, good point. If I can work out how to get Github actions to fire up an IPsec tunnel to my production network in order to deploy after running my tests, I’ll be laughing. In the meantime, I’ll follow your lead and test on a non-production system.

G’day Ken. Interesting points. I’d accepted that I’d live with a conditional for DEBUG and Django-debug-toolbar, but I was hoping for something a bit more flexible with Sentry. I agree that having the config file in Python is a winner as it is more flexible (can you imagine if it were in XML? Oh deary me!). I’m just trying to keep things to as few moving parts as possible. Like you, it’s my env vars which are now the thing to be managed.

Slightly on and slightly off topic, I read up on the Django’s Test Runner and have used that to quieten down my new and improved production logging whilst running tests. Could also be an ideal place to turn off Rollbar - will have a think and a read about that.

TEST_RUNNER = "config.test_runner.eClinicTestRunner"

class eClinicTestRunner(DiscoverRunner):
    def setup_test_environment(self, **kwargs):
        # turn off logging during tests
        logging.disable(logging.CRITICAL)
        return super().setup_test_environment(**kwargs)
1 Like

Five years configuring Java / JEE systems in a Websphere / Tomcat environment.

Yes, I can. :grinning_face_with_smiling_eyes:

1 Like