Skip to content

Commit 638c042

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

File tree

3 files changed

+88
-6
lines changed

3 files changed

+88
-6
lines changed

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

+23
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,25 @@ def _sqlcommenter_endpoint():
3437
)
3538
return sqlcommenter_flask_values
3639

40+
@staticmethod
41+
def _multithreaded_endpoint(count):
42+
def do_random_stuff():
43+
@flask.copy_current_request_context
44+
def inner():
45+
return randint(0, 100)
46+
47+
return inner
48+
49+
executor = ThreadPoolExecutor(count)
50+
futures = []
51+
for _ in range(count):
52+
futures.append(executor.submit(do_random_stuff()))
53+
numbers = []
54+
for future in as_completed(futures):
55+
numbers.append(future.result())
56+
57+
return " ".join([str(i) for i in numbers])
58+
3759
@staticmethod
3860
def _custom_response_headers():
3961
resp = flask.Response("test response")
@@ -61,6 +83,7 @@ def excluded2_endpoint():
6183
# pylint: disable=no-member
6284
self.app.route("/hello/<int:helloid>")(self._hello_endpoint)
6385
self.app.route("/sqlcommenter")(self._sqlcommenter_endpoint)
86+
self.app.route("/multithreaded")(self._multithreaded_endpoint)
6487
self.app.route("/excluded/<int:helloid>")(self._hello_endpoint)
6588
self.app.route("/excluded")(excluded_endpoint)
6689
self.app.route("/excluded2")(excluded2_endpoint)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
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>")(
45+
self._multithreaded_endpoint
46+
)
47+
client = Client(self.app, Response)
48+
count = 5
49+
resp = client.get(f"/multithreaded/{count}")
50+
self.assertEqual(200, resp.status_code)
51+
# Should return the specified number of random integers
52+
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)