-
-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Add missing types to opentracing #13345
Changes from 5 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
Add type hints to `trace` decorator. | ||
Add missing type hints to open tracing module. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
Add missing type hints to open tracing module. |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -14,7 +14,7 @@ | |
# limitations under the License. | ||
|
||
import logging | ||
from typing import TYPE_CHECKING, Dict, Optional | ||
from typing import TYPE_CHECKING, Dict, Optional, cast | ||
|
||
from typing_extensions import Literal | ||
|
||
|
@@ -97,7 +97,7 @@ async def get_room_keys( | |
user_id, version, room_id, session_id | ||
) | ||
|
||
log_kv(results) | ||
log_kv(cast(JsonDict, results)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Bit of a shame we need the noise here. We could maybe change our (Fine as it is, I'm just lamenting in passing) |
||
return results | ||
|
||
@trace | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -182,6 +182,8 @@ def set_fates(clotho, lachesis, atropos, father="Zues", mother="Themis"): | |
Type, | ||
TypeVar, | ||
Union, | ||
cast, | ||
overload, | ||
) | ||
|
||
import attr | ||
|
@@ -328,6 +330,7 @@ class _Sentinel(enum.Enum): | |
|
||
P = ParamSpec("P") | ||
R = TypeVar("R") | ||
T = TypeVar("T") | ||
|
||
|
||
def only_if_tracing(func: Callable[P, R]) -> Callable[P, Optional[R]]: | ||
|
@@ -343,22 +346,43 @@ def _only_if_tracing_inner(*args: P.args, **kwargs: P.kwargs) -> Optional[R]: | |
return _only_if_tracing_inner | ||
|
||
|
||
def ensure_active_span(message: str, ret=None): | ||
@overload | ||
def ensure_active_span( | ||
message: str, | ||
) -> Callable[[Callable[P, R]], Callable[P, Optional[R]]]: | ||
... | ||
|
||
|
||
@overload | ||
def ensure_active_span( | ||
message: str, ret: T | ||
) -> Callable[[Callable[P, R]], Callable[P, Union[T, R]]]: | ||
... | ||
|
||
|
||
def ensure_active_span( | ||
message: str, ret: Optional[T] = None | ||
) -> Callable[[Callable[P, R]], Callable[P, Union[Optional[T], R]]]: | ||
"""Executes the operation only if opentracing is enabled and there is an active span. | ||
If there is no active span it logs message at the error level. | ||
|
||
Args: | ||
message: Message which fills in "There was no active span when trying to %s" | ||
in the error log if there is no active span and opentracing is enabled. | ||
ret (object): return value if opentracing is None or there is no active span. | ||
ret: return value if opentracing is None or there is no active span. | ||
|
||
Returns (object): The result of the func or ret if opentracing is disabled or there | ||
Returns: | ||
The result of the func, falling back to ret if opentracing is disabled or there | ||
was no active span. | ||
""" | ||
|
||
def ensure_active_span_inner_1(func): | ||
def ensure_active_span_inner_1( | ||
func: Callable[P, R] | ||
) -> Callable[P, Union[Optional[T], R]]: | ||
@wraps(func) | ||
def ensure_active_span_inner_2(*args, **kwargs): | ||
def ensure_active_span_inner_2( | ||
*args: P.args, **kwargs: P.kwargs | ||
) -> Union[Optional[T], R]: | ||
if not opentracing: | ||
return ret | ||
|
||
|
@@ -464,7 +488,7 @@ def start_active_span( | |
finish_on_close: bool = True, | ||
*, | ||
tracer: Optional["opentracing.Tracer"] = None, | ||
): | ||
) -> "opentracing.Scope": | ||
"""Starts an active opentracing span. | ||
|
||
Records the start time for the span, and sets it as the "active span" in the | ||
|
@@ -502,7 +526,7 @@ def start_active_span_follows_from( | |
*, | ||
inherit_force_tracing: bool = False, | ||
tracer: Optional["opentracing.Tracer"] = None, | ||
): | ||
) -> "opentracing.Scope": | ||
"""Starts an active opentracing span, with additional references to previous spans | ||
|
||
Args: | ||
|
@@ -717,7 +741,9 @@ def inject_response_headers(response_headers: Headers) -> None: | |
response_headers.addRawHeader("Synapse-Trace-Id", f"{trace_id:x}") | ||
|
||
|
||
@ensure_active_span("get the active span context as a dict", ret={}) | ||
@ensure_active_span( | ||
"get the active span context as a dict", ret=cast(Dict[str, str], {}) | ||
) | ||
def get_active_span_text_map(destination: Optional[str] = None) -> Dict[str, str]: | ||
""" | ||
Gets a span context as a dict. This can be used instead of manually | ||
|
@@ -886,7 +912,7 @@ def _tag_args_inner(*args: P.args, **kwargs: P.kwargs) -> R: | |
for i, arg in enumerate(argspec.args[1:]): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This isn't your change, but I don't really understand the offset of 1 here. I'm guessing that we want to ignore the first arg to a function call because that arg is a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't know, I was a bit confused by it too but decided not to touch it. |
||
set_tag("ARG_" + arg, args[i]) # type: ignore[index] | ||
set_tag("args", args[len(argspec.args) :]) # type: ignore[index] | ||
set_tag("kwargs", kwargs) | ||
set_tag("kwargs", str(kwargs)) | ||
return func(*args, **kwargs) | ||
|
||
return _tag_args_inner | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,6 +12,8 @@ | |
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
|
||
from typing import cast | ||
|
||
from twisted.internet import defer | ||
from twisted.test.proto_helpers import MemoryReactorClock | ||
|
||
|
@@ -40,6 +42,14 @@ | |
|
||
|
||
class LogContextScopeManagerTestCase(TestCase): | ||
""" | ||
Test logging contexts and active opentracing spans. | ||
|
||
There's casts throughout this from generic opentracing objects (e.g. | ||
opentracing.Span) to the ones specific to Jaeger since they have additional | ||
properties that these tests depend on. This is safe since the only supported | ||
opentracing backend is Jaeger. | ||
""" | ||
if LogContextScopeManager is None: | ||
skip = "Requires opentracing" # type: ignore[unreachable] | ||
if jaeger_client is None: | ||
|
@@ -69,7 +79,7 @@ def test_start_active_span(self) -> None: | |
|
||
# start_active_span should start and activate a span. | ||
scope = start_active_span("span", tracer=self._tracer) | ||
span = scope.span | ||
span = cast(jaeger_client.Span, scope.span) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In this file we reference a bunch of properties which are specific to jaeger's implementation of There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Before I saw your comment, I drafted:
Your explanation shows my guess wasn't correct. Might it be worth a quick comment? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hopefully edab4ec makes sense? |
||
self.assertEqual(self._tracer.active_span, span) | ||
self.assertIsNotNone(span.start_time) | ||
|
||
|
@@ -91,6 +101,7 @@ def test_nested_spans(self) -> None: | |
with LoggingContext("root context"): | ||
with start_active_span("root span", tracer=self._tracer) as root_scope: | ||
self.assertEqual(self._tracer.active_span, root_scope.span) | ||
root_context = cast(jaeger_client.SpanContext, root_scope.span.context) | ||
|
||
scope1 = start_active_span( | ||
"child1", | ||
|
@@ -99,27 +110,27 @@ def test_nested_spans(self) -> None: | |
self.assertEqual( | ||
self._tracer.active_span, scope1.span, "child1 was not activated" | ||
) | ||
self.assertEqual( | ||
scope1.span.context.parent_id, root_scope.span.context.span_id | ||
) | ||
context1 = cast(jaeger_client.SpanContext, scope1.span.context) | ||
self.assertEqual(context1.parent_id, root_context.span_id) | ||
|
||
scope2 = start_active_span_follows_from( | ||
"child2", | ||
contexts=(scope1,), | ||
tracer=self._tracer, | ||
) | ||
self.assertEqual(self._tracer.active_span, scope2.span) | ||
self.assertEqual( | ||
scope2.span.context.parent_id, scope1.span.context.span_id | ||
) | ||
context2 = cast(jaeger_client.SpanContext, scope2.span.context) | ||
self.assertEqual(context2.parent_id, context1.span_id) | ||
|
||
with scope1, scope2: | ||
pass | ||
|
||
# the root scope should be restored | ||
self.assertEqual(self._tracer.active_span, root_scope.span) | ||
self.assertIsNotNone(scope2.span.end_time) | ||
self.assertIsNotNone(scope1.span.end_time) | ||
span2 = cast(jaeger_client.Span, scope2.span) | ||
span1 = cast(jaeger_client.Span, scope1.span) | ||
self.assertIsNotNone(span2.end_time) | ||
self.assertIsNotNone(span1.end_time) | ||
|
||
self.assertIsNone(self._tracer.active_span) | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Jaeger automatically casts things to string, but according to the
opentracing
API these must be simple types.