Correctly initialise the `synapse_user_logins` metric. (#10677)

Fix a bug where the prometheus metrics for SSO logins wouldn't be initialised
until the first user logged in with a given auth provider.
This commit is contained in:
Richard van der Hoff 2021-08-24 10:17:51 +01:00 committed by GitHub
parent 86415f162d
commit 15db8b7c7f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 44 additions and 6 deletions

1
changelog.d/10677.bugfix Normal file
View File

@ -0,0 +1 @@
Fix a bug which caused the `synapse_user_logins_total` Prometheus metric not to be correctly initialised on restart.

View File

@ -56,6 +56,22 @@ login_counter = Counter(
) )
def init_counters_for_auth_provider(auth_provider_id: str) -> None:
"""Ensure the prometheus counters for the given auth provider are initialised
This fixes a problem where the counters are not reported for a given auth provider
until the user first logs in/registers.
"""
for is_guest in (True, False):
login_counter.labels(guest=is_guest, auth_provider=auth_provider_id)
for shadow_banned in (True, False):
registration_counter.labels(
guest=is_guest,
shadow_banned=shadow_banned,
auth_provider=auth_provider_id,
)
class LoginDict(TypedDict): class LoginDict(TypedDict):
device_id: str device_id: str
access_token: str access_token: str
@ -96,6 +112,8 @@ class RegistrationHandler(BaseHandler):
self.session_lifetime = hs.config.session_lifetime self.session_lifetime = hs.config.session_lifetime
self.access_token_lifetime = hs.config.access_token_lifetime self.access_token_lifetime = hs.config.access_token_lifetime
init_counters_for_auth_provider("")
async def check_username( async def check_username(
self, self,
localpart: str, localpart: str,

View File

@ -37,6 +37,7 @@ from twisted.web.server import Request
from synapse.api.constants import LoginType from synapse.api.constants import LoginType
from synapse.api.errors import Codes, NotFoundError, RedirectException, SynapseError from synapse.api.errors import Codes, NotFoundError, RedirectException, SynapseError
from synapse.config.sso import SsoAttributeRequirement from synapse.config.sso import SsoAttributeRequirement
from synapse.handlers.register import init_counters_for_auth_provider
from synapse.handlers.ui_auth import UIAuthSessionDataConstants from synapse.handlers.ui_auth import UIAuthSessionDataConstants
from synapse.http import get_request_user_agent from synapse.http import get_request_user_agent
from synapse.http.server import respond_with_html, respond_with_redirect from synapse.http.server import respond_with_html, respond_with_redirect
@ -213,6 +214,7 @@ class SsoHandler:
p_id = p.idp_id p_id = p.idp_id
assert p_id not in self._identity_providers assert p_id not in self._identity_providers
self._identity_providers[p_id] = p self._identity_providers[p_id] = p
init_counters_for_auth_provider(p_id)
def get_identity_providers(self) -> Mapping[str, SsoIdentityProvider]: def get_identity_providers(self) -> Mapping[str, SsoIdentityProvider]:
"""Get the configured identity providers""" """Get the configured identity providers"""

View File

@ -104,6 +104,12 @@ class LoginRestServlet(RestServlet):
burst_count=self.hs.config.rc_login_account.burst_count, burst_count=self.hs.config.rc_login_account.burst_count,
) )
# ensure the CAS/SAML/OIDC handlers are loaded on this worker instance.
# The reason for this is to ensure that the auth_provider_ids are registered
# with SsoHandler, which in turn ensures that the login/registration prometheus
# counters are initialised for the auth_provider_ids.
_load_sso_handlers(hs)
def on_GET(self, request: SynapseRequest): def on_GET(self, request: SynapseRequest):
flows = [] flows = []
if self.jwt_enabled: if self.jwt_enabled:
@ -499,12 +505,7 @@ class SsoRedirectServlet(RestServlet):
def __init__(self, hs: "HomeServer"): def __init__(self, hs: "HomeServer"):
# make sure that the relevant handlers are instantiated, so that they # make sure that the relevant handlers are instantiated, so that they
# register themselves with the main SSOHandler. # register themselves with the main SSOHandler.
if hs.config.cas_enabled: _load_sso_handlers(hs)
hs.get_cas_handler()
if hs.config.saml2_enabled:
hs.get_saml_handler()
if hs.config.oidc_enabled:
hs.get_oidc_handler()
self._sso_handler = hs.get_sso_handler() self._sso_handler = hs.get_sso_handler()
self._msc2858_enabled = hs.config.experimental.msc2858_enabled self._msc2858_enabled = hs.config.experimental.msc2858_enabled
self._public_baseurl = hs.config.public_baseurl self._public_baseurl = hs.config.public_baseurl
@ -598,3 +599,19 @@ def register_servlets(hs, http_server):
SsoRedirectServlet(hs).register(http_server) SsoRedirectServlet(hs).register(http_server)
if hs.config.cas_enabled: if hs.config.cas_enabled:
CasTicketServlet(hs).register(http_server) CasTicketServlet(hs).register(http_server)
def _load_sso_handlers(hs: "HomeServer"):
"""Ensure that the SSO handlers are loaded, if they are enabled by configuration.
This is mostly useful to ensure that the CAS/SAML/OIDC handlers register themselves
with the main SsoHandler.
It's safe to call this multiple times.
"""
if hs.config.cas.cas_enabled:
hs.get_cas_handler()
if hs.config.saml2.saml2_enabled:
hs.get_saml_handler()
if hs.config.oidc.oidc_enabled:
hs.get_oidc_handler()