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

Commit

Permalink
Add metrics to track how the rate limiter is affecting requests
Browse files Browse the repository at this point in the history
  • Loading branch information
MadLittleMods committed Aug 16, 2022
1 parent 1b09b08 commit 325cadc
Showing 1 changed file with 13 additions and 2 deletions.
15 changes: 13 additions & 2 deletions synapse/util/ratelimitutils.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@

from twisted.internet import defer

from prometheus_client.core import Counter

from synapse.api.errors import LimitExceededError
from synapse.config.ratelimiting import FederationRatelimitSettings
from synapse.logging.context import (
Expand All @@ -35,6 +37,11 @@
logger = logging.getLogger(__name__)


rate_limit_sleep_counter = Counter("synapse_rate_limit_sleep", "", ["host"])

rate_limit_reject_counter = Counter("synapse_rate_limit_reject", "", ["host"])


class FederationRateLimiter:
def __init__(self, clock: Clock, config: FederationRatelimitSettings):
def new_limiter() -> "_PerHostRatelimiter":
Expand All @@ -59,7 +66,7 @@ def ratelimit(self, host: str) -> "_GeneratorContextManager[defer.Deferred[None]
Returns:
context manager which returns a deferred.
"""
return self.ratelimiters[host].ratelimit()
return self.ratelimiters[host].ratelimit(host)


class _PerHostRatelimiter:
Expand Down Expand Up @@ -94,12 +101,14 @@ def __init__(self, clock: Clock, config: FederationRatelimitSettings):
self.request_times: List[int] = []

@contextlib.contextmanager
def ratelimit(self) -> "Iterator[defer.Deferred[None]]":
def ratelimit(self, host: str) -> "Iterator[defer.Deferred[None]]":
# `contextlib.contextmanager` takes a generator and turns it into a
# context manager. The generator should only yield once with a value
# to be returned by manager.
# Exceptions will be reraised at the yield.

self.host = host

request_id = object()
ret = self._on_enter(request_id)
try:
Expand All @@ -119,6 +128,7 @@ def _on_enter(self, request_id: object) -> "defer.Deferred[None]":
# sleeping or in the ready queue).
queue_size = len(self.ready_request_queue) + len(self.sleeping_requests)
if queue_size > self.reject_limit:
rate_limit_reject_counter.labels(self.host).inc()
raise LimitExceededError(
retry_after_ms=int(self.window_size / self.sleep_limit)
)
Expand Down Expand Up @@ -146,6 +156,7 @@ def queue_request() -> "defer.Deferred[None]":

if len(self.request_times) > self.sleep_limit:
logger.debug("Ratelimiter: sleeping request for %f sec", self.sleep_sec)
rate_limit_sleep_counter.labels(self.host).inc()
ret_defer = run_in_background(self.clock.sleep, self.sleep_sec)

self.sleeping_requests.add(request_id)
Expand Down

0 comments on commit 325cadc

Please sign in to comment.