Skip to content

Commit 7fb531d

Browse files
committed
2 parents eb9f9e0 + 2ee2cf3 commit 7fb531d

File tree

59 files changed

+362
-211
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

59 files changed

+362
-211
lines changed

CHANGELOG.md

+8
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1212
([#545](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/545))
1313
- `openelemetry-sdk-extension-aws` Take a dependency on `opentelemetry-sdk`
1414
([#558](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/558))
15+
1516
### Changed
1617
- `opentelemetry-instrumentation-tornado` properly instrument work done in tornado on_finish method.
1718
([#499](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/499))
@@ -24,10 +25,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
2425
([#538](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/538))
2526
- Changed the psycopg2-binary to psycopg2 as dependency in production
2627
([#543](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/543))
28+
- Implement consistent way of checking if instrumentation is already active
29+
([#549](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/549))
2730
- Require aiopg to be less than 1.3.0
2831
([#560](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/560))
2932
- `opentelemetry-instrumentation-django` Migrated Django middleware to new-style.
3033
([#533](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/533))
34+
- Updating dependency for opentelemetry api/sdk packages to support major version instead
35+
of pinning to specific versions.
36+
([#567](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/567))
37+
- `opentelemetry-instrumentation-grpc` Fixed asynchonous unary call traces
38+
([#536](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/536))
3139

3240
### Added
3341
- `opentelemetry-instrumentation-httpx` Add `httpx` instrumentation

_template/setup.cfg

+1-1
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ package_dir=
4545
packages=find_namespace:
4646

4747
install_requires =
48-
opentelemetry-api == 1.4.0.dev0
48+
opentelemetry-api ~= 1.3
4949

5050
[options.extras_require]
5151
test =

exporter/opentelemetry-exporter-datadog/setup.cfg

+2-2
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,8 @@ package_dir=
3939
packages=find_namespace:
4040
install_requires =
4141
ddtrace>=0.34.0,<0.47.0
42-
opentelemetry-api == 1.4.0.dev0
43-
opentelemetry-sdk == 1.4.0.dev0
42+
opentelemetry-api ~= 1.3
43+
opentelemetry-sdk ~= 1.3
4444
opentelemetry-semantic-conventions == 0.23.dev0
4545

4646
[options.packages.find]

instrumentation/opentelemetry-instrumentation-aiohttp-client/setup.cfg

+1-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ package_dir=
3838
=src
3939
packages=find_namespace:
4040
install_requires =
41-
opentelemetry-api == 1.4.0.dev0
41+
opentelemetry-api ~= 1.3
4242
opentelemetry-semantic-conventions == 0.23.dev0
4343
opentelemetry-instrumentation == 0.23.dev0
4444
opentelemetry-util-http == 0.23.dev0

instrumentation/opentelemetry-instrumentation-aiohttp-client/src/opentelemetry/instrumentation/aiohttp_client/__init__.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,7 @@ def instrumented_init(wrapped, instance, args, kwargs):
259259
span_name=span_name,
260260
tracer_provider=tracer_provider,
261261
)
262-
trace_config.opentelemetry_aiohttp_instrumented = True
262+
trace_config._is_instrumented_by_opentelemetry = True
263263
trace_configs.append(trace_config)
264264

265265
kwargs["trace_configs"] = trace_configs
@@ -282,7 +282,7 @@ def _uninstrument_session(client_session: aiohttp.ClientSession):
282282
client_session._trace_configs = [
283283
trace_config
284284
for trace_config in trace_configs
285-
if not hasattr(trace_config, "opentelemetry_aiohttp_instrumented")
285+
if not hasattr(trace_config, "_is_instrumented_by_opentelemetry")
286286
]
287287

288288

instrumentation/opentelemetry-instrumentation-aiopg/setup.cfg

+1-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ package_dir=
3838
=src
3939
packages=find_namespace:
4040
install_requires =
41-
opentelemetry-api == 1.4.0.dev0
41+
opentelemetry-api ~= 1.3
4242
opentelemetry-semantic-conventions == 0.23.dev0
4343
opentelemetry-instrumentation-dbapi == 0.23.dev0
4444
opentelemetry-instrumentation == 0.23.dev0

instrumentation/opentelemetry-instrumentation-aiopg/src/opentelemetry/instrumentation/aiopg/aiopg_integration.py

+2-7
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
11
import typing
22

33
import wrapt
4-
from aiopg.utils import ( # pylint: disable=no-name-in-module
5-
_ContextManager,
6-
_PoolAcquireContextManager,
7-
)
4+
from aiopg.utils import _ContextManager, _PoolAcquireContextManager
85

96
from opentelemetry.instrumentation.dbapi import (
107
CursorTracer,
@@ -64,9 +61,7 @@ def __init__(self, connection, *args, **kwargs):
6461

6562
def cursor(self, *args, **kwargs):
6663
coro = self._cursor(*args, **kwargs)
67-
return _ContextManager( # pylint: disable=no-value-for-parameter
68-
coro
69-
)
64+
return _ContextManager(coro)
7065

7166
async def _cursor(self, *args, **kwargs):
7267
# pylint: disable=protected-access

instrumentation/opentelemetry-instrumentation-aiopg/src/opentelemetry/instrumentation/aiopg/wrappers.py

+6-1
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141

4242
from opentelemetry.instrumentation.aiopg.aiopg_integration import (
4343
AiopgIntegration,
44+
AsyncProxyObject,
4445
get_traced_connection_proxy,
4546
)
4647
from opentelemetry.instrumentation.aiopg.version import __version__
@@ -153,6 +154,10 @@ def instrument_connection(
153154
Returns:
154155
An instrumented connection.
155156
"""
157+
if isinstance(connection, AsyncProxyObject):
158+
logger.warning("Connection already instrumented")
159+
return connection
160+
156161
db_integration = AiopgIntegration(
157162
name,
158163
database_system,
@@ -173,7 +178,7 @@ def uninstrument_connection(connection):
173178
Returns:
174179
An uninstrumented connection.
175180
"""
176-
if isinstance(connection, wrapt.ObjectProxy):
181+
if isinstance(connection, AsyncProxyObject):
177182
return connection.__wrapped__
178183

179184
logger.warning("Connection is not instrumented")

instrumentation/opentelemetry-instrumentation-aiopg/tests/test_aiopg_integration.py

+17
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,23 @@ def test_instrument_connection(self):
207207
spans_list = self.memory_exporter.get_finished_spans()
208208
self.assertEqual(len(spans_list), 1)
209209

210+
def test_instrument_connection_after_instrument(self):
211+
cnx = async_call(aiopg.connect(database="test"))
212+
query = "SELECT * FROM test"
213+
cursor = async_call(cnx.cursor())
214+
async_call(cursor.execute(query))
215+
216+
spans_list = self.memory_exporter.get_finished_spans()
217+
self.assertEqual(len(spans_list), 0)
218+
219+
AiopgInstrumentor().instrument()
220+
cnx = AiopgInstrumentor().instrument_connection(cnx)
221+
cursor = async_call(cnx.cursor())
222+
async_call(cursor.execute(query))
223+
224+
spans_list = self.memory_exporter.get_finished_spans()
225+
self.assertEqual(len(spans_list), 1)
226+
210227
def test_custom_tracer_provider_instrument_connection(self):
211228
resource = resources.Resource.create(
212229
{"service.name": "db-test-service"}

instrumentation/opentelemetry-instrumentation-asgi/setup.cfg

+1-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ package_dir=
3838
=src
3939
packages=find_namespace:
4040
install_requires =
41-
opentelemetry-api == 1.4.0.dev0
41+
opentelemetry-api ~= 1.3
4242
opentelemetry-semantic-conventions == 0.23.dev0
4343
opentelemetry-instrumentation == 0.23.dev0
4444
opentelemetry-util-http == 0.23.dev0

instrumentation/opentelemetry-instrumentation-asyncpg/setup.cfg

+1-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ package_dir=
3838
=src
3939
packages=find_namespace:
4040
install_requires =
41-
opentelemetry-api == 1.4.0.dev0
41+
opentelemetry-api ~= 1.3
4242
opentelemetry-semantic-conventions == 0.23.dev0
4343
opentelemetry-instrumentation == 0.23.dev0
4444

instrumentation/opentelemetry-instrumentation-boto/setup.cfg

+1-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ package_dir=
3838
=src
3939
packages=find_namespace:
4040
install_requires =
41-
opentelemetry-api == 1.4.0.dev0
41+
opentelemetry-api ~= 1.3
4242
opentelemetry-semantic-conventions == 0.23.dev0
4343
opentelemetry-instrumentation == 0.23.dev0
4444
opentelemetry-instrumentation-botocore == 0.23.dev0

instrumentation/opentelemetry-instrumentation-botocore/setup.cfg

+1-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ package_dir=
3838
=src
3939
packages=find_namespace:
4040
install_requires =
41-
opentelemetry-api == 1.4.0.dev0
41+
opentelemetry-api ~= 1.3
4242
opentelemetry-semantic-conventions == 0.23.dev0
4343
opentelemetry-instrumentation == 0.23.dev0
4444

instrumentation/opentelemetry-instrumentation-celery/setup.cfg

+1-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ package_dir=
3838
=src
3939
packages=find_namespace:
4040
install_requires =
41-
opentelemetry-api == 1.4.0.dev0
41+
opentelemetry-api ~= 1.3
4242
opentelemetry-semantic-conventions == 0.23.dev0
4343
opentelemetry-instrumentation == 0.23.dev0
4444

instrumentation/opentelemetry-instrumentation-dbapi/setup.cfg

+1-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ package_dir=
3838
=src
3939
packages=find_namespace:
4040
install_requires =
41-
opentelemetry-api == 1.4.0.dev0
41+
opentelemetry-api ~= 1.3
4242
opentelemetry-semantic-conventions == 0.23.dev0
4343
opentelemetry-instrumentation == 0.23.dev0
4444
wrapt >= 1.0.0, < 2.0.0

instrumentation/opentelemetry-instrumentation-dbapi/src/opentelemetry/instrumentation/dbapi/__init__.py

+4
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,10 @@ def instrument_connection(
180180
Returns:
181181
An instrumented connection.
182182
"""
183+
if isinstance(connection, wrapt.ObjectProxy):
184+
logger.warning("Connection already instrumented")
185+
return connection
186+
183187
db_integration = DatabaseApiIntegration(
184188
name,
185189
database_system,

instrumentation/opentelemetry-instrumentation-django/setup.cfg

+1-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ install_requires =
4141
opentelemetry-util-http == 0.23.dev0
4242
opentelemetry-instrumentation-wsgi == 0.23.dev0
4343
opentelemetry-instrumentation == 0.23.dev0
44-
opentelemetry-api == 1.4.0.dev0
44+
opentelemetry-api ~= 1.3
4545
opentelemetry-semantic-conventions == 0.23.dev0
4646

4747
[options.extras_require]

instrumentation/opentelemetry-instrumentation-elasticsearch/setup.cfg

+1-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ package_dir=
3838
=src
3939
packages=find_namespace:
4040
install_requires =
41-
opentelemetry-api == 1.4.0.dev0
41+
opentelemetry-api ~= 1.3
4242
opentelemetry-semantic-conventions == 0.23.dev0
4343
opentelemetry-instrumentation == 0.23.dev0
4444
wrapt >= 1.0.0, < 2.0.0

instrumentation/opentelemetry-instrumentation-falcon/setup.cfg

+1-1
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ install_requires =
4242
opentelemetry-instrumentation-wsgi == 0.23.dev0
4343
opentelemetry-util-http == 0.23.dev0
4444
opentelemetry-instrumentation == 0.23.dev0
45-
opentelemetry-api == 1.4.0.dev0
45+
opentelemetry-api ~= 1.3
4646
opentelemetry-semantic-conventions == 0.23.dev0
4747

4848
[options.extras_require]

instrumentation/opentelemetry-instrumentation-fastapi/setup.cfg

+1-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ package_dir=
3838
=src
3939
packages=find_namespace:
4040
install_requires =
41-
opentelemetry-api == 1.4.0.dev0
41+
opentelemetry-api ~= 1.3
4242
opentelemetry-semantic-conventions == 0.23.dev0
4343
opentelemetry-instrumentation == 0.23.dev0
4444
opentelemetry-instrumentation-asgi == 0.23.dev0

instrumentation/opentelemetry-instrumentation-fastapi/src/opentelemetry/instrumentation/fastapi/__init__.py

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

15+
import logging
1516
from typing import Collection
1617

1718
import fastapi
19+
from starlette import middleware
1820
from starlette.routing import Match
1921

2022
from opentelemetry.instrumentation.asgi import OpenTelemetryMiddleware
@@ -24,6 +26,7 @@
2426
from opentelemetry.util.http import get_excluded_urls, parse_excluded_urls
2527

2628
_excluded_urls_from_env = get_excluded_urls("FASTAPI")
29+
_logger = logging.getLogger(__name__)
2730

2831

2932
class FastAPIInstrumentor(BaseInstrumentor):
@@ -39,7 +42,10 @@ def instrument_app(
3942
app: fastapi.FastAPI, tracer_provider=None, excluded_urls=None,
4043
):
4144
"""Instrument an uninstrumented FastAPI application."""
42-
if not getattr(app, "is_instrumented_by_opentelemetry", False):
45+
if not hasattr(app, "_is_instrumented_by_opentelemetry"):
46+
app._is_instrumented_by_opentelemetry = False
47+
48+
if not getattr(app, "_is_instrumented_by_opentelemetry", False):
4349
if excluded_urls is None:
4450
excluded_urls = _excluded_urls_from_env
4551
else:
@@ -51,7 +57,21 @@ def instrument_app(
5157
span_details_callback=_get_route_details,
5258
tracer_provider=tracer_provider,
5359
)
54-
app.is_instrumented_by_opentelemetry = True
60+
app._is_instrumented_by_opentelemetry = True
61+
else:
62+
_logger.warning(
63+
"Attempting to instrument FastAPI app while already instrumented"
64+
)
65+
66+
@staticmethod
67+
def uninstrument_app(app: fastapi.FastAPI):
68+
app.user_middleware = [
69+
x
70+
for x in app.user_middleware
71+
if x.cls is not OpenTelemetryMiddleware
72+
]
73+
app.middleware_stack = app.build_middleware_stack()
74+
app._is_instrumented_by_opentelemetry = False
5575

5676
def instrumentation_dependencies(self) -> Collection[str]:
5777
return _instruments

instrumentation/opentelemetry-instrumentation-fastapi/tests/test_fastapi_instrumentation.py

+42
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
from fastapi.testclient import TestClient
2020

2121
import opentelemetry.instrumentation.fastapi as otel_fastapi
22+
from opentelemetry.instrumentation.asgi import OpenTelemetryMiddleware
2223
from opentelemetry.sdk.resources import Resource
2324
from opentelemetry.semconv.trace import SpanAttributes
2425
from opentelemetry.test.test_base import TestBase
@@ -57,6 +58,47 @@ def tearDown(self):
5758
super().tearDown()
5859
self.env_patch.stop()
5960
self.exclude_patch.stop()
61+
with self.disable_logging():
62+
self._instrumentor.uninstrument()
63+
self._instrumentor.uninstrument_app(self._app)
64+
65+
def test_instrument_app_with_instrument(self):
66+
if not isinstance(self, TestAutoInstrumentation):
67+
self._instrumentor.instrument()
68+
self._client.get("/foobar")
69+
spans = self.memory_exporter.get_finished_spans()
70+
self.assertEqual(len(spans), 3)
71+
for span in spans:
72+
self.assertIn("/foobar", span.name)
73+
74+
def test_uninstrument_app(self):
75+
self._client.get("/foobar")
76+
spans = self.memory_exporter.get_finished_spans()
77+
self.assertEqual(len(spans), 3)
78+
# pylint: disable=import-outside-toplevel
79+
from fastapi.middleware.httpsredirect import HTTPSRedirectMiddleware
80+
81+
self._app.add_middleware(HTTPSRedirectMiddleware)
82+
self._instrumentor.uninstrument_app(self._app)
83+
print(self._app.user_middleware[0].cls)
84+
self.assertFalse(
85+
isinstance(
86+
self._app.user_middleware[0].cls, OpenTelemetryMiddleware
87+
)
88+
)
89+
self._client = TestClient(self._app)
90+
resp = self._client.get("/foobar")
91+
self.assertEqual(200, resp.status_code)
92+
span_list = self.memory_exporter.get_finished_spans()
93+
self.assertEqual(len(span_list), 3)
94+
95+
def test_uninstrument_app_after_instrument(self):
96+
if not isinstance(self, TestAutoInstrumentation):
97+
self._instrumentor.instrument()
98+
self._instrumentor.uninstrument_app(self._app)
99+
self._client.get("/foobar")
100+
spans = self.memory_exporter.get_finished_spans()
101+
self.assertEqual(len(spans), 0)
60102

61103
def test_basic_fastapi_call(self):
62104
self._client.get("/foobar")

instrumentation/opentelemetry-instrumentation-flask/setup.cfg

+1-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ install_requires =
4141
opentelemetry-util-http == 0.23.dev0
4242
opentelemetry-instrumentation == 0.23.dev0
4343
opentelemetry-instrumentation-wsgi == 0.23.dev0
44-
opentelemetry-api == 1.4.0.dev0
44+
opentelemetry-api ~= 1.3
4545
opentelemetry-semantic-conventions == 0.23.dev0
4646

4747
[options.extras_require]

0 commit comments

Comments
 (0)