Skip to content

Commit 4882ca4

Browse files
committed
Merge branch 'main' into fix-flask-multithread-context-bug
2 parents 631828a + ffbbb4d commit 4882ca4

File tree

3 files changed

+87
-6
lines changed

3 files changed

+87
-6
lines changed

instrumentation/opentelemetry-instrumentation-flask/tests/base_test.py

+24
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15+
from concurrent.futures import ThreadPoolExecutor, as_completed
16+
from random import randint
17+
1518
import flask
1619
from werkzeug.test import Client
1720
from werkzeug.wrappers import Response
@@ -34,6 +37,26 @@ def _sqlcommenter_endpoint():
3437
)
3538
return sqlcommenter_flask_values
3639

40+
41+
42+
@staticmethod
43+
def _multithreaded_endpoint(count):
44+
def do_random_stuff():
45+
@flask.copy_current_request_context
46+
def inner():
47+
return randint(0, 100)
48+
return inner
49+
50+
executor = ThreadPoolExecutor(count)
51+
futures = []
52+
for _ in range(count):
53+
futures.append(executor.submit(do_random_stuff()))
54+
numbers = []
55+
for future in as_completed(futures):
56+
numbers.append(future.result())
57+
58+
return ' '.join([str(i) for i in numbers])
59+
3760
@staticmethod
3861
def _custom_response_headers():
3962
resp = flask.Response("test response")
@@ -61,6 +84,7 @@ def excluded2_endpoint():
6184
# pylint: disable=no-member
6285
self.app.route("/hello/<int:helloid>")(self._hello_endpoint)
6386
self.app.route("/sqlcommenter")(self._sqlcommenter_endpoint)
87+
self.app.route("/multithreaded")(self._multithreaded_endpoint)
6488
self.app.route("/excluded/<int:helloid>")(self._hello_endpoint)
6589
self.app.route("/excluded")(excluded_endpoint)
6690
self.app.route("/excluded2")(excluded2_endpoint)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
# Copyright The OpenTelemetry Authors
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
import flask
16+
from werkzeug.test import Client
17+
from werkzeug.wrappers import Response
18+
19+
from opentelemetry.instrumentation.flask import FlaskInstrumentor
20+
from opentelemetry.test.wsgitestutil import WsgiTestBase
21+
22+
# pylint: disable=import-error
23+
from .base_test import InstrumentationTest
24+
25+
26+
class TestMultiThreading(InstrumentationTest, WsgiTestBase):
27+
def setUp(self):
28+
super().setUp()
29+
FlaskInstrumentor().instrument()
30+
self.app = flask.Flask(__name__)
31+
self._common_initialization()
32+
33+
def tearDown(self):
34+
super().tearDown()
35+
with self.disable_logging():
36+
FlaskInstrumentor().uninstrument()
37+
38+
def test_multithreaded(self):
39+
"""Test that instrumentation tear down does not blow up
40+
when the request thread spawn children threads and the request
41+
context is copied to the children threads
42+
"""
43+
self.app = flask.Flask(__name__)
44+
self.app.route("/multithreaded/<int:count>")(self._multithreaded_endpoint)
45+
client = Client(self.app, Response)
46+
count = 5
47+
resp = client.get(f"/multithreaded/{count}")
48+
self.assertEqual(200, resp.status_code)
49+
# Should return the specified number of random integers
50+
self.assertEqual(count, len(resp.text.split(' ')))

scripts/otel_packaging.py

+13-6
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
import os
1616
import subprocess
17+
from subprocess import CalledProcessError
1718

1819
import tomli
1920

@@ -28,12 +29,18 @@ def get_instrumentation_packages():
2829
if not os.path.isdir(pkg_path):
2930
continue
3031

31-
version = subprocess.check_output(
32-
"hatch version",
33-
shell=True,
34-
cwd=pkg_path,
35-
universal_newlines=True,
36-
)
32+
try:
33+
version = subprocess.check_output(
34+
"hatch version",
35+
shell=True,
36+
cwd=pkg_path,
37+
universal_newlines=True,
38+
)
39+
except CalledProcessError as exc:
40+
print(f"Could not get hatch version from path {pkg_path}")
41+
print(exc.output)
42+
raise exc
43+
3744
pyproject_toml_path = os.path.join(pkg_path, "pyproject.toml")
3845

3946
with open(pyproject_toml_path, "rb") as file:

0 commit comments

Comments
 (0)