Gunicorn + Flask - #app.errorhandler(500) being ignored? - flask

I've spent quite a bit of time searching and I'm amazed I've not found an answer to this.
I've got basic #app.errorhandler(500) code in my flask app. As expected, I get a debugger when running with DEBUG on, and I get my custom error page when it's false. The next stage of my build though is serving the app from gunicorn in a docker container, and I'm just getting generic "Internal Server Error"s when I do that. I'm guessing gunicorn is handling the errors now instead of flask? But I can't for the life of me figure out how to ask it to let flask handle the errors (if that's even possible), or make it use custom error pages.
The final stage will be gunicorn in docker behind nginx, but I think I've found a config directive for nginx to make it let gunicorn handle the errors - I just need to get gunicorn to pass it down one level further so I can use my custom error page, and fire off notifications to relevant people with details regarding the error that occurred (which I suspect I'd lose if I did a custom error page at the gunicorn or nginx level). Help would be GREATLY appreciated.

I have Flask + gunicorn + Nginx system, The Internal Server Error was handled by default with Nginx, I added the following config to let 500 errors handled by flask:
import logging
from werkzeug.exceptions import InternalServerError
import traceback
#app.errorhandler(InternalServerError)
def handle_500(e):
logging.error(traceback.format_exc())

I was able to fix it with the below handle. But I still can't properly explain it. In any case even though the original handling (#app.app_errorhandler(500)) worked fine with the dev flask server and not with gunicorn, I don't believe the problem is to be solved with gunicron. It needs to be solved within the code.
#app.app_errorhandler(Exception)
def handle_exception_error(err):
""" Defines how to handle Exception errors. """
logger.error(err)
return "INTERNAL_SERVER_ERROR", 500

Related

Internal server error running Django on Heroku accessing from browser

I think this is a simple fix, but I've deployed quite a few Django apps to Heroku and I still can't figure out what's going on.
Accessing https://dundjeon-finder.herokuapp.com/ gives me a 500 error when using the browser/curl, but if I shell into the app using heroku run ./manage.py shell I can render the views no problem. My logs aren't telling me anything (just that the response is 500) despite DEBUG being set to True, and Sentry isn't receiving an error (it has previously when the database env variable was set badly), so I'm assuming it's something to do with the way the request works.
The repo is public, any help would be much appreciated! The settings file is here.
Well it was because of using asgi instead of wsgi. I'm not sure why that caused the errors, but will do some more searching.

Django Postgresql Heroku : Operational Error - 'FATAL too many connections for role "usename"'

I am running a web application using Django and Django Rest Framework on Heroku with a postgresql and redis datastore. I am on the free postgresql tier which is limited to 20 connections.
This hasn't been an issue in the past, but recently I started using django channels 2.0 and the daphne server (switched my Procfile from gunicorn to daphne like this tutorial) and now I have been running into all sort of weird problems.
The most critical is that connections to the database are being left open so as the app runs, the number of connections keep increasing until it reaches 20 and gives me the following error message: Operational Error - 'FATAL too many connections for role "usename"'
Then I have to manually go to shell and type heroku pg:killall each time, this is obviously not a feasible solution and this is production so my users cant get access to site and get 500 errors. Would really appreciate any help.
I have tried:
Adding this to my different views in different places
from django.db import connections
conections.close_all()
for con in connections:
con.close()
I also tried doing SELECT * from pg_activity and saw a bunch of stuff but have no idea what to make of it:
We figured out whats the problem. I assume that you are using dj_database_url like in heroku manual. All you have to do is to drop conn_max_age.
db_from_env = dj_database_url.config()
There is the solution:
Nowadays heroku provide the django_heroku package that deal with default django-heroku app configuration, so when you call django_heroku.config(locals()) on the end of your settings.py the default CONN_MAX_AGE database config is set to 600 seconds, so the default of django is 0 what mean all database connections are been closed after request complete, if you don't replace the value of CONN_MAX_AGE after calling django_heroku.config(locals()) the value of this field is default to 600 what mean the DB connections still alive for 600 seconds causing this trouble.
Put this line on the end of your settings.py, its mandatory to be after heroku config:
django_heroku.config(locals())
DATABASES['default']['CONN_MAX_AGE'] = 0
I think I may have solved it.
One of the changes I made was modifying how I closed my connections.
The key is to close old connections before and after various view functions.
from django.db import close_old_connections
#csrf_exempt
#api_view(['GET', ])
def search(request):
close_old_connections()
# do stuff
close_old_connections()

