Skip to content
This repository has been archived by the owner on Apr 26, 2024. It is now read-only.

Prometheus metrics for logins and registrations #9511

Merged
merged 3 commits into from
Mar 4, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog.d/9511.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add prometheus metrics for number of users successfully registering and logging in.
35 changes: 33 additions & 2 deletions synapse/handlers/register.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
import logging
from typing import TYPE_CHECKING, Iterable, List, Optional, Tuple

from prometheus_client import Counter

from synapse import types
from synapse.api.constants import MAX_USERID_LENGTH, EventTypes, JoinRules, LoginType
from synapse.api.errors import AuthError, Codes, ConsentNotGivenError, SynapseError
Expand All @@ -41,6 +43,19 @@
logger = logging.getLogger(__name__)


registration_counter = Counter(
"synapse_user_registrations_total",
"Number of new users registered (since restart)",
["guest", "shadow_banned", "auth_provider"],
)

login_counter = Counter(
"synapse_user_logins_total",
"Number of user logins (since restart)",
["guest", "auth_provider"],
)


class RegistrationHandler(BaseHandler):
def __init__(self, hs: "HomeServer"):
super().__init__(hs)
Expand Down Expand Up @@ -156,6 +171,7 @@ async def register_user(
bind_emails: Iterable[str] = [],
by_admin: bool = False,
user_agent_ips: Optional[List[Tuple[str, str]]] = None,
auth_provider_id: Optional[str] = None,
) -> str:
"""Registers a new client on the server.

Expand All @@ -181,8 +197,10 @@ async def register_user(
admin api, otherwise False.
user_agent_ips: Tuples of IP addresses and user-agents used
during the registration process.
auth_provider_id: The SSO IdP the user used, if any (just used for the
prometheus metrics).
Returns:
The registere user_id.
The registered user_id.
Raises:
SynapseError if there was a problem registering.
"""
Expand Down Expand Up @@ -280,6 +298,12 @@ async def register_user(
# if user id is taken, just generate another
fail_count += 1

registration_counter.labels(
guest=make_guest,
shadow_banned=shadow_banned,
auth_provider=(auth_provider_id or ""),
).inc()

if not self.hs.config.user_consent_at_registration:
if not self.hs.config.auto_join_rooms_for_guests and make_guest:
logger.info(
Expand Down Expand Up @@ -638,6 +662,7 @@ async def register_device(
initial_display_name: Optional[str],
is_guest: bool = False,
is_appservice_ghost: bool = False,
auth_provider_id: Optional[str] = None,
) -> Tuple[str, str]:
"""Register a device for a user and generate an access token.

Expand All @@ -648,7 +673,8 @@ async def register_device(
device_id: The device ID to check, or None to generate a new one.
initial_display_name: An optional display name for the device.
is_guest: Whether this is a guest account

auth_provider_id: The SSO IdP the user used, if any (just used for the
prometheus metrics).
Returns:
Tuple of device ID and access token
"""
Expand Down Expand Up @@ -687,6 +713,11 @@ async def register_device(
is_appservice_ghost=is_appservice_ghost,
)

login_counter.labels(
guest=is_guest,
auth_provider=(auth_provider_id or ""),
).inc()

return (registered_device_id, access_token)

async def post_registration_actions(
Expand Down
1 change: 1 addition & 0 deletions synapse/handlers/sso.py
Original file line number Diff line number Diff line change
Expand Up @@ -606,6 +606,7 @@ async def _register_mapped_user(
default_display_name=attributes.display_name,
bind_emails=attributes.emails,
user_agent_ips=[(user_agent, ip_address)],
auth_provider_id=auth_provider_id,
)

await self._store.record_user_external_id(
Expand Down
10 changes: 8 additions & 2 deletions synapse/rest/client/v1/login.py
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,7 @@ async def _complete_login(
callback: Optional[Callable[[Dict[str, str]], Awaitable[None]]] = None,
create_non_existent_users: bool = False,
ratelimit: bool = True,
auth_provider_id: Optional[str] = None,
) -> Dict[str, str]:
"""Called when we've successfully authed the user and now need to
actually login them in (e.g. create devices). This gets called on
Expand All @@ -234,6 +235,8 @@ async def _complete_login(
create_non_existent_users: Whether to create the user if they don't
exist. Defaults to False.
ratelimit: Whether to ratelimit the login request.
auth_provider_id: The SSO IdP the user used, if any (just used for the
prometheus metrics).

Returns:
result: Dictionary of account information after successful login.
Expand All @@ -256,7 +259,7 @@ async def _complete_login(
device_id = login_submission.get("device_id")
initial_display_name = login_submission.get("initial_device_display_name")
device_id, access_token = await self.registration_handler.register_device(
user_id, device_id, initial_display_name
user_id, device_id, initial_display_name, auth_provider_id=auth_provider_id
)

result = {
Expand Down Expand Up @@ -286,7 +289,10 @@ async def _do_token_login(self, login_submission: JsonDict) -> Dict[str, str]:
res = await auth_handler.validate_short_term_login_token(token)

return await self._complete_login(
res.user_id, login_submission, self.auth_handler._sso_login_callback
res.user_id,
login_submission,
self.auth_handler._sso_login_callback,
auth_provider_id=res.auth_provider_id,
)

async def _do_jwt_login(self, login_submission: JsonDict) -> Dict[str, str]:
Expand Down