Skip to content

Commit 76033bd

Browse files
committed
chore: add type hinting to tornado instrumentation
Signed-off-by: Cagri Yonca <[email protected]>
1 parent 5c46281 commit 76033bd

File tree

2 files changed

+78
-42
lines changed

2 files changed

+78
-42
lines changed

src/instana/instrumentation/tornado/client.py

Lines changed: 26 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,41 @@
1-
# (c) Copyright IBM Corp. 2021
2-
# (c) Copyright Instana Inc. 2019
1+
# (c) Copyright IBM Corp. 2021, 2025
2+
33

44
try:
55
import tornado
66

77
import wrapt
88
import functools
9-
from typing import TYPE_CHECKING, Dict, Any
9+
from typing import TYPE_CHECKING, Dict, Any, Callable, Tuple
10+
11+
if TYPE_CHECKING:
12+
from instana.span.span import InstanaSpan
13+
from asyncio import Future
14+
from tornado.httpclient import AsyncHTTPClient
1015

1116
from opentelemetry.semconv.trace import SpanAttributes
1217

1318
from instana.log import logger
14-
from instana.singletons import agent, tracer
19+
from instana.singletons import agent, get_tracer
1520
from instana.util.secrets import strip_secrets_from_query
1621
from instana.util.traceutils import extract_custom_headers
1722
from instana.propagators.format import Format
1823
from instana.span.span import get_current_span
1924

20-
21-
@wrapt.patch_function_wrapper('tornado.httpclient', 'AsyncHTTPClient.fetch')
22-
def fetch_with_instana(wrapped, instance, argv, kwargs):
25+
@wrapt.patch_function_wrapper("tornado.httpclient", "AsyncHTTPClient.fetch")
26+
def fetch_with_instana(
27+
wrapped: Callable[..., object],
28+
instance: "AsyncHTTPClient",
29+
argv: Tuple[object, ...],
30+
kwargs: Dict[str, Any],
31+
) -> "Future":
2332
try:
2433
parent_span = get_current_span()
2534

2635
# If we're not tracing, just return
27-
if (not parent_span.is_recording()) or (parent_span.name == "tornado-client"):
36+
if (not parent_span.is_recording()) or (
37+
parent_span.name == "tornado-client"
38+
):
2839
return wrapped(*argv, **kwargs)
2940

3041
request = argv[0]
@@ -35,25 +46,26 @@ def fetch_with_instana(wrapped, instance, argv, kwargs):
3546
request = tornado.httpclient.HTTPRequest(url=request, **kwargs)
3647

3748
new_kwargs = {}
38-
for param in ('callback', 'raise_error'):
49+
for param in ("callback", "raise_error"):
3950
# if not in instead and pop
4051
if param in kwargs:
4152
new_kwargs[param] = kwargs.pop(param)
4253
kwargs = new_kwargs
4354

4455
parent_context = parent_span.get_span_context() if parent_span else None
45-
56+
tracer = get_tracer()
4657
span = tracer.start_span("tornado-client", span_context=parent_context)
4758

4859
extract_custom_headers(span, request.headers)
4960

5061
tracer.inject(span.context, Format.HTTP_HEADERS, request.headers)
5162

5263
# Query param scrubbing
53-
parts = request.url.split('?')
64+
parts = request.url.split("?")
5465
if len(parts) > 1:
55-
cleaned_qp = strip_secrets_from_query(parts[1], agent.options.secrets_matcher,
56-
agent.options.secrets_list)
66+
cleaned_qp = strip_secrets_from_query(
67+
parts[1], agent.options.secrets_matcher, agent.options.secrets_list
68+
)
5769
span.set_attribute("http.params", cleaned_qp)
5870

5971
span.set_attribute(SpanAttributes.HTTP_URL, parts[0])
@@ -69,8 +81,7 @@ def fetch_with_instana(wrapped, instance, argv, kwargs):
6981
except Exception:
7082
logger.debug("Tornado fetch_with_instana: ", exc_info=True)
7183

72-
73-
def finish_tracing(future, span):
84+
def finish_tracing(future: "Future", span: "InstanaSpan") -> None:
7485
try:
7586
response = future.result()
7687
span.set_attribute(SpanAttributes.HTTP_STATUS_CODE, response.code)
@@ -84,7 +95,6 @@ def finish_tracing(future, span):
8495
if span.is_recording():
8596
span.end()
8697

87-
8898
logger.debug("Instrumenting tornado client")
8999
except ImportError:
90100
pass

src/instana/instrumentation/tornado/server.py

Lines changed: 52 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,52 @@
1-
# (c) Copyright IBM Corp. 2021
2-
# (c) Copyright Instana Inc. 2019
1+
# (c) Copyright IBM Corp. 2021, 2025
32

43

54
try:
65
import tornado
6+
from typing import TYPE_CHECKING, Callable, Tuple, Dict, Any, Coroutine, Optional
77

88
import wrapt
99

10+
if TYPE_CHECKING:
11+
from tornado.web import RequestHandler
12+
1013
from opentelemetry.semconv.trace import SpanAttributes
1114

1215
from instana.log import logger
13-
from instana.singletons import agent, tracer
16+
from instana.singletons import agent, get_tracer
1417
from instana.util.secrets import strip_secrets_from_query
1518
from instana.util.traceutils import extract_custom_headers
1619
from instana.propagators.format import Format
1720

