diff options
author | Sean Quah <seanq@element.io> | 2022-04-28 14:03:39 +0100 |
---|---|---|
committer | Sean Quah <seanq@element.io> | 2022-04-28 19:28:00 +0100 |
commit | 1ce7dbf42c24c139683e58cd79d0ad6f16502219 (patch) | |
tree | 0b7f28437d65005fc06d0e46b031231921fad0aa | |
parent | Add `@cancellable` decorator, for use on request handlers (diff) | |
download | synapse-1ce7dbf42c24c139683e58cd79d0ad6f16502219.tar.xz |
Improve logging for cancelled requests
Don't log stack traces for cancelled requests and use a custom HTTP status code of 499. Signed-off-by: Sean Quah <seanq@element.io>
-rw-r--r-- | synapse/http/server.py | 31 |
1 files changed, 31 insertions, 0 deletions
diff --git a/synapse/http/server.py b/synapse/http/server.py index 8e91a4b50c..f19c0c4f2d 100644 --- a/synapse/http/server.py +++ b/synapse/http/server.py @@ -44,6 +44,7 @@ from typing_extensions import Protocol from zope.interface import implementer from twisted.internet import defer, interfaces +from twisted.internet.defer import CancelledError from twisted.python import failure from twisted.web import resource from twisted.web.server import NOT_DONE_YET, Request @@ -83,6 +84,15 @@ HTML_ERROR_TEMPLATE = """<!DOCTYPE html> </html> """ +# A fictional HTTP status code for requests where the client has disconnected and we +# successfully cancelled the request. Used only for logging purposes. Clients will never +# observe this code unless cancellations leak across requests or we raise a +# `CancelledError` ourselves. +# Analogous to nginx's 499 status code: +# https://github.com/nginx/nginx/blob/release-1.21.6/src/http/ngx_http_request.h#L128-L134 +HTTP_STATUS_REQUEST_CANCELLED = 499 + + F = TypeVar("F", bound=Callable[..., Any]) @@ -140,6 +150,17 @@ def return_json_error(f: failure.Failure, request: SynapseRequest) -> None: error_dict = exc.error_dict() logger.info("%s SynapseError: %s - %s", request, error_code, exc.msg) + elif f.check(CancelledError): + error_code = HTTP_STATUS_REQUEST_CANCELLED + error_dict = {"error": "Request cancelled", "errcode": Codes.UNKNOWN} + + if not request._disconnected: + logger.error( + "Got cancellation before client disconnection from %r: %r", + request.request_metrics.name, + request, + exc_info=(f.type, f.value, f.getTracebackObject()), # type: ignore[arg-type] + ) else: error_code = 500 error_dict = {"error": "Internal server error", "errcode": Codes.UNKNOWN} @@ -202,6 +223,16 @@ def return_html_error( request, exc_info=(f.type, f.value, f.getTracebackObject()), # type: ignore[arg-type] ) + elif f.check(CancelledError): + code = HTTP_STATUS_REQUEST_CANCELLED + msg = "Request cancelled" + + if not request._disconnected: + logger.error( + "Got cancellation before client disconnection when handling request %r", + request, + exc_info=(f.type, f.value, f.getTracebackObject()), # type: ignore[arg-type] + ) else: code = HTTPStatus.INTERNAL_SERVER_ERROR msg = "Internal server error" |