forked from MirrorHub/synapse
Fix servlet metric names (#5734)
* Fix servlet metric names Co-Authored-By: Richard van der Hoff <1389908+richvdh@users.noreply.github.com> * Remove redundant check * Cover all return paths
This commit is contained in:
parent
8b0d5b171e
commit
cf2972c818
1
changelog.d/5734.bugfix
Normal file
1
changelog.d/5734.bugfix
Normal file
|
@ -0,0 +1 @@
|
||||||
|
Fix a regression introduced in v1.2.0rc1 which led to incorrect labels on some prometheus metrics.
|
|
@ -325,7 +325,9 @@ class BaseFederationServlet(object):
|
||||||
if code is None:
|
if code is None:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
server.register_paths(method, (pattern,), self._wrap(code))
|
server.register_paths(
|
||||||
|
method, (pattern,), self._wrap(code), self.__class__.__name__
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class FederationSendServlet(BaseFederationServlet):
|
class FederationSendServlet(BaseFederationServlet):
|
||||||
|
|
|
@ -245,7 +245,9 @@ class JsonResource(HttpServer, resource.Resource):
|
||||||
|
|
||||||
isLeaf = True
|
isLeaf = True
|
||||||
|
|
||||||
_PathEntry = collections.namedtuple("_PathEntry", ["pattern", "callback"])
|
_PathEntry = collections.namedtuple(
|
||||||
|
"_PathEntry", ["pattern", "callback", "servlet_classname"]
|
||||||
|
)
|
||||||
|
|
||||||
def __init__(self, hs, canonical_json=True):
|
def __init__(self, hs, canonical_json=True):
|
||||||
resource.Resource.__init__(self)
|
resource.Resource.__init__(self)
|
||||||
|
@ -255,12 +257,28 @@ class JsonResource(HttpServer, resource.Resource):
|
||||||
self.path_regexs = {}
|
self.path_regexs = {}
|
||||||
self.hs = hs
|
self.hs = hs
|
||||||
|
|
||||||
def register_paths(self, method, path_patterns, callback):
|
def register_paths(self, method, path_patterns, callback, servlet_classname):
|
||||||
|
"""
|
||||||
|
Registers a request handler against a regular expression. Later request URLs are
|
||||||
|
checked against these regular expressions in order to identify an appropriate
|
||||||
|
handler for that request.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
method (str): GET, POST etc
|
||||||
|
|
||||||
|
path_patterns (Iterable[str]): A list of regular expressions to which
|
||||||
|
the request URLs are compared.
|
||||||
|
|
||||||
|
callback (function): The handler for the request. Usually a Servlet
|
||||||
|
|
||||||
|
servlet_classname (str): The name of the handler to be used in prometheus
|
||||||
|
and opentracing logs.
|
||||||
|
"""
|
||||||
method = method.encode("utf-8") # method is bytes on py3
|
method = method.encode("utf-8") # method is bytes on py3
|
||||||
for path_pattern in path_patterns:
|
for path_pattern in path_patterns:
|
||||||
logger.debug("Registering for %s %s", method, path_pattern.pattern)
|
logger.debug("Registering for %s %s", method, path_pattern.pattern)
|
||||||
self.path_regexs.setdefault(method, []).append(
|
self.path_regexs.setdefault(method, []).append(
|
||||||
self._PathEntry(path_pattern, callback)
|
self._PathEntry(path_pattern, callback, servlet_classname)
|
||||||
)
|
)
|
||||||
|
|
||||||
def render(self, request):
|
def render(self, request):
|
||||||
|
@ -275,13 +293,9 @@ class JsonResource(HttpServer, resource.Resource):
|
||||||
This checks if anyone has registered a callback for that method and
|
This checks if anyone has registered a callback for that method and
|
||||||
path.
|
path.
|
||||||
"""
|
"""
|
||||||
callback, group_dict = self._get_handler_for_request(request)
|
callback, servlet_classname, group_dict = self._get_handler_for_request(request)
|
||||||
|
|
||||||
servlet_instance = getattr(callback, "__self__", None)
|
# Make sure we have a name for this handler in prometheus.
|
||||||
if servlet_instance is not None:
|
|
||||||
servlet_classname = servlet_instance.__class__.__name__
|
|
||||||
else:
|
|
||||||
servlet_classname = "%r" % callback
|
|
||||||
request.request_metrics.name = servlet_classname
|
request.request_metrics.name = servlet_classname
|
||||||
|
|
||||||
# Now trigger the callback. If it returns a response, we send it
|
# Now trigger the callback. If it returns a response, we send it
|
||||||
|
@ -311,7 +325,8 @@ class JsonResource(HttpServer, resource.Resource):
|
||||||
request (twisted.web.http.Request):
|
request (twisted.web.http.Request):
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Tuple[Callable, dict[unicode, unicode]]: callback method, and the
|
Tuple[Callable, str, dict[unicode, unicode]]: callback method, the
|
||||||
|
label to use for that method in prometheus metrics, and the
|
||||||
dict mapping keys to path components as specified in the
|
dict mapping keys to path components as specified in the
|
||||||
handler's path match regexp.
|
handler's path match regexp.
|
||||||
|
|
||||||
|
@ -320,7 +335,7 @@ class JsonResource(HttpServer, resource.Resource):
|
||||||
None, or a tuple of (http code, response body).
|
None, or a tuple of (http code, response body).
|
||||||
"""
|
"""
|
||||||
if request.method == b"OPTIONS":
|
if request.method == b"OPTIONS":
|
||||||
return _options_handler, {}
|
return _options_handler, "options_request_handler", {}
|
||||||
|
|
||||||
# Loop through all the registered callbacks to check if the method
|
# Loop through all the registered callbacks to check if the method
|
||||||
# and path regex match
|
# and path regex match
|
||||||
|
@ -328,10 +343,10 @@ class JsonResource(HttpServer, resource.Resource):
|
||||||
m = path_entry.pattern.match(request.path.decode("ascii"))
|
m = path_entry.pattern.match(request.path.decode("ascii"))
|
||||||
if m:
|
if m:
|
||||||
# We found a match!
|
# We found a match!
|
||||||
return path_entry.callback, m.groupdict()
|
return path_entry.callback, path_entry.servlet_classname, m.groupdict()
|
||||||
|
|
||||||
# Huh. No one wanted to handle that? Fiiiiiine. Send 400.
|
# Huh. No one wanted to handle that? Fiiiiiine. Send 400.
|
||||||
return _unrecognised_request_handler, {}
|
return _unrecognised_request_handler, "unrecognised_request_handler", {}
|
||||||
|
|
||||||
def _send_response(
|
def _send_response(
|
||||||
self, request, code, response_json_object, response_code_message=None
|
self, request, code, response_json_object, response_code_message=None
|
||||||
|
|
|
@ -290,11 +290,13 @@ class RestServlet(object):
|
||||||
|
|
||||||
for method in ("GET", "PUT", "POST", "OPTIONS", "DELETE"):
|
for method in ("GET", "PUT", "POST", "OPTIONS", "DELETE"):
|
||||||
if hasattr(self, "on_%s" % (method,)):
|
if hasattr(self, "on_%s" % (method,)):
|
||||||
|
servlet_classname = self.__class__.__name__
|
||||||
method_handler = getattr(self, "on_%s" % (method,))
|
method_handler = getattr(self, "on_%s" % (method,))
|
||||||
http_server.register_paths(
|
http_server.register_paths(
|
||||||
method,
|
method,
|
||||||
patterns,
|
patterns,
|
||||||
trace_servlet(self.__class__.__name__, method_handler),
|
trace_servlet(servlet_classname, method_handler),
|
||||||
|
servlet_classname,
|
||||||
)
|
)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -205,7 +205,7 @@ class ReplicationEndpoint(object):
|
||||||
args = "/".join("(?P<%s>[^/]+)" % (arg,) for arg in url_args)
|
args = "/".join("(?P<%s>[^/]+)" % (arg,) for arg in url_args)
|
||||||
pattern = re.compile("^/_synapse/replication/%s/%s$" % (self.NAME, args))
|
pattern = re.compile("^/_synapse/replication/%s/%s$" % (self.NAME, args))
|
||||||
|
|
||||||
http_server.register_paths(method, [pattern], handler)
|
http_server.register_paths(method, [pattern], handler, self.__class__.__name__)
|
||||||
|
|
||||||
def _cached_handler(self, request, txn_id, **kwargs):
|
def _cached_handler(self, request, txn_id, **kwargs):
|
||||||
"""Called on new incoming requests when caching is enabled. Checks
|
"""Called on new incoming requests when caching is enabled. Checks
|
||||||
|
|
|
@ -59,9 +59,14 @@ class SendServerNoticeServlet(RestServlet):
|
||||||
|
|
||||||
def register(self, json_resource):
|
def register(self, json_resource):
|
||||||
PATTERN = "^/_synapse/admin/v1/send_server_notice"
|
PATTERN = "^/_synapse/admin/v1/send_server_notice"
|
||||||
json_resource.register_paths("POST", (re.compile(PATTERN + "$"),), self.on_POST)
|
|
||||||
json_resource.register_paths(
|
json_resource.register_paths(
|
||||||
"PUT", (re.compile(PATTERN + "/(?P<txn_id>[^/]*)$"),), self.on_PUT
|
"POST", (re.compile(PATTERN + "$"),), self.on_POST, self.__class__.__name__
|
||||||
|
)
|
||||||
|
json_resource.register_paths(
|
||||||
|
"PUT",
|
||||||
|
(re.compile(PATTERN + "/(?P<txn_id>[^/]*)$"),),
|
||||||
|
self.on_PUT,
|
||||||
|
self.__class__.__name__,
|
||||||
)
|
)
|
||||||
|
|
||||||
@defer.inlineCallbacks
|
@defer.inlineCallbacks
|
||||||
|
|
|
@ -67,11 +67,17 @@ class RoomCreateRestServlet(TransactionRestServlet):
|
||||||
register_txn_path(self, PATTERNS, http_server)
|
register_txn_path(self, PATTERNS, http_server)
|
||||||
# define CORS for all of /rooms in RoomCreateRestServlet for simplicity
|
# define CORS for all of /rooms in RoomCreateRestServlet for simplicity
|
||||||
http_server.register_paths(
|
http_server.register_paths(
|
||||||
"OPTIONS", client_patterns("/rooms(?:/.*)?$", v1=True), self.on_OPTIONS
|
"OPTIONS",
|
||||||
|
client_patterns("/rooms(?:/.*)?$", v1=True),
|
||||||
|
self.on_OPTIONS,
|
||||||
|
self.__class__.__name__,
|
||||||
)
|
)
|
||||||
# define CORS for /createRoom[/txnid]
|
# define CORS for /createRoom[/txnid]
|
||||||
http_server.register_paths(
|
http_server.register_paths(
|
||||||
"OPTIONS", client_patterns("/createRoom(?:/.*)?$", v1=True), self.on_OPTIONS
|
"OPTIONS",
|
||||||
|
client_patterns("/createRoom(?:/.*)?$", v1=True),
|
||||||
|
self.on_OPTIONS,
|
||||||
|
self.__class__.__name__,
|
||||||
)
|
)
|
||||||
|
|
||||||
def on_PUT(self, request, txn_id):
|
def on_PUT(self, request, txn_id):
|
||||||
|
@ -116,16 +122,28 @@ class RoomStateEventRestServlet(TransactionRestServlet):
|
||||||
)
|
)
|
||||||
|
|
||||||
http_server.register_paths(
|
http_server.register_paths(
|
||||||
"GET", client_patterns(state_key, v1=True), self.on_GET
|
"GET",
|
||||||
|
client_patterns(state_key, v1=True),
|
||||||
|
self.on_GET,
|
||||||
|
self.__class__.__name__,
|
||||||
)
|
)
|
||||||
http_server.register_paths(
|
http_server.register_paths(
|
||||||
"PUT", client_patterns(state_key, v1=True), self.on_PUT
|
"PUT",
|
||||||
|
client_patterns(state_key, v1=True),
|
||||||
|
self.on_PUT,
|
||||||
|
self.__class__.__name__,
|
||||||
)
|
)
|
||||||
http_server.register_paths(
|
http_server.register_paths(
|
||||||
"GET", client_patterns(no_state_key, v1=True), self.on_GET_no_state_key
|
"GET",
|
||||||
|
client_patterns(no_state_key, v1=True),
|
||||||
|
self.on_GET_no_state_key,
|
||||||
|
self.__class__.__name__,
|
||||||
)
|
)
|
||||||
http_server.register_paths(
|
http_server.register_paths(
|
||||||
"PUT", client_patterns(no_state_key, v1=True), self.on_PUT_no_state_key
|
"PUT",
|
||||||
|
client_patterns(no_state_key, v1=True),
|
||||||
|
self.on_PUT_no_state_key,
|
||||||
|
self.__class__.__name__,
|
||||||
)
|
)
|
||||||
|
|
||||||
def on_GET_no_state_key(self, request, room_id, event_type):
|
def on_GET_no_state_key(self, request, room_id, event_type):
|
||||||
|
@ -845,18 +863,23 @@ def register_txn_path(servlet, regex_string, http_server, with_get=False):
|
||||||
with_get: True to also register respective GET paths for the PUTs.
|
with_get: True to also register respective GET paths for the PUTs.
|
||||||
"""
|
"""
|
||||||
http_server.register_paths(
|
http_server.register_paths(
|
||||||
"POST", client_patterns(regex_string + "$", v1=True), servlet.on_POST
|
"POST",
|
||||||
|
client_patterns(regex_string + "$", v1=True),
|
||||||
|
servlet.on_POST,
|
||||||
|
servlet.__class__.__name__,
|
||||||
)
|
)
|
||||||
http_server.register_paths(
|
http_server.register_paths(
|
||||||
"PUT",
|
"PUT",
|
||||||
client_patterns(regex_string + "/(?P<txn_id>[^/]*)$", v1=True),
|
client_patterns(regex_string + "/(?P<txn_id>[^/]*)$", v1=True),
|
||||||
servlet.on_PUT,
|
servlet.on_PUT,
|
||||||
|
servlet.__class__.__name__,
|
||||||
)
|
)
|
||||||
if with_get:
|
if with_get:
|
||||||
http_server.register_paths(
|
http_server.register_paths(
|
||||||
"GET",
|
"GET",
|
||||||
client_patterns(regex_string + "/(?P<txn_id>[^/]*)$", v1=True),
|
client_patterns(regex_string + "/(?P<txn_id>[^/]*)$", v1=True),
|
||||||
servlet.on_GET,
|
servlet.on_GET,
|
||||||
|
servlet.__class__.__name__,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -72,11 +72,13 @@ class RelationSendServlet(RestServlet):
|
||||||
"POST",
|
"POST",
|
||||||
client_patterns(self.PATTERN + "$", releases=()),
|
client_patterns(self.PATTERN + "$", releases=()),
|
||||||
self.on_PUT_or_POST,
|
self.on_PUT_or_POST,
|
||||||
|
self.__class__.__name__,
|
||||||
)
|
)
|
||||||
http_server.register_paths(
|
http_server.register_paths(
|
||||||
"PUT",
|
"PUT",
|
||||||
client_patterns(self.PATTERN + "/(?P<txn_id>[^/]*)$", releases=()),
|
client_patterns(self.PATTERN + "/(?P<txn_id>[^/]*)$", releases=()),
|
||||||
self.on_PUT,
|
self.on_PUT,
|
||||||
|
self.__class__.__name__,
|
||||||
)
|
)
|
||||||
|
|
||||||
def on_PUT(self, request, *args, **kwargs):
|
def on_PUT(self, request, *args, **kwargs):
|
||||||
|
|
|
@ -61,7 +61,10 @@ class JsonResourceTests(unittest.TestCase):
|
||||||
|
|
||||||
res = JsonResource(self.homeserver)
|
res = JsonResource(self.homeserver)
|
||||||
res.register_paths(
|
res.register_paths(
|
||||||
"GET", [re.compile("^/_matrix/foo/(?P<room_id>[^/]*)$")], _callback
|
"GET",
|
||||||
|
[re.compile("^/_matrix/foo/(?P<room_id>[^/]*)$")],
|
||||||
|
_callback,
|
||||||
|
"test_servlet",
|
||||||
)
|
)
|
||||||
|
|
||||||
request, channel = make_request(
|
request, channel = make_request(
|
||||||
|
@ -82,7 +85,9 @@ class JsonResourceTests(unittest.TestCase):
|
||||||
raise Exception("boo")
|
raise Exception("boo")
|
||||||
|
|
||||||
res = JsonResource(self.homeserver)
|
res = JsonResource(self.homeserver)
|
||||||
res.register_paths("GET", [re.compile("^/_matrix/foo$")], _callback)
|
res.register_paths(
|
||||||
|
"GET", [re.compile("^/_matrix/foo$")], _callback, "test_servlet"
|
||||||
|
)
|
||||||
|
|
||||||
request, channel = make_request(self.reactor, b"GET", b"/_matrix/foo")
|
request, channel = make_request(self.reactor, b"GET", b"/_matrix/foo")
|
||||||
render(request, res, self.reactor)
|
render(request, res, self.reactor)
|
||||||
|
@ -105,7 +110,9 @@ class JsonResourceTests(unittest.TestCase):
|
||||||
return make_deferred_yieldable(d)
|
return make_deferred_yieldable(d)
|
||||||
|
|
||||||
res = JsonResource(self.homeserver)
|
res = JsonResource(self.homeserver)
|
||||||
res.register_paths("GET", [re.compile("^/_matrix/foo$")], _callback)
|
res.register_paths(
|
||||||
|
"GET", [re.compile("^/_matrix/foo$")], _callback, "test_servlet"
|
||||||
|
)
|
||||||
|
|
||||||
request, channel = make_request(self.reactor, b"GET", b"/_matrix/foo")
|
request, channel = make_request(self.reactor, b"GET", b"/_matrix/foo")
|
||||||
render(request, res, self.reactor)
|
render(request, res, self.reactor)
|
||||||
|
@ -122,7 +129,9 @@ class JsonResourceTests(unittest.TestCase):
|
||||||
raise SynapseError(403, "Forbidden!!one!", Codes.FORBIDDEN)
|
raise SynapseError(403, "Forbidden!!one!", Codes.FORBIDDEN)
|
||||||
|
|
||||||
res = JsonResource(self.homeserver)
|
res = JsonResource(self.homeserver)
|
||||||
res.register_paths("GET", [re.compile("^/_matrix/foo$")], _callback)
|
res.register_paths(
|
||||||
|
"GET", [re.compile("^/_matrix/foo$")], _callback, "test_servlet"
|
||||||
|
)
|
||||||
|
|
||||||
request, channel = make_request(self.reactor, b"GET", b"/_matrix/foo")
|
request, channel = make_request(self.reactor, b"GET", b"/_matrix/foo")
|
||||||
render(request, res, self.reactor)
|
render(request, res, self.reactor)
|
||||||
|
@ -143,7 +152,9 @@ class JsonResourceTests(unittest.TestCase):
|
||||||
self.fail("shouldn't ever get here")
|
self.fail("shouldn't ever get here")
|
||||||
|
|
||||||
res = JsonResource(self.homeserver)
|
res = JsonResource(self.homeserver)
|
||||||
res.register_paths("GET", [re.compile("^/_matrix/foo$")], _callback)
|
res.register_paths(
|
||||||
|
"GET", [re.compile("^/_matrix/foo$")], _callback, "test_servlet"
|
||||||
|
)
|
||||||
|
|
||||||
request, channel = make_request(self.reactor, b"GET", b"/_matrix/foobar")
|
request, channel = make_request(self.reactor, b"GET", b"/_matrix/foobar")
|
||||||
render(request, res, self.reactor)
|
render(request, res, self.reactor)
|
||||||
|
|
|
@ -471,7 +471,7 @@ class MockHttpResource(HttpServer):
|
||||||
|
|
||||||
raise KeyError("No event can handle %s" % path)
|
raise KeyError("No event can handle %s" % path)
|
||||||
|
|
||||||
def register_paths(self, method, path_patterns, callback):
|
def register_paths(self, method, path_patterns, callback, servlet_name):
|
||||||
for path_pattern in path_patterns:
|
for path_pattern in path_patterns:
|
||||||
self.callbacks.append((method, path_pattern, callback))
|
self.callbacks.append((method, path_pattern, callback))
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue