Handling psycopg2 errors properly - python

I am building a web application that works as Web API server for our mobile and Electron app. I am trying to properly design our error handling too.
I use Django, Django Rest Framework for RESTful API implementation.
For psycopg2 errors, I get the following:
"column "unifiedidd" of relation "basicinformation" does not
exist\nLINE 1: INSERT INTO profile.basicinformation (unifiedidd,
firstname,...\n ^\nQUERY:
INSERT INTO profile.basicinformation (unifiedidd, firstname,
middlename, familyname, sex, birthdate) VALUES
('8f38f402-ddee-11ea-bfee-ead0fcb69cd9'::uuid, 'Lily Francis Jane',
'Luo Yi', 'Chao Fan', 'Male', '1990-03-20')\nCONTEXT: PL/pgSQL
function inline_code_block line 5 at SQL statement\n"
In my view file, I am catching these errors as such:
def post(self, request, *args, **kwargs):
try:
return Response({"message": "Cool"},status=http_200_OK)
except ProgrammingError as e:
return Response({"message": str(e)},status=http_500_INTERNAL_SERVER_ERROR)
except IntegrityError as e:
return Response({"message": str(e)},status=http_500_INTERNAL_SERVER_ERROR)
except Exception as e:
return Response({"message": str(e)},status=http_500_INTERNAL_SERVER_ERROR)
First thing I wanna confirm is, because of the content of the error, I assume it is not a good idea to output the whole thing right? Since it shows the actual query. This is useful but maybe for error logging for developer use only.
So I assume I need to output a custom message. But given that there are tons of errors that may be encountered and I think it's impossible to create a custom message for each of these errors, I am thinking to output just a wildcard error message such as `Unexpected error has been encountered. Please contact developer team."
But also, this wildcard error message does not seem so informative for both the developers and the users as well.
I am not sure how to properly handle exceptions and response it to the API client as informative as possible.

Related

Django. How to return error 500 without sending mail to admins

I am using standard error handling in production - if there are server errors I am getting mails.
However, on certain APIs I want to have a response with HTTP code 500 or 502 as part of the "valid flow". (It's done for educational purposes)
So my view for that looks like this:
from rest_framework.response import Response
from rest_framework import status
def give_me_error(request):
return Response("This is expected error", status=status.HTTP_500_INTERNAL_SERVER_ERROR)
And what I want is not to get email of this particular response (because I wanted it to be 500)
I've also tried this way:
from django.http import JsonResponse
def give_me_error(request):
return JsonResponse({'error': 'expected error'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
But it also generates mail.
Is there a way to have a view returning error 500 that will not trigger e-mail send? (without disabling the e-mail functionality system-wide)
Per Django documentation: https://docs.djangoproject.com/en/4.0/howto/error-reporting/
When DEBUG is False, Django will email the users listed in the ADMINS setting whenever your code raises an unhandled exception and results in an internal server error (strictly speaking, for any response with an HTTP status code of 500 or greater)

Raise instead a return

Can anybody help me to understand why not raise an HTTPException when the status is 200 instead a return ?
working with fastApi
A code as example:
#app.delete("/delete")
def delete(id = Query(...,description="Delete ID to be deleted")):
if id not in dictionary:
raise HTTPException(status_code=404,detail="Delete Id doesn't exists.")
del dictionary[id]
return {"Success":"Delete deleted!"}
I want to understand why not to use as example:
raise HTTPException(status_code=200,detail="Delete deleted!")
Is this a correct way to use it?
First of all because of the semantics: an exception is a language construct that means something else than returning the result of a function. It breaks the normal flow of the FastAPI application, and I'm guessing it will/could break most middleware handling (such as CORS headers) because suddenly an exception has occurred instead.
Secondly: Because you probably want to return something else than just information under a detail key. It won't be able to use the response_model mechanism that's built-in to FastAPI and allows you to tweak and validate the response model for each type of request declaratively (i.e. by configuring the view decorator).

How to use Error Report from GCE with Docker and Django?

I'm running Django on a compute engine using Docker. I would like to know how to check the error in the Error Report when the application encounters an error like Cloud run.
I'm looking at how to set up an Error Report in Python. https://github.com/googleapis/python-error-reporting/tree/main/samples/snippets/fluent_on_compute
Looking at this sample, it looks like I need to raise an exception and run report (traceback.format_exc ()) to use the Error Report.
Sample code
def simulate_error():
fluent.sender.setup('myapp', host='localhost', port=24224)
def report(ex):
data = {}
data['message'] = '{0}'.format(ex)
data['serviceContext'] = {'service': 'myapp'}
# ... add more metadata
fluent.event.Event('errors', data)
# report exception data using:
try:
# simulate calling a method that's not defined
raise NameError
except Exception:
report(traceback.format_exc())
When I run Django, I get an error other than using try: execpt.
How can I display such errors in the Error Report?
Please let me know if there is any good way. thank you.
Django provides an option to define custom exception handler.
You can define custom exception handler as show below,
from google.cloud import error_reporting
from rest_framework.views import exception_handler
# Initialize Error reporting client
client = error_reporting.Client()
def custom_exception_handler(exc, context):
# Call REST framework's default exception handler first,
# to get the standard error response.
response = exception_handler(exc, context)
# Send error to Error Reporting
client.report(response)
return response
In your settings file add the below configuration,
REST_FRAMEWORK = {
'EXCEPTION_HANDLER': 'my_project.my_app.utils.custom_exception_handler'
}
To install google cloud error reporting library, use the below command
pip install google-cloud-error-reporting
For reference on setting up Error reporting in python, refer to this

Handling Google App Engine datastore NoneType errors

I wish to handle NoneType errors from the Google App Engine ndb Datastore.
Here is my code:
def post(self):
# get the email and password from the login form
global u_qry
email = self.request.get("email")
password = self.request.get("password")
try:
u_qry = user_db.User.get_by_email(email)
except BaseException, e:
self.response.out.write(e, u_qry)
else:
self.response.out.write("User Recognised")
self.response.out.write(u_qry)
When the user does not exist, the except clause is not catching any error.
Output:
User Recognised None
why is the except clause not catching this error? What exception can be used to catch this error?
I realise I can use if/else statements on this, but would like to learn how to use the try/except clause in GAE.
Thanks.
While you're not showing the way the User.get_by_email() function is implemented I suspect it is simply based on a query. And returning an empty result from a query is a perfectly valid situation - no existing datastore entity matches the query. It's not an exception.
If you intend to consider such case an exception you have to raise one yourself inside User.get_by_email() and in that case you'd be able to catch it in your post() function.
Alternatively you can directly check u_qry for a None value.

Display a specific template when Django raises an exception

In my django app, I have multiple places where I raise a specific custom exception DeserializationError. My goal is to show/redirect to a pretty page to show the user this error, including the error message, when this error is raised. Basically, a page that says something like
Something went wrong. Please contact webmaster#email.com.
Error: DeserializationError. Message: SomeModel, "somemodel", does not exist.
Would this even be possible? I've been trying to search for a solution but haven't been able to find anything yet.
Most likely such errors will return HTTP 500 server error.
In django you can write your own custom view to handle such cases and return your own page with the html that you like.
The 500 (server error) view explains writing server error views. There are more types of errors handled as explained on same page.
An option for handling HTTP 500 errors, add this to your Settings file,
handler500 = 'mysite.views.my_custom_error_view'
and in the view, you can render the "error page" using
HttpResponseNotFound('<h1>Page not found</h1>')
the server_error() view will be overridden by handler500.

Categories