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

Commit df425c2

Browse files
authored
Prometheus metrics for logins and registrations (#9511)
Add prom metrics for number of users successfully registering and logging in, by SSO provider.
1 parent 7eb6e39 commit df425c2

File tree

4 files changed

+43
-4
lines changed

4 files changed

+43
-4
lines changed

changelog.d/9511.feature

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Add prometheus metrics for number of users successfully registering and logging in.

synapse/handlers/register.py

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
import logging
1919
from typing import TYPE_CHECKING, Iterable, List, Optional, Tuple
2020

21+
from prometheus_client import Counter
22+
2123
from synapse import types
2224
from synapse.api.constants import MAX_USERID_LENGTH, EventTypes, JoinRules, LoginType
2325
from synapse.api.errors import AuthError, Codes, ConsentNotGivenError, SynapseError
@@ -41,6 +43,19 @@
4143
logger = logging.getLogger(__name__)
4244

4345

46+
registration_counter = Counter(
47+
"synapse_user_registrations_total",
48+
"Number of new users registered (since restart)",
49+
["guest", "shadow_banned", "auth_provider"],
50+
)
51+
52+
login_counter = Counter(
53+
"synapse_user_logins_total",
54+
"Number of user logins (since restart)",
55+
["guest", "auth_provider"],
56+
)
57+
58+
4459
class RegistrationHandler(BaseHandler):
4560
def __init__(self, hs: "HomeServer"):
4661
super().__init__(hs)
@@ -156,6 +171,7 @@ async def register_user(
156171
bind_emails: Iterable[str] = [],
157172
by_admin: bool = False,
158173
user_agent_ips: Optional[List[Tuple[str, str]]] = None,
174+
auth_provider_id: Optional[str] = None,
159175
) -> str:
160176
"""Registers a new client on the server.
161177
@@ -181,8 +197,10 @@ async def register_user(
181197
admin api, otherwise False.
182198
user_agent_ips: Tuples of IP addresses and user-agents used
183199
during the registration process.
200+
auth_provider_id: The SSO IdP the user used, if any (just used for the
201+
prometheus metrics).
184202
Returns:
185-
The registere user_id.
203+
The registered user_id.
186204
Raises:
187205
SynapseError if there was a problem registering.
188206
"""
@@ -280,6 +298,12 @@ async def register_user(
280298
# if user id is taken, just generate another
281299
fail_count += 1
282300

301+
registration_counter.labels(
302+
guest=make_guest,
303+
shadow_banned=shadow_banned,
304+
auth_provider=(auth_provider_id or ""),
305+
).inc()
306+
283307
if not self.hs.config.user_consent_at_registration:
284308
if not self.hs.config.auto_join_rooms_for_guests and make_guest:
285309
logger.info(
@@ -638,6 +662,7 @@ async def register_device(
638662
initial_display_name: Optional[str],
639663
is_guest: bool = False,
640664
is_appservice_ghost: bool = False,
665+
auth_provider_id: Optional[str] = None,
641666
) -> Tuple[str, str]:
642667
"""Register a device for a user and generate an access token.
643668
@@ -648,7 +673,8 @@ async def register_device(
648673
device_id: The device ID to check, or None to generate a new one.
649674
initial_display_name: An optional display name for the device.
650675
is_guest: Whether this is a guest account
651-
676+
auth_provider_id: The SSO IdP the user used, if any (just used for the
677+
prometheus metrics).
652678
Returns:
653679
Tuple of device ID and access token
654680
"""
@@ -687,6 +713,11 @@ async def register_device(
687713
is_appservice_ghost=is_appservice_ghost,
688714
)
689715

716+
login_counter.labels(
717+
guest=is_guest,
718+
auth_provider=(auth_provider_id or ""),
719+
).inc()
720+
690721
return (registered_device_id, access_token)
691722

692723
async def post_registration_actions(

synapse/handlers/sso.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -606,6 +606,7 @@ async def _register_mapped_user(
606606
default_display_name=attributes.display_name,
607607
bind_emails=attributes.emails,
608608
user_agent_ips=[(user_agent, ip_address)],
609+
auth_provider_id=auth_provider_id,
609610
)
610611

611612
await self._store.record_user_external_id(

synapse/rest/client/v1/login.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,7 @@ async def _complete_login(
219219
callback: Optional[Callable[[Dict[str, str]], Awaitable[None]]] = None,
220220
create_non_existent_users: bool = False,
221221
ratelimit: bool = True,
222+
auth_provider_id: Optional[str] = None,
222223
) -> Dict[str, str]:
223224
"""Called when we've successfully authed the user and now need to
224225
actually login them in (e.g. create devices). This gets called on
@@ -234,6 +235,8 @@ async def _complete_login(
234235
create_non_existent_users: Whether to create the user if they don't
235236
exist. Defaults to False.
236237
ratelimit: Whether to ratelimit the login request.
238+
auth_provider_id: The SSO IdP the user used, if any (just used for the
239+
prometheus metrics).
237240
238241
Returns:
239242
result: Dictionary of account information after successful login.
@@ -256,7 +259,7 @@ async def _complete_login(
256259
device_id = login_submission.get("device_id")
257260
initial_display_name = login_submission.get("initial_device_display_name")
258261
device_id, access_token = await self.registration_handler.register_device(
259-
user_id, device_id, initial_display_name
262+
user_id, device_id, initial_display_name, auth_provider_id=auth_provider_id
260263
)
261264

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

288291
return await self._complete_login(
289-
res.user_id, login_submission, self.auth_handler._sso_login_callback
292+
res.user_id,
293+
login_submission,
294+
self.auth_handler._sso_login_callback,
295+
auth_provider_id=res.auth_provider_id,
290296
)
291297

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

0 commit comments

Comments
 (0)