Skip to content

Commit a45d617

Browse files
committed
Add tornado metrics test_metrics_concurrent_requests test
1 parent 1761813 commit a45d617

File tree

2 files changed

+84
-0
lines changed

2 files changed

+84
-0
lines changed

instrumentation/opentelemetry-instrumentation-tornado/tests/test_metrics_instrumentation.py

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,11 @@
1313
# limitations under the License.
1414

1515

16+
import asyncio
1617
from timeit import default_timer
1718

19+
import tornado.testing
20+
1821
from opentelemetry.instrumentation.tornado import TornadoInstrumentor
1922
from opentelemetry.sdk.metrics.export import HistogramDataPoint
2023

@@ -165,6 +168,78 @@ def test_basic_metrics(self):
165168
),
166169
)
167170

171+
@tornado.testing.gen_test
172+
async def test_metrics_concurrent_requests(self):
173+
"""
174+
Test that metrics can handle concurrent requests and calculate in an async-safe way.
175+
"""
176+
req1 = self.http_client.fetch(self.get_url("/slow?duration=1.0"))
177+
req2 = self.http_client.fetch(self.get_url("/async"))
178+
await asyncio.gather(req1, req2)
179+
180+
metrics = self.get_sorted_metrics()
181+
self.assertEqual(len(metrics), 7)
182+
183+
client_duration = metrics[0]
184+
server_duration = metrics[4]
185+
self.assertEqual(client_duration.name, "http.client.duration")
186+
self.assertEqual(server_duration.name, "http.server.duration")
187+
188+
# Calculating duration requires tracking state via `_HANDLER_STATE_KEY`, so we want to make sure
189+
# duration is calculated properly per request, and doesn't affect concurrent requests.
190+
req1_client_duration_data_point = next(
191+
dp
192+
for dp in client_duration.data.data_points
193+
if "/slow" in dp.attributes.get("http.url")
194+
)
195+
req1_server_duration_data_point = next(
196+
dp
197+
for dp in server_duration.data.data_points
198+
if "/slow" in dp.attributes.get("http.target")
199+
)
200+
req2_client_duration_data_point = next(
201+
dp
202+
for dp in client_duration.data.data_points
203+
if "/async" in dp.attributes.get("http.url")
204+
)
205+
req2_server_duration_data_point = next(
206+
dp
207+
for dp in server_duration.data.data_points
208+
if "/async" in dp.attributes.get("http.target")
209+
)
210+
211+
# Server and client durations should be similar (adjusting for msecs vs secs)
212+
self.assertAlmostEqual(
213+
abs(
214+
req1_server_duration_data_point.sum / 1000.0
215+
- req1_client_duration_data_point.sum
216+
),
217+
0.0,
218+
delta=0.01,
219+
)
220+
self.assertAlmostEqual(
221+
abs(
222+
req2_server_duration_data_point.sum / 1000.0
223+
- req2_client_duration_data_point.sum
224+
),
225+
0.0,
226+
delta=0.01,
227+
)
228+
229+
# Make sure duration is roughly equivalent to expected (req1/slow) should be around 1 second
230+
self.assertAlmostEqual(
231+
req1_server_duration_data_point.sum / 1000.0,
232+
1.0,
233+
delta=0.1,
234+
msg="Should have been about 1 second",
235+
)
236+
self.assertAlmostEqual(
237+
req2_server_duration_data_point.sum,
238+
0.0,
239+
delta=0.1,
240+
msg="Should have been really short",
241+
)
242+
168243
def test_metric_uninstrument(self):
169244
self.fetch("/")
170245
TornadoInstrumentor().uninstrument()

instrumentation/opentelemetry-instrumentation-tornado/tests/tornado_test_app.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
# pylint: disable=W0223,R0201
2+
import asyncio
23
import time
34

45
import tornado.web
@@ -106,6 +107,13 @@ def get(self):
106107
self.set_status(200)
107108

108109

110+
class SlowHandler(tornado.web.RequestHandler):
111+
async def get(self):
112+
with self.application.tracer.start_as_current_span("slow"):
113+
duration = float(self.get_argument("duration", "1.0"))
114+
await asyncio.sleep(duration)
115+
116+
109117
class RaiseHTTPErrorHandler(tornado.web.RequestHandler):
110118
def get(self):
111119
raise tornado.web.HTTPError(403)
@@ -133,6 +141,7 @@ def make_app(tracer):
133141
(r"/ping", HealthCheckHandler),
134142
(r"/test_custom_response_headers", CustomResponseHeaderHandler),
135143
(r"/raise_403", RaiseHTTPErrorHandler),
144+
(r"/slow", SlowHandler),
136145
(r"/echo_socket", EchoWebSocketHandler),
137146
]
138147
)

0 commit comments

Comments
 (0)