Heroku Server 500 error on particular page

Just deployed a Django app on Heroku. Everything works except for one page of my site which creates a Server 500 error (even though it works fine on my local development server).
The page raising the error doesn't do anything unusual. It makes some database calls, renders some forms, implements JQuery, etc. Any clue what this could be or how I can debug it?
Also, I thought this might be a data issue since my data in Dev doesn't match my data in production, but I checked and this doesn't seem to be the cause.
enable DEBUG=TRUE in your django settings.py file or type in console heroku logs --app your_app to get heroku server logs.
This was because I didn't include a runtime.txt telling Heroku to use Python 3 instead of 2 which subsequently raised an error in one of my views where I called super() with no args.

Django is giving me a 404 error

I installed Django, and it works. I set it up so it uses my mysql database, and I started a project. So far so good.
I followed the tutorial on setting up your first Django app over at
https://docs.djangoproject.com/en/dev/intro/tutorial01/
It is a tutorial over setting up a pre-existing poll app where everything has practically been built for you. The database structure has even been handled.
I ran:
python manage.py startapp polls
python manage.py sql polls
python manage.py syncdb
I didn't receive any kind of success message so I went into my phpmyadmin, and hooray! There are new tables and rows in my database.
Their tutorial then told me to run:
python manage.py shell
and that I'd see some database stuff, but I didn't. Why could this be? I ignored it and went on to step two. I still hadn't set DEBUG in my settings.py to False so I did. Only to get a 500 error.
After some digging I read I needed to add:
ALLOWED_HOSTS = ['my ip address'];
I did this and now after running:
python manage.py runserver myip:8000
When I try to access Django in my browser I get a
Not Found
The requested URL / was not found on this server.
Obviously / changes to a different location when navigating to those places as well, but the point is I get a 404 no matter what.
So I look at my terminal and I have a yellow message in my terminal that says.
"GET / HTTP/1.1" 404 74
and there is 1 message like this for each place I tried to access.
I'm thinking there is a Python package that I don't have installed on my server?
I do not want to use ALLOWED_HOSTS ['*'] I read that this is bad practice. I did try it and it produces the same results as using my ip address in place of the * (I just wanted to add that extra piece of info in case it helps)
If you want to use the database shell, you should run the dbshell command instead of shell as in your post, like this:
python manage.py dbshell
If you run shell, you get a Python shell, where you can easily import and inspect the Python objects of your project.
On your local PC, it's better to have DEBUG = True in your settings.py. That way you don't need to bother about ALLOWED_HOSTS, because in debug mode all hosts are allowed. Secondly, when you get a 404 error in debug mode, the page will show you the valid URLs that you can try.
The Django tutorial certainly works. The only way it won't work for you is if you missed a step or mistyped something somewhere. If you start over and pay extra attention, I think it will work.

Django manage.py runserver never finishes "validating models"

I am trying to follow the django tutorial. I am running on windows+eclipse.
When I run python manage.py runserver I get the message Validating models... and afterwards see no progress...
Am I doing something wrong?
I've got my answer in another question: can't get django to work in eclipse + windows
When I ran the server with the --noreload option, I saw that there's an exception thrown. After I fixed that, the output does complete, and says:
Validating models...
0 errors found
Django version 1.2.1, using settings 'XXX'
Development server is running at http://127.0.0.1:8000/
Quit the server with CTRL-BREAK.
The shell is running the runserver process, and it won't go back to a command prompt until the server process ends. So, this sounds normal.
Is the server functioning?
You could possibly be importing something in your models.py file that is failing in another file. I had an import in a try/catch clause that caused this behavior. Installing the missing dependency fixed the problem.
This is what you're supposed to see. If you make a request to your test site (via your browser), you will see the log of the request. If you don't see that, then something else is wrong.