Skip to content

Commit 9598863

Browse files
committed
chore: add type hinting to tornado instrumentation
Signed-off-by: Cagri Yonca <[email protected]>
1 parent 42796b2 commit 9598863

File tree

2 files changed

+77
-40
lines changed

2 files changed

+77
-40
lines changed

src/instana/instrumentation/tornado/client.py

Lines changed: 25 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,41 @@
1-
# (c) Copyright IBM Corp. 2021
1+
# (c) Copyright IBM Corp. 2025
22
# (c) Copyright Instana Inc. 2019
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 & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,53 @@
1-
# (c) Copyright IBM Corp. 2021
1+
# (c) Copyright IBM Corp. 2025
22
# (c) Copyright Instana Inc. 2019
33

44

55
try:
66
import tornado
7+
from typing import TYPE_CHECKING, Callable, Tuple, Dict, Any, Coroutine, Optional
78

89
import wrapt
910

11+
if TYPE_CHECKING:
12+
from tornado.web import RequestHandler
13+
1014
from opentelemetry.semconv.trace import SpanAttributes
1115

1216
from instana.log import logger
13-
from instana.singletons import agent, tracer
17+
from instana.singletons import agent, get_tracer
1418
from instana.util.secrets import strip_secrets_from_query
1519
from instana.util.traceutils import extract_custom_headers
1620
from instana.propagators.format import Format
1721

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

2840
span = tracer.start_span("tornado-server", span_context=span_context)
2941

3042
# Query param scrubbing
3143
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)
44+
cleaned_qp = strip_secrets_from_query(
45+
instance.request.query,
46+
agent.options.secrets_matcher,
47+
agent.options.secrets_list,
48+
)
3449
span.set_attribute("http.params", cleaned_qp)
35-
50+
3651
url = f"{instance.request.protocol}://{instance.request.host}{instance.request.path}"
3752
span.set_attribute(SpanAttributes.HTTP_URL, url)
3853
span.set_attribute(SpanAttributes.HTTP_METHOD, instance.request.method)
@@ -52,20 +67,29 @@ def execute_with_instana(wrapped, instance, argv, kwargs):
5267
except Exception:
5368
logger.debug("tornado execute", exc_info=True)
5469

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'):
70+
@wrapt.patch_function_wrapper("tornado.web", "RequestHandler.set_default_headers")
71+
def set_default_headers_with_instana(
72+
wrapped: Callable[..., object],
73+
instance: "RequestHandler",
74+
argv: Tuple[object, ...],
75+
kwargs: Dict[str, Any],
76+
) -> Optional[Coroutine]:
77+
if not hasattr(instance.request, "_instana"):
5978
return wrapped(*argv, **kwargs)
6079

6180
span = instance.request._instana
81+
tracer = get_tracer()
6282
tracer.inject(span.context, Format.HTTP_HEADERS, instance._headers)
6383

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

7195
span = instance.request._instana
@@ -86,11 +110,15 @@ def on_finish_with_instana(wrapped, instance, argv, kwargs):
86110
except Exception:
87111
logger.debug("tornado on_finish", exc_info=True)
88112

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

96124
if not isinstance(argv[1], tornado.web.HTTPError):
@@ -101,7 +129,6 @@ def log_exception_with_instana(wrapped, instance, argv, kwargs):
101129
except Exception:
102130
logger.debug("tornado log_exception", exc_info=True)
103131

104-
105132
logger.debug("Instrumenting tornado server")
106133
except ImportError:
107134
pass

0 commit comments

Comments
 (0)