How to ignore flasks http 400 exception in Sentry - flask

I have setup a flask project in Sentry but have noticed a problem that I need to fix.
Currently if the flask application throws a HTTPException (for example for a validation exception) that exception creates an issue in Sentry. This clutters up the issues since it creates issues even for HTTP 400.
Are there any way to configure Sentry so it ignores all HTTPExceptions with code 4xx but still create Issues for all HTTPExceptions with code 5xx?

If I’m not mistaken, Sentry should only send not handled exceptions. So you could setup custom error handlers: http://flask.pocoo.org/docs/1.0/patterns/errorpages/?highlight=error%20handler#error-handlers
If you want to handle all default exceptions you could register an error handler like this:
from werkzeug.exceptions import default_exceptions
def register_error_handlers(app):
""" Register error handler for default exceptions """
for code in default_exceptions:
app.register_error_handler(code, your_error_handler)
where app is your flask App instance and your_error_handler takes the error as argument and returns a response. So you could filter for the 400 codes in this for loop to only handle 4xx errors.

Related

How to make all the error responses for API access in Content-Type of application/json instead of Content-Type of text/html in Flask?

I am building a Flask app that support access by human users and through API. The /api path and its subpaths are dedicated for API access. All API access should receive a response in JSON, i.e., with Content-Type of application/json.
I have organized all API endpoints within a blueprint named api. Using the technique illustrated in Implementing API Exceptions, I have defined a custom error class called ApiAccessError and registered the handler for it in the api blueprint, so whenever ApiAccessError is raised in a view function in the api blueprint, the registered handler for ApiAccessError is invoked to generate a JSON response with Content-Type of application/json.
The issue I have with the current design is that whenever an error that is not an ApiAccessError is raised in handling an API request, the response to the request is not in JSON but in HTML, i.e. having Content-Type of text/html. Such an error can occur, for example, in accessing a GET-only API endpoint with the POST method. In this case, the server response is in HTML with status code of 405. I would like the response to be in JSON while keeping the status code of 405. How can set Flask to respond to the 405 error and all other default errors in JSON instead of HTML in handling API requests?
After further examination of the error handling mechanism through Application Errors, Error Handlers, Custom Error Pages, the source code, and #Jonhasacat's suggestion. I think the best way to accomplish what I wanted in the program is to register an error handler at the app level for HTTPException. In my application, this is done as:
def handle_http_exception(e: HTTPException):
if request.path.startswith(API_PATH):
# Start with the response represented by the error
resp = e.get_response()
# jsonify the response
resp.set_data(
json.dumps(
{
'name': e.name,
'err_msg': e.description
}
)
)
resp.content_type = 'application/json'
return resp
else:
return e
app.register_error_handler(HTTPException, handle_http_exception)
This works because, roughly speaking, all errors raised in the process of handling a request that is an instance of Exception is either an HTTPException or an error to be converted to HTTPException if it doesn't have a handler registered for handling it.

How can I get uncaught exceptions to appear in the Django log

When there are uncaught exceptions in my Django project the log only shows a simple "HTTP 500" message. The HTTP response will contain the full stack trace as HTML but this is not very useful when I am developing web services not being consumed by a web browser. How can I get the full stack trace of uncaught exceptions to appear in the Django log?
I have tried installing custom middleware with a "process_exception" method and custom signals handler for the "got_request_exception" event but neither of these handlers ever got invoked.
I am using Django 1.6.1 and Tastypie 0.11.0 and I'm running in debug mode.
In your django settings set:
DEBUG_PROPAGATE_EXCEPTIONS = True
TASTYPIE_FULL_DEBUG = True
Setting both of these options will allow Tastypie exceptions to propagate upwards.
https://docs.djangoproject.com/en/3.2/ref/settings/#debug-propagate-exceptions
http://django-tastypie.readthedocs.org/en/latest/settings.html#tastypie-full-debug

Debug transient 404 errors

I sometimes get http 404 errors in my client on a certain url on my tastypie API.
However, when I access it manually via my browswer, it works all the time with the exact URL that the client is requesting.
This is a GET call with some query parameters:
https://example.com/v2/xxx?limit=&offset=&timestamp=
How can I debug this?
UPDATE 1
It looks like the error is returned by tastypie because the response body is {"error_message": "Sorry, this request could not be processed. Please try again later."}
UPDATE 2
It seems that it is a NOT_FOUND_EXCEPTIONS in tastypie resources.py, but how can I debug a transient problem? The data is pretty static and does not change.

Simulate server error

I use the App Engine for run my application and want to test how it will handle server errors.
Is there any possibility to simulate an error 500 via the WebTest ?
I got around it using a try except loop.
try:
self.testapp.get('/')
self.assertEqual(1, 2, 'GET request should have resulted in a 405 error') # Purposely fail
except webtest.app.AppError:
pass
Another way is the following:
self.assertEqual("500 Internal Server Error", self.testapp.post('/', params={}, expect_errors=True).status, 'POST Request should have resulted in a 500 error')
Both methods still will cause traceback to appear but the test passes
A 500 error is just what your webapp returns to the client when it gets an uncaught exception. It's not a specific failure - just what it shows to your users when something unexpected goes wrong. Instead, you should unit-test your handlers to ensure they act as expected.

Catching Django Errors When Client Is Not A Web Browser?

I'm building a Django web service that is called from an application. When it throws an exception, I can't see the Django debug page, and can't get to it because the calling application doesn't behave like a web browser (and I don't have control over that application).
Is there a way to redirect the Django error page to a a log file rather than to the calling client, possibly via changing the FastCGI config (I'm using lighty + FastCGI)? Or maybe a "dump to file" config option or some sort of LogExceptionToFile() method within the framework itself?
You might try just creating custom ExceptionMiddleware. Just change the process_exception method to log the exception and request data somewhere.
Here's an example: http://www.peterbe.com/plog/who-was-logged-in-during-a-django-exception
If the exception in the django app is not caught, and DEBUG = True, then the exception should be sent to the client.
Some options to help you get debugging info:
Enable and configure logging
Set up email error reporting
Use something like Wireshark to inspect the HTTP request and responses.