-
-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Add admin API to get some information about federation status #11407
Changes from 5 commits
e13af5c
3c9cd10
003028c
d9d469e
19d0459
8175dcc
4d966e7
be1f889
7bd0c47
c77a10f
6cc6a26
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| Add admin API to get some information about federation status with remote servers. |
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,81 @@ | ||||||||||
| # Federation API | ||||||||||
|
|
||||||||||
| This API allows a server administrator to manage Synapse's federation with other homeservers. | ||||||||||
|
|
||||||||||
| Note: This API is new, experimental and "subject to change". | ||||||||||
|
|
||||||||||
| ## List of destinations | ||||||||||
|
|
||||||||||
| This API gets the current destination retry timing info for a remote server. | ||||||||||
|
|
||||||||||
| The API is: | ||||||||||
|
|
||||||||||
| A standard request with no filtering: | ||||||||||
|
|
||||||||||
| ``` | ||||||||||
| GET /_synapse/admin/v1/federation/destinations | ||||||||||
| ``` | ||||||||||
|
|
||||||||||
| A response body like the following is returned: | ||||||||||
|
|
||||||||||
| ```json | ||||||||||
| { | ||||||||||
| "destinations":[ | ||||||||||
| { | ||||||||||
| "destination": "matrix.org", | ||||||||||
| "retry_last_ts": 1557332397936, | ||||||||||
| "retry_interval": 3000000, | ||||||||||
| "failure_ts": 1557329397936, | ||||||||||
| "last_successful_stream_ordering": null | ||||||||||
| } | ||||||||||
| ], | ||||||||||
| "total": 1 | ||||||||||
| } | ||||||||||
| ``` | ||||||||||
|
|
||||||||||
| To paginate, check for `next_token` and if present, call the endpoint again | ||||||||||
| with `from` set to the value of `next_token`. This will return a new page. | ||||||||||
|
|
||||||||||
| If the endpoint does not return a `next_token` then there are no more destinations | ||||||||||
| to paginate through. | ||||||||||
|
|
||||||||||
| **Parameters** | ||||||||||
|
|
||||||||||
| The following query parameters are available: | ||||||||||
|
|
||||||||||
| - `from` - Offset in the returned list. Defaults to `0`. | ||||||||||
| - `limit` - Maximum amount of destinations to return. Defaults to `100`. | ||||||||||
| - `order_by` - The method in which to sort the returned list of destinations. | ||||||||||
| Valid values are: | ||||||||||
| - `destination` - Destinations are ordered alphabetically by remote server name. | ||||||||||
| This is the default. | ||||||||||
|
Comment on lines
+55
to
+56
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This doesn't sound very stable to me to use as the initial sorting / pagination scheme. This might not matter usually, but is something to note.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The reason for this default sorting is the performances / indexes. All other columns have no indexes. The idea is not to generate a high load by default. |
||||||||||
| - `retry_last_ts` - Destinations are ordered by time of last retry attempt in ms. | ||||||||||
| - `retry_interval` - Destinations are ordered by how long until next retry in ms. | ||||||||||
| - `failure_ts` - Destinations are ordered by when the server started failing in ms. | ||||||||||
| - `last_successful_stream_ordering` - Destinations are ordered by the stream ordering | ||||||||||
| of the most recent successfully-sent PDU. | ||||||||||
| - `dir` - Direction of room order. Either `f` for forwards or `b` for backwards. Setting | ||||||||||
| this value to `b` will reverse the above sort order. Defaults to `f`. | ||||||||||
|
|
||||||||||
| *Caution:* The database only has an index on the column `destination`. | ||||||||||
| This means that if a different sort order is used, | ||||||||||
| this can cause a large load on the database, especially for large environments. | ||||||||||
|
|
||||||||||
| **Response** | ||||||||||
|
|
||||||||||
| The following fields are returned in the JSON response body: | ||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. A couple of questions:
Sorry---I appreciate that some of these questions are about how Synapse itself works, rather than this API. But I think they're the kind of thing that'd be useful to consider in the documentation.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. A few answers:
Every federated server should be in the list. synapse/synapse/storage/databases/main/transactions.py Lines 368 to 369 in 2b82ec4
Yes. synapse/synapse/storage/databases/main/transactions.py Lines 203 to 204 in 2b82ec4
Yes.
I don't know. |
||||||||||
|
|
||||||||||
| - `destinations` - An array of objects, each containing information about a destination. | ||||||||||
| Destinations objects contain the following fields: | ||||||||||
dklimpel marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||||||
| - `destination` - string - Name of the remote server to federate. | ||||||||||
| - `retry_last_ts` - integer - The last time Synapse tried and failed to reach the | ||||||||||
| remote server, in ms. | ||||||||||
| - `retry_interval` - integer - How long since the last time Synapse tried to reach | ||||||||||
| the remote server before trying again, in ms. | ||||||||||
| - `failure_ts` - integer - The first time Synapse tried and failed to reach the | ||||||||||
| remote server, in ms. | ||||||||||
| - `last_successful_stream_ordering` - integer - The stream ordering of the most | ||||||||||
dklimpel marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||||||
| recent successfully-sent [PDU](Understanding-Synapse-Performance-Issues-Through-Grafana-Graphs.md#federation) | ||||||||||
dklimpel marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||||||
| to this destination or `null` if this information has not been tracked yet. | ||||||||||
dklimpel marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||||||
| - `next_token`: string representing a positive integer - Indication for pagination. See above. | ||||||||||
| - `total` - integer - Total number of destinations. | ||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,90 @@ | ||
| # Copyright 2021 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. | ||
| import logging | ||
| from http import HTTPStatus | ||
| from typing import TYPE_CHECKING, Tuple | ||
|
|
||
| from synapse.api.errors import Codes, SynapseError | ||
| from synapse.http.servlet import RestServlet, parse_integer, parse_string | ||
| from synapse.http.site import SynapseRequest | ||
| from synapse.rest.admin._base import admin_patterns, assert_requester_is_admin | ||
| from synapse.storage.databases.main.transactions import DestinationSortOrder | ||
| from synapse.types import JsonDict | ||
|
|
||
| if TYPE_CHECKING: | ||
| from synapse.server import HomeServer | ||
|
|
||
| logger = logging.getLogger(__name__) | ||
|
|
||
|
|
||
| class FederationDestinationRestServlet(RestServlet): | ||
| """Get request to list all destinations. | ||
| This needs user to have administrator access in Synapse. | ||
|
|
||
| GET /_synapse/admin/v1/federation/destinations?from=0&limit=10 | ||
|
|
||
| returns: | ||
| 200 OK with list of destinations if success otherwise an error. | ||
|
|
||
| The parameters `from` and `limit` are required only for pagination. | ||
| By default, a `limit` of 100 is used. | ||
| The parameter `destination` can be used to filter by destination. | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I wonder if this might be served better by a separate endpoint for querying the status of one specific destination?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In the future, an API for a single destination can certainly be added. However, the aim is to design the API in a similar way like rooms or users.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I agree with @DMRobertson that this sounds like it should be a separate API, maybe
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I had in mind the use cases #7982 (comment) outlined here. But I don't mind there being a generic means to answer "what's the state of federation on my homeserver?", and this seems like a start to that. It's flagged as
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It is not easy for me to work on it. Information on the subject is hard to find. |
||
| The parameter `order_by` can be used to order the result. | ||
| """ | ||
|
|
||
| PATTERNS = admin_patterns("/federation/destinations$") | ||
|
|
||
| def __init__(self, hs: "HomeServer"): | ||
| self._auth = hs.get_auth() | ||
| self._store = hs.get_datastore() | ||
|
|
||
| async def on_GET(self, request: SynapseRequest) -> Tuple[int, JsonDict]: | ||
| await assert_requester_is_admin(self._auth, request) | ||
|
|
||
| start = parse_integer(request, "from", default=0) | ||
| limit = parse_integer(request, "limit", default=100) | ||
|
|
||
| if start < 0: | ||
| raise SynapseError( | ||
| HTTPStatus.BAD_REQUEST, | ||
| "Query parameter from must be a string representing a positive integer.", | ||
| errcode=Codes.INVALID_PARAM, | ||
| ) | ||
|
|
||
| if limit < 0: | ||
| raise SynapseError( | ||
| HTTPStatus.BAD_REQUEST, | ||
| "Query parameter limit must be a string representing a positive integer.", | ||
| errcode=Codes.INVALID_PARAM, | ||
| ) | ||
|
|
||
| destination = parse_string(request, "destination") | ||
|
|
||
| order_by = parse_string( | ||
| request, | ||
| "order_by", | ||
| default=DestinationSortOrder.DESTINATION.value, | ||
| allowed_values=[dest.value for dest in DestinationSortOrder], | ||
| ) | ||
|
|
||
| direction = parse_string(request, "dir", default="f", allowed_values=("f", "b")) | ||
|
|
||
| destinations, total = await self._store.get_destinations_paginate( | ||
| start, limit, destination, order_by, direction | ||
| ) | ||
| response = {"destinations": destinations, "total": total} | ||
| if (start + limit) < total: | ||
| response["next_token"] = str(start + len(destinations)) | ||
|
|
||
| return HTTPStatus.OK, response | ||
Uh oh!
There was an error while loading. Please reload this page.