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

Commit

Permalink
Prometheus metrics for logins and registrations (#9511)
Browse files Browse the repository at this point in the history
Add prom metrics for number of users successfully registering and logging in, by SSO provider.
  • Loading branch information
richvdh authored Mar 4, 2021
1 parent 7eb6e39 commit df425c2
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 4 deletions.
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

0 comments on commit df425c2

Please sign in to comment.