From c36228c40340f521ad52591ac3eab14946db4be2 Mon Sep 17 00:00:00 2001 From: Patrick Cloke Date: Thu, 6 Aug 2020 08:20:42 -0400 Subject: Convert run_as_background_process inner function to async. (#8032) --- synapse/http/site.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'synapse/http/site.py') diff --git a/synapse/http/site.py b/synapse/http/site.py index 6f3b2258cc..f506152fea 100644 --- a/synapse/http/site.py +++ b/synapse/http/site.py @@ -146,10 +146,9 @@ class SynapseRequest(Request): Returns a context manager; the correct way to use this is: - @defer.inlineCallbacks - def handle_request(request): + async def handle_request(request): with request.processing("FooServlet"): - yield really_handle_the_request() + await really_handle_the_request() Once the context manager is closed, the completion of the request will be logged, and the various metrics will be updated. -- cgit 1.5.1 From 7620912d84f6a8b24143f1340dd653f44b13bf30 Mon Sep 17 00:00:00 2001 From: Erik Johnston Date: Fri, 7 Aug 2020 14:21:24 +0100 Subject: Add health check endpoint (#8048) --- changelog.d/8048.feature | 1 + docs/reverse_proxy.md | 7 +++++++ synapse/app/generic_worker.py | 6 +++++- synapse/app/homeserver.py | 5 ++++- synapse/http/site.py | 9 ++++++++- synapse/rest/health.py | 31 +++++++++++++++++++++++++++++++ tests/rest/test_health.py | 34 ++++++++++++++++++++++++++++++++++ 7 files changed, 90 insertions(+), 3 deletions(-) create mode 100644 changelog.d/8048.feature create mode 100644 synapse/rest/health.py create mode 100644 tests/rest/test_health.py (limited to 'synapse/http/site.py') diff --git a/changelog.d/8048.feature b/changelog.d/8048.feature new file mode 100644 index 0000000000..8521d1920e --- /dev/null +++ b/changelog.d/8048.feature @@ -0,0 +1 @@ +Add a `/health` endpoint to every configured HTTP listener that can be used as a health check endpoint by load balancers. diff --git a/docs/reverse_proxy.md b/docs/reverse_proxy.md index 7bfb96eff6..fd48ba0874 100644 --- a/docs/reverse_proxy.md +++ b/docs/reverse_proxy.md @@ -139,3 +139,10 @@ client IP addresses are recorded correctly. Having done so, you can then use `https://matrix.example.com` (instead of `https://matrix.example.com:8448`) as the "Custom server" when connecting to Synapse from a client. + + +## Health check endpoint + +Synapse exposes a health check endpoint for use by reverse proxies. +Each configured HTTP listener has a `/health` endpoint which always returns +200 OK (and doesn't get logged). diff --git a/synapse/app/generic_worker.py b/synapse/app/generic_worker.py index 1a16d0b9f8..7957586d69 100644 --- a/synapse/app/generic_worker.py +++ b/synapse/app/generic_worker.py @@ -123,6 +123,7 @@ from synapse.rest.client.v2_alpha.account_data import ( from synapse.rest.client.v2_alpha.keys import KeyChangesServlet, KeyQueryServlet from synapse.rest.client.v2_alpha.register import RegisterRestServlet from synapse.rest.client.versions import VersionsRestServlet +from synapse.rest.health import HealthResource from synapse.rest.key.v2 import KeyApiV2Resource from synapse.server import HomeServer from synapse.storage.databases.main.censor_events import CensorEventsStore @@ -493,7 +494,10 @@ class GenericWorkerServer(HomeServer): site_tag = listener_config.http_options.tag if site_tag is None: site_tag = port - resources = {} + + # We always include a health resource. + resources = {"/health": HealthResource()} + for res in listener_config.http_options.resources: for name in res.names: if name == "metrics": diff --git a/synapse/app/homeserver.py b/synapse/app/homeserver.py index d87a77718e..98d0d14a12 100644 --- a/synapse/app/homeserver.py +++ b/synapse/app/homeserver.py @@ -68,6 +68,7 @@ from synapse.replication.http import REPLICATION_PREFIX, ReplicationRestResource from synapse.replication.tcp.resource import ReplicationStreamProtocolFactory from synapse.rest import ClientRestResource from synapse.rest.admin import AdminRestResource +from synapse.rest.health import HealthResource from synapse.rest.key.v2 import KeyApiV2Resource from synapse.rest.well_known import WellKnownResource from synapse.server import HomeServer @@ -98,7 +99,9 @@ class SynapseHomeServer(HomeServer): if site_tag is None: site_tag = port - resources = {} + # We always include a health resource. + resources = {"/health": HealthResource()} + for res in listener_config.http_options.resources: for name in res.names: if name == "openid" and "federation" in res.names: diff --git a/synapse/http/site.py b/synapse/http/site.py index f506152fea..79a9229a26 100644 --- a/synapse/http/site.py +++ b/synapse/http/site.py @@ -286,7 +286,9 @@ class SynapseRequest(Request): # the connection dropped) code += "!" - self.site.access_logger.info( + log_level = logging.INFO if self._should_log_request() else logging.DEBUG + self.site.access_logger.log( + log_level, "%s - %s - {%s}" " Processed request: %.3fsec/%.3fsec (%.3fsec, %.3fsec) (%.3fsec/%.3fsec/%d)" ' %sB %s "%s %s %s" "%s" [%d dbevts]', @@ -314,6 +316,11 @@ class SynapseRequest(Request): except Exception as e: logger.warning("Failed to stop metrics: %r", e) + def _should_log_request(self) -> bool: + """Whether we should log at INFO that we processed the request. + """ + return self.path != b"/health" + class XForwardedForRequest(SynapseRequest): def __init__(self, *args, **kw): diff --git a/synapse/rest/health.py b/synapse/rest/health.py new file mode 100644 index 0000000000..0170950bf3 --- /dev/null +++ b/synapse/rest/health.py @@ -0,0 +1,31 @@ +# -*- coding: utf-8 -*- +# Copyright 2020 The Matrix.org Foundation C.I.C. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from twisted.web.resource import Resource + + +class HealthResource(Resource): + """A resource that does nothing except return a 200 with a body of `OK`, + which can be used as a health check. + + Note: `SynapseRequest._should_log_request` ensures that requests to + `/health` do not get logged at INFO. + """ + + isLeaf = 1 + + def render_GET(self, request): + request.setHeader(b"Content-Type", b"text/plain") + return b"OK" diff --git a/tests/rest/test_health.py b/tests/rest/test_health.py new file mode 100644 index 0000000000..2d021f6565 --- /dev/null +++ b/tests/rest/test_health.py @@ -0,0 +1,34 @@ +# -*- coding: utf-8 -*- +# Copyright 2020 The Matrix.org Foundation C.I.C. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +from synapse.rest.health import HealthResource + +from tests import unittest + + +class HealthCheckTests(unittest.HomeserverTestCase): + def setUp(self): + super().setUp() + + # replace the JsonResource with a HealthResource. + self.resource = HealthResource() + + def test_health(self): + request, channel = self.make_request("GET", "/health", shorthand=False) + self.render(request) + + self.assertEqual(request.code, 200) + self.assertEqual(channel.result["body"], b"OK") -- cgit 1.5.1 From 2f9fd5ab00fa915fd76e5ebcfbbe458b17d0168e Mon Sep 17 00:00:00 2001 From: Erik Johnston Date: Fri, 7 Aug 2020 14:53:05 +0100 Subject: Don't log OPTIONS request at INFO (#8049) --- changelog.d/8049.misc | 1 + synapse/http/site.py | 8 +++++++- 2 files changed, 8 insertions(+), 1 deletion(-) create mode 100644 changelog.d/8049.misc (limited to 'synapse/http/site.py') diff --git a/changelog.d/8049.misc b/changelog.d/8049.misc new file mode 100644 index 0000000000..7fce36215d --- /dev/null +++ b/changelog.d/8049.misc @@ -0,0 +1 @@ +Log `OPTIONS` requests at `DEBUG` rather than `INFO` level to reduce amount logged at `INFO`. diff --git a/synapse/http/site.py b/synapse/http/site.py index 79a9229a26..6e79b47828 100644 --- a/synapse/http/site.py +++ b/synapse/http/site.py @@ -319,7 +319,13 @@ class SynapseRequest(Request): def _should_log_request(self) -> bool: """Whether we should log at INFO that we processed the request. """ - return self.path != b"/health" + if self.path == b"/health": + return False + + if self.method == b"OPTIONS": + return False + + return True class XForwardedForRequest(SynapseRequest): -- cgit 1.5.1