18-
19-
20-
@wrapt.patch_function_wrapper('tornado.web', 'RequestHandler._execute')
21-
def execute_with_instana(wrapped, instance, argv, kwargs):
21+
@wrapt.patch_function_wrapper("tornado.web", "RequestHandler._execute")
22+
def execute_with_instana(
23+
wrapped: Callable[..., object],
24+
instance: "RequestHandler",
25+
argv: Tuple[object, ...],
26+
kwargs: Dict[str, Any],
27+
) -> Coroutine:
2228
try:
2329
span_context = None
24-
if hasattr(instance.request.headers, '__dict__') and '_dict' in instance.request.headers.__dict__:
25-
span_context = tracer.extract(Format.HTTP_HEADERS,
26-
instance.request.headers.__dict__['_dict'])
30+
tracer = get_tracer()
31+
if (
32+
hasattr(instance.request.headers, "__dict__")
33+
and "_dict" in instance.request.headers.__dict__
34+
):
35+
span_context = tracer.extract(
36+
Format.HTTP_HEADERS, instance.request.headers.__dict__["_dict"]
37+
)
2738

2839
span = tracer.start_span("tornado-server", span_context=span_context)
2940

3041
# Query param scrubbing
3142
if instance.request.query is not None and len(instance.request.query) > 0:
32-
cleaned_qp = strip_secrets_from_query(instance.request.query, agent.options.secrets_matcher,
33-
agent.options.secrets_list)
43+
cleaned_qp = strip_secrets_from_query(
44+
instance.request.query,
45+
agent.options.secrets_matcher,
46+
agent.options.secrets_list,
47+
)
3448
span.set_attribute("http.params", cleaned_qp)
35-
49+
3650
url = f"{instance.request.protocol}://{instance.request.host}{instance.request.path}"
3751
span.set_attribute(SpanAttributes.HTTP_URL, url)
3852
span.set_attribute(SpanAttributes.HTTP_METHOD, instance.request.method)
@@ -52,20 +66,29 @@ def execute_with_instana(wrapped, instance, argv, kwargs):
5266
except Exception:
5367
logger.debug("tornado execute", exc_info=True)
5468

55-
56-
@wrapt.patch_function_wrapper('tornado.web', 'RequestHandler.set_default_headers')
57-
def set_default_headers_with_instana(wrapped, instance, argv, kwargs):
58-
if not hasattr(instance.request, '_instana'):
69+
@wrapt.patch_function_wrapper("tornado.web", "RequestHandler.set_default_headers")
70+
def set_default_headers_with_instana(
71+
wrapped: Callable[..., object],
72+
instance: "RequestHandler",
73+
argv: Tuple[object, ...],
74+
kwargs: Dict[str, Any],
75+
) -> Optional[Coroutine]:
76+
if not hasattr(instance.request, "_instana"):
5977
return wrapped(*argv, **kwargs)
6078

6179
span = instance.request._instana
80+
tracer = get_tracer()
6281
tracer.inject(span.context, Format.HTTP_HEADERS, instance._headers)
6382

64-
65-
@wrapt.patch_function_wrapper('tornado.web', 'RequestHandler.on_finish')
66-
def on_finish_with_instana(wrapped, instance, argv, kwargs):
83+
@wrapt.patch_function_wrapper("tornado.web", "RequestHandler.on_finish")
84+
def on_finish_with_instana(
85+
wrapped: Callable[..., object],
86+
instance: "RequestHandler",
87+
argv: Tuple[object, ...],
88+
kwargs: Dict[str, Any],
89+
) -> Coroutine:
6790
try:
68-
if not hasattr(instance.request, '_instana'):
91+
if not hasattr(instance.request, "_instana"):
6992
return wrapped(*argv, **kwargs)
7093

7194
span = instance.request._instana
@@ -86,11 +109,15 @@ def on_finish_with_instana(wrapped, instance, argv, kwargs):
86109
except Exception:
87110
logger.debug("tornado on_finish", exc_info=True)
88111

89-
90-
@wrapt.patch_function_wrapper('tornado.web', 'RequestHandler.log_exception')
91-
def log_exception_with_instana(wrapped, instance, argv, kwargs):
112+
@wrapt.patch_function_wrapper("tornado.web", "RequestHandler.log_exception")
113+
def log_exception_with_instana(
114+
wrapped: Callable[..., object],
115+
instance: "RequestHandler",
116+
argv: Tuple[object, ...],
117+
kwargs: Dict[str, Any],
118+
) -> Coroutine:
92119
try:
93-
if not hasattr(instance.request, '_instana'):
120+
if not hasattr(instance.request, "_instana"):
94121
return wrapped(*argv, **kwargs)
95122

96123
if not isinstance(argv[1], tornado.web.HTTPError):
@@ -101,7 +128,6 @@ def log_exception_with_instana(wrapped, instance, argv, kwargs):
101128
except Exception:
102129
logger.debug("tornado log_exception", exc_info=True)
103130

104-
105131
logger.debug("Instrumenting tornado server")
106132
except ImportError:
107133
pass

0 commit comments

Comments
 (0)