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

Commit 0a70837

Browse files
author
David Robertson
committed
Additional typing in synapse.util.metrics
Didn't get this to pass `no-untyped-def`, think I'll need to watch #10847
1 parent f3ad101 commit 0a70837

File tree

1 file changed

+24
-11
lines changed

1 file changed

+24
-11
lines changed

synapse/util/metrics.py

+24-11
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@
1414

1515
import logging
1616
from functools import wraps
17-
from typing import Any, Callable, Optional, TypeVar, cast
17+
from types import TracebackType
18+
from typing import Any, Callable, Optional, Protocol, Type, TypeVar, cast
1819

1920
from prometheus_client import Counter
2021

@@ -24,6 +25,7 @@
2425
current_context,
2526
)
2627
from synapse.metrics import InFlightGauge
28+
from synapse.util import Clock
2729

2830
logger = logging.getLogger(__name__)
2931

@@ -61,10 +63,15 @@
6163
sub_metrics=["real_time_max", "real_time_sum"],
6264
)
6365

64-
T = TypeVar("T", bound=Callable[..., Any])
66+
R = TypeVar("R")
67+
F = Callable[..., R]
6568

6669

67-
def measure_func(name: Optional[str] = None) -> Callable[[T], T]:
70+
class HasClock(Protocol):
71+
clock: Clock
72+
73+
74+
def measure_func(name: Optional[str] = None) -> Callable[[F], F]:
6875
"""
6976
Used to decorate an async function with a `Measure` context manager.
7077
@@ -82,16 +89,16 @@ async def foo(...):
8289
8390
"""
8491

85-
def wrapper(func: T) -> T:
92+
def wrapper(func: F) -> F:
8693
block_name = func.__name__ if name is None else name
8794

8895
@wraps(func)
89-
async def measured_func(self, *args, **kwargs):
96+
async def measured_func(self: HasClock, *args: Any, **kwargs: Any) -> R:
9097
with Measure(self.clock, block_name):
9198
r = await func(self, *args, **kwargs)
9299
return r
93100

94-
return cast(T, measured_func)
101+
return cast(F, measured_func)
95102

96103
return wrapper
97104

@@ -104,10 +111,10 @@ class Measure:
104111
"start",
105112
]
106113

107-
def __init__(self, clock, name: str):
114+
def __init__(self, clock: Clock, name: str) -> None:
108115
"""
109116
Args:
110-
clock: A n object with a "time()" method, which returns the current
117+
clock: An object with a "time()" method, which returns the current
111118
time in seconds.
112119
name: The name of the metric to report.
113120
"""
@@ -124,7 +131,7 @@ def __init__(self, clock, name: str):
124131
assert isinstance(curr_context, LoggingContext)
125132
parent_context = curr_context
126133
self._logging_context = LoggingContext(str(curr_context), parent_context)
127-
self.start: Optional[int] = None
134+
self.start: Optional[float] = None
128135

129136
def __enter__(self) -> "Measure":
130137
if self.start is not None:
@@ -138,7 +145,12 @@ def __enter__(self) -> "Measure":
138145

139146
return self
140147

141-
def __exit__(self, exc_type, exc_val, exc_tb):
148+
def __exit__(
149+
self,
150+
exc_type: Optional[Type[BaseException]],
151+
exc_val: Optional[BaseException],
152+
exc_tb: Optional[TracebackType],
153+
) -> None:
142154
if self.start is None:
143155
raise RuntimeError("Measure() block exited without being entered")
144156

@@ -168,8 +180,9 @@ def get_resource_usage(self) -> ContextResourceUsage:
168180
"""
169181
return self._logging_context.get_resource_usage()
170182

171-
def _update_in_flight(self, metrics):
183+
def _update_in_flight(self, metrics) -> None:
172184
"""Gets called when processing in flight metrics"""
185+
assert self.start is not None
173186
duration = self.clock.time() - self.start
174187

175188
metrics.real_time_max = max(metrics.real_time_max, duration)

0 commit comments

Comments
 (0)