diff --git a/.readthedocs.yml b/.readthedocs.yml index 2a3c920b45..dcf3204080 100644 --- a/.readthedocs.yml +++ b/.readthedocs.yml @@ -12,4 +12,4 @@ build: python: install: - - requirements: docs-requirements.txt + - requirements: rtd-requirements.txt diff --git a/CHANGELOG.md b/CHANGELOG.md index a23f7fe2d0..1aeccfb60c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -48,6 +48,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ([#3022](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3022)) - Replace all instrumentor unit test `assertEqualSpanInstrumentationInfo` calls with `assertEqualSpanInstrumentationScope` calls ([#3037](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3037)) +- `opentelemetry-instrumentation-sqlalchemy` Fixes engines from `sqlalchemy.engine_from_config` not being fully instrumented + ([#2816](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2816)) - `opentelemetry-instrumentation-sqlalchemy`: Fix a remaining memory leak in EngineTracer ([#3053](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3053)) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 633a356c40..e90402edc2 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -272,7 +272,11 @@ Below is a checklist of things to be mindful of when implementing a new instrume - Isolate sync and async test - For synchronous tests, the typical test case class is inherited from `opentelemetry.test.test_base.TestBase`. However, if you want to write asynchronous tests, the test case class should inherit also from `IsolatedAsyncioTestCase`. Adding asynchronous tests to a common test class can lead to tests passing without actually running, which can be misleading. - ex. -- All instrumentations have the same version. If you are going to develop a new instrumentation it would probably have `X.Y.dev` version and depends on `opentelemetry-instrumentation` and `opentelemetry-semantic-conventions` for the same version. That means that if you want to install your instrumentation you need to install its dependencies from this repo and the core repo also from git. +- Most of the instrumentations have the same version. If you are going to develop a new instrumentation it would probably have `X.Y.dev` version and depends on `opentelemetry-instrumentation` and `opentelemetry-semantic-conventions` for a [compatible version](https://peps.python.org/pep-0440/#compatible-release). That means that you may need to install the instrumentation dependencies from this repo and the core repo from git. +- Documentation + - When adding a new instrumentation remember to add an entry in `docs/instrumentation/` named `/.rst` to have the instrumentation documentation referenced from the index. You can use the entry template available [here](./_template/autodoc_entry.rst) +- Testing + - When adding a new instrumentation remember to update `tox.ini` adding appropriate rules in `envlist`, `command_pre` and `commands` sections ## Guideline for GenAI instrumentations diff --git a/_template/autodoc_entry.rst b/_template/autodoc_entry.rst new file mode 100644 index 0000000000..ee2688bacd --- /dev/null +++ b/_template/autodoc_entry.rst @@ -0,0 +1,7 @@ +.. include:: ../../../instrumentation/opentelemetry-instrumentation-/README.rst + :end-before: References + +.. automodule:: opentelemetry.instrumentation. + :members: + :undoc-members: + :show-inheritance: diff --git a/docs-requirements.txt b/docs-requirements.txt index 43e2265f7c..d547e806a3 100644 --- a/docs-requirements.txt +++ b/docs-requirements.txt @@ -2,14 +2,6 @@ sphinx==7.1.2 sphinx-rtd-theme==2.0.0rc4 sphinx-autodoc-typehints==1.25.2 -# Need to install the api/sdk in the venv for autodoc. Modifying sys.path -# doesn't work for pkg_resources. --e "git+https://github.com/open-telemetry/opentelemetry-python.git#egg=opentelemetry-api&subdirectory=opentelemetry-api" --e "git+https://github.com/open-telemetry/opentelemetry-python.git#egg=opentelemetry-semantic-conventions&subdirectory=opentelemetry-semantic-conventions" --e "git+https://github.com/open-telemetry/opentelemetry-python.git#egg=opentelemetry-sdk&subdirectory=opentelemetry-sdk" --e "git+https://github.com/open-telemetry/opentelemetry-python-contrib.git#egg=opentelemetry-util-http&subdirectory=util/opentelemetry-util-http" -./opentelemetry-instrumentation - # Required by opentelemetry-instrumentation fastapi>=0.65.2 pymemcache~=1.3 diff --git a/instrumentation-genai/opentelemetry-instrumentation-openai-v2/CHANGELOG.md b/instrumentation-genai/opentelemetry-instrumentation-openai-v2/CHANGELOG.md index 2c10498511..4644ee3dc5 100644 --- a/instrumentation-genai/opentelemetry-instrumentation-openai-v2/CHANGELOG.md +++ b/instrumentation-genai/opentelemetry-instrumentation-openai-v2/CHANGELOG.md @@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased +- Coerce openai response_format to semconv format + ([#3073](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3073)) - Add example to `opentelemetry-instrumentation-openai-v2` ([#3006](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3006)) - Support for `AsyncOpenAI/AsyncCompletions` ([#2984](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2984)) diff --git a/instrumentation-genai/opentelemetry-instrumentation-openai-v2/src/opentelemetry/instrumentation/openai_v2/utils.py b/instrumentation-genai/opentelemetry-instrumentation-openai-v2/src/opentelemetry/instrumentation/openai_v2/utils.py index cf920c17ee..f8a837259e 100644 --- a/instrumentation-genai/opentelemetry-instrumentation-openai-v2/src/opentelemetry/instrumentation/openai_v2/utils.py +++ b/instrumentation-genai/opentelemetry-instrumentation-openai-v2/src/opentelemetry/instrumentation/openai_v2/utils.py @@ -13,7 +13,7 @@ # limitations under the License. from os import environ -from typing import Optional, Union +from typing import Mapping, Optional, Union from urllib.parse import urlparse from httpx import URL @@ -202,12 +202,23 @@ def get_llm_request_attributes( GenAIAttributes.GEN_AI_REQUEST_FREQUENCY_PENALTY: kwargs.get( "frequency_penalty" ), - GenAIAttributes.GEN_AI_OPENAI_REQUEST_RESPONSE_FORMAT: kwargs.get( - "response_format" - ), GenAIAttributes.GEN_AI_OPENAI_REQUEST_SEED: kwargs.get("seed"), } + if (response_format := kwargs.get("response_format")) is not None: + # response_format may be string or object with a string in the `type` key + if isinstance(response_format, Mapping): + if ( + response_format_type := response_format.get("type") + ) is not None: + attributes[ + GenAIAttributes.GEN_AI_OPENAI_REQUEST_RESPONSE_FORMAT + ] = response_format_type + else: + attributes[ + GenAIAttributes.GEN_AI_OPENAI_REQUEST_RESPONSE_FORMAT + ] = response_format + set_server_address_and_port(client_instance, attributes) service_tier = kwargs.get("service_tier") attributes[GenAIAttributes.GEN_AI_OPENAI_RESPONSE_SERVICE_TIER] = ( diff --git a/instrumentation-genai/opentelemetry-instrumentation-openai-v2/tests/cassettes/test_async_chat_completion_extra_params.yaml b/instrumentation-genai/opentelemetry-instrumentation-openai-v2/tests/cassettes/test_async_chat_completion_extra_params.yaml index 3d13c9344e..37c18b091a 100644 --- a/instrumentation-genai/opentelemetry-instrumentation-openai-v2/tests/cassettes/test_async_chat_completion_extra_params.yaml +++ b/instrumentation-genai/opentelemetry-instrumentation-openai-v2/tests/cassettes/test_async_chat_completion_extra_params.yaml @@ -10,6 +10,9 @@ interactions: ], "model": "gpt-4o-mini", "max_tokens": 50, + "response_format": { + "type": "text" + }, "seed": 42, "stream": false, "temperature": 0.5, @@ -25,7 +28,7 @@ interactions: connection: - keep-alive content-length: - - '183' + - '220' content-type: - application/json host: @@ -45,16 +48,16 @@ interactions: x-stainless-runtime: - CPython x-stainless-runtime-version: - - 3.12.5 + - 3.12.7 method: POST uri: https://api.openai.com/v1/chat/completions response: body: string: |- { - "id": "chatcmpl-ASv9WMTAMZY4O1EImv3csZa6Ch7KI", + "id": "chatcmpl-AbMH3rR6OBMN9hG5w0TRrezuiHLMr", "object": "chat.completion", - "created": 1731456242, + "created": 1733467121, "model": "gpt-4o-mini-2024-07-18", "choices": [ { @@ -84,19 +87,19 @@ interactions: } }, "service_tier": "default", - "system_fingerprint": "fp_0ba0d124f1" + "system_fingerprint": "fp_bba3c8e70b" } headers: CF-Cache-Status: - DYNAMIC CF-RAY: - - 8e1a8088f867e167-MRS + - 8eda4640ead3e535-KUL Connection: - keep-alive Content-Type: - application/json Date: - - Wed, 13 Nov 2024 00:04:02 GMT + - Fri, 06 Dec 2024 06:38:42 GMT Server: - cloudflare Set-Cookie: test_set_cookie @@ -112,25 +115,25 @@ interactions: - '825' openai-organization: test_openai_org_id openai-processing-ms: - - '488' + - '835' openai-version: - '2020-10-01' strict-transport-security: - max-age=31536000; includeSubDomains; preload x-ratelimit-limit-requests: - - '30000' + - '10000' x-ratelimit-limit-tokens: - - '150000000' + - '200000' x-ratelimit-remaining-requests: - - '29999' + - '9999' x-ratelimit-remaining-tokens: - - '149999943' + - '199943' x-ratelimit-reset-requests: - - 2ms + - 8.64s x-ratelimit-reset-tokens: - - 0s + - 16ms x-request-id: - - req_6df08d6267415e8f5db3628a6757edad + - req_fea877c0a861ff92a6a5217247681f24 status: code: 200 message: OK diff --git a/instrumentation-genai/opentelemetry-instrumentation-openai-v2/tests/cassettes/test_chat_completion_extra_params.yaml b/instrumentation-genai/opentelemetry-instrumentation-openai-v2/tests/cassettes/test_chat_completion_extra_params.yaml index 7cc89ad9b8..87f9673512 100644 --- a/instrumentation-genai/opentelemetry-instrumentation-openai-v2/tests/cassettes/test_chat_completion_extra_params.yaml +++ b/instrumentation-genai/opentelemetry-instrumentation-openai-v2/tests/cassettes/test_chat_completion_extra_params.yaml @@ -10,6 +10,9 @@ interactions: ], "model": "gpt-4o-mini", "max_tokens": 50, + "response_format": { + "type": "text" + }, "seed": 42, "stream": false, "temperature": 0.5, @@ -25,13 +28,13 @@ interactions: connection: - keep-alive content-length: - - '183' + - '220' content-type: - application/json host: - api.openai.com user-agent: - - OpenAI/Python 1.54.3 + - OpenAI/Python 1.26.0 x-stainless-arch: - arm64 x-stainless-async: @@ -41,22 +44,20 @@ interactions: x-stainless-os: - MacOS x-stainless-package-version: - - 1.54.3 - x-stainless-retry-count: - - '0' + - 1.26.0 x-stainless-runtime: - CPython x-stainless-runtime-version: - - 3.12.6 + - 3.12.7 method: POST uri: https://api.openai.com/v1/chat/completions response: body: string: |- { - "id": "chatcmpl-ASYMT7913Sp58qhZqQgY7g7Ia2J4M", + "id": "chatcmpl-AbMH70fQA9lMPIClvBPyBSjqJBm9F", "object": "chat.completion", - "created": 1731368633, + "created": 1733467125, "model": "gpt-4o-mini-2024-07-18", "choices": [ { @@ -86,19 +87,17 @@ interactions: } }, "service_tier": "default", - "system_fingerprint": "fp_0ba0d124f1" + "system_fingerprint": "fp_0705bf87c0" } headers: - CF-Cache-Status: - - DYNAMIC CF-RAY: - - 8e1225a3f8e9ce65-SIN + - 8eda465e8fe9e58c-KUL Connection: - keep-alive Content-Type: - application/json Date: - - Mon, 11 Nov 2024 23:43:53 GMT + - Fri, 06 Dec 2024 06:38:46 GMT Server: - cloudflare Set-Cookie: test_set_cookie @@ -110,11 +109,13 @@ interactions: - X-Request-ID alt-svc: - h3=":443"; ma=86400 + cf-cache-status: + - DYNAMIC content-length: - '825' openai-organization: test_openai_org_id openai-processing-ms: - - '431' + - '558' openai-version: - '2020-10-01' strict-transport-security: @@ -128,11 +129,11 @@ interactions: x-ratelimit-remaining-tokens: - '199943' x-ratelimit-reset-requests: - - 14.746s + - 12.967s x-ratelimit-reset-tokens: - 16ms x-request-id: - - req_81e29a8992ea8001c0240bd990acf0ab + - req_22ff608d47a299f0780f52360631eabb status: code: 200 message: OK diff --git a/instrumentation-genai/opentelemetry-instrumentation-openai-v2/tests/test_async_chat_completions.py b/instrumentation-genai/opentelemetry-instrumentation-openai-v2/tests/test_async_chat_completions.py index e19bc7c311..65c596796d 100644 --- a/instrumentation-genai/opentelemetry-instrumentation-openai-v2/tests/test_async_chat_completions.py +++ b/instrumentation-genai/opentelemetry-instrumentation-openai-v2/tests/test_async_chat_completions.py @@ -158,6 +158,7 @@ async def test_async_chat_completion_extra_params( max_tokens=50, stream=False, extra_body={"service_tier": "default"}, + response_format={"type": "text"}, ) spans = span_exporter.get_finished_spans() @@ -173,6 +174,12 @@ async def test_async_chat_completion_extra_params( spans[0].attributes[GenAIAttributes.GEN_AI_OPENAI_REQUEST_SERVICE_TIER] == "default" ) + assert ( + spans[0].attributes[ + GenAIAttributes.GEN_AI_OPENAI_REQUEST_RESPONSE_FORMAT + ] + == "text" + ) @pytest.mark.vcr() diff --git a/instrumentation-genai/opentelemetry-instrumentation-openai-v2/tests/test_chat_completions.py b/instrumentation-genai/opentelemetry-instrumentation-openai-v2/tests/test_chat_completions.py index 4f732290c0..4677b7cb95 100644 --- a/instrumentation-genai/opentelemetry-instrumentation-openai-v2/tests/test_chat_completions.py +++ b/instrumentation-genai/opentelemetry-instrumentation-openai-v2/tests/test_chat_completions.py @@ -151,6 +151,7 @@ def test_chat_completion_extra_params( max_tokens=50, stream=False, extra_body={"service_tier": "default"}, + response_format={"type": "text"}, ) spans = span_exporter.get_finished_spans() @@ -166,6 +167,12 @@ def test_chat_completion_extra_params( spans[0].attributes[GenAIAttributes.GEN_AI_OPENAI_REQUEST_SERVICE_TIER] == "default" ) + assert ( + spans[0].attributes[ + GenAIAttributes.GEN_AI_OPENAI_REQUEST_RESPONSE_FORMAT + ] + == "text" + ) @pytest.mark.vcr() diff --git a/instrumentation/opentelemetry-instrumentation-aiohttp-client/test-requirements.txt b/instrumentation/opentelemetry-instrumentation-aiohttp-client/test-requirements.txt index 8a0c88f805..04f853bdbf 100644 --- a/instrumentation/opentelemetry-instrumentation-aiohttp-client/test-requirements.txt +++ b/instrumentation/opentelemetry-instrumentation-aiohttp-client/test-requirements.txt @@ -24,7 +24,7 @@ requests==2.32.3 tomli==2.0.1 typing_extensions==4.12.2 urllib3==2.2.2 -Werkzeug==3.0.3 +Werkzeug==3.0.6 wrapt==1.16.0 yarl==1.9.4 zipp==3.19.2 diff --git a/instrumentation/opentelemetry-instrumentation-aiokafka/src/opentelemetry/instrumentation/aiokafka/__init__.py b/instrumentation/opentelemetry-instrumentation-aiokafka/src/opentelemetry/instrumentation/aiokafka/__init__.py index 507206f4f2..4b14ace4fb 100644 --- a/instrumentation/opentelemetry-instrumentation-aiokafka/src/opentelemetry/instrumentation/aiokafka/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-aiokafka/src/opentelemetry/instrumentation/aiokafka/__init__.py @@ -18,7 +18,7 @@ Usage ----- -..code:: python +.. code:: python from opentelemetry.instrumentation.aiokafka import AIOKafkaInstrumentor from aiokafka import AIOKafkaProducer, AIOKafkaConsumer @@ -45,7 +45,8 @@ def async_produce_hook(span: Span, args, kwargs) def async_consume_hook(span: Span, record: kafka.record.ABCRecord, args, kwargs) for example: -.. code: python +.. code:: python + from opentelemetry.instrumentation.kafka import AIOKafkaInstrumentor from aiokafka import AIOKafkaProducer, AIOKafkaConsumer diff --git a/instrumentation/opentelemetry-instrumentation-botocore/test-requirements.txt b/instrumentation/opentelemetry-instrumentation-botocore/test-requirements.txt index 5253cf3bba..aa5f89859f 100644 --- a/instrumentation/opentelemetry-instrumentation-botocore/test-requirements.txt +++ b/instrumentation/opentelemetry-instrumentation-botocore/test-requirements.txt @@ -29,7 +29,7 @@ six==1.16.0 tomli==2.0.1 typing_extensions==4.12.2 urllib3==1.26.19 -Werkzeug==3.0.3 +Werkzeug==3.0.6 wrapt==1.16.0 xmltodict==0.13.0 zipp==3.19.2 diff --git a/instrumentation/opentelemetry-instrumentation-confluent-kafka/src/opentelemetry/instrumentation/confluent_kafka/__init__.py b/instrumentation/opentelemetry-instrumentation-confluent-kafka/src/opentelemetry/instrumentation/confluent_kafka/__init__.py index aaf906d118..48b2bd2c26 100644 --- a/instrumentation/opentelemetry-instrumentation-confluent-kafka/src/opentelemetry/instrumentation/confluent_kafka/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-confluent-kafka/src/opentelemetry/instrumentation/confluent_kafka/__init__.py @@ -18,7 +18,7 @@ Usage ----- -.. code-block:: python +.. code:: python from opentelemetry.instrumentation.confluent_kafka import ConfluentKafkaInstrumentor from confluent_kafka import Producer, Consumer @@ -54,7 +54,6 @@ def basic_consume_loop(consumer, topics): consumer.close() basic_consume_loop(consumer, "my-topic") - --- The _instrument method accepts the following keyword args: tracer_provider (TracerProvider) - an optional tracer provider @@ -95,7 +94,6 @@ def instrument_consumer(consumer: Consumer, tracer_provider=None) p.produce('my-topic',b'raw_bytes') msg = c.poll() -___ """ from typing import Collection diff --git a/instrumentation/opentelemetry-instrumentation-django/test-requirements-2.txt b/instrumentation/opentelemetry-instrumentation-django/test-requirements-2.txt index 1ee4b0bfbf..6d84c3db89 100644 --- a/instrumentation/opentelemetry-instrumentation-django/test-requirements-2.txt +++ b/instrumentation/opentelemetry-instrumentation-django/test-requirements-2.txt @@ -1,7 +1,7 @@ asgiref==3.8.1 backports.zoneinfo==0.2.1 Deprecated==1.2.14 -Django==4.2.15 +Django==4.2.17 iniconfig==2.0.0 packaging==24.0 pluggy==1.5.0 diff --git a/instrumentation/opentelemetry-instrumentation-django/test-requirements-3.txt b/instrumentation/opentelemetry-instrumentation-django/test-requirements-3.txt index aba0b28fa2..61ed226da4 100644 --- a/instrumentation/opentelemetry-instrumentation-django/test-requirements-3.txt +++ b/instrumentation/opentelemetry-instrumentation-django/test-requirements-3.txt @@ -1,6 +1,6 @@ asgiref==3.8.1 Deprecated==1.2.14 -Django==4.2.15 +Django==4.2.17 iniconfig==2.0.0 packaging==24.0 pluggy==1.5.0 diff --git a/instrumentation/opentelemetry-instrumentation-flask/test-requirements-2.txt b/instrumentation/opentelemetry-instrumentation-flask/test-requirements-2.txt index 59edf6f540..d7bf77e315 100644 --- a/instrumentation/opentelemetry-instrumentation-flask/test-requirements-2.txt +++ b/instrumentation/opentelemetry-instrumentation-flask/test-requirements-2.txt @@ -13,7 +13,7 @@ py-cpuinfo==9.0.0 pytest==7.4.4 tomli==2.0.1 typing_extensions==4.12.2 -Werkzeug==3.0.3 +Werkzeug==3.0.6 wrapt==1.16.0 zipp==3.19.2 -e opentelemetry-instrumentation diff --git a/instrumentation/opentelemetry-instrumentation-kafka-python/src/opentelemetry/instrumentation/kafka/__init__.py b/instrumentation/opentelemetry-instrumentation-kafka-python/src/opentelemetry/instrumentation/kafka/__init__.py index 9b0f4895f9..1e0dbf79e1 100644 --- a/instrumentation/opentelemetry-instrumentation-kafka-python/src/opentelemetry/instrumentation/kafka/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-kafka-python/src/opentelemetry/instrumentation/kafka/__init__.py @@ -18,7 +18,7 @@ Usage ----- -..code:: python +.. code:: python from opentelemetry.instrumentation.kafka import KafkaInstrumentor from kafka import KafkaProducer, KafkaConsumer @@ -45,7 +45,8 @@ def produce_hook(span: Span, args, kwargs) def consume_hook(span: Span, record: kafka.record.ABCRecord, args, kwargs) for example: -.. code: python +.. code:: python + from opentelemetry.instrumentation.kafka import KafkaInstrumentor from kafka import KafkaProducer, KafkaConsumer diff --git a/instrumentation/opentelemetry-instrumentation-pyramid/test-requirements.txt b/instrumentation/opentelemetry-instrumentation-pyramid/test-requirements.txt index 97815133f8..157b9b6040 100644 --- a/instrumentation/opentelemetry-instrumentation-pyramid/test-requirements.txt +++ b/instrumentation/opentelemetry-instrumentation-pyramid/test-requirements.txt @@ -15,7 +15,7 @@ translationstring==1.4 typing_extensions==4.12.2 venusian==3.1.0 WebOb==1.8.8 -Werkzeug==3.0.3 +Werkzeug==3.0.6 wrapt==1.16.0 zipp==3.19.2 zope.deprecation==5.0 diff --git a/instrumentation/opentelemetry-instrumentation-sqlalchemy/src/opentelemetry/instrumentation/sqlalchemy/__init__.py b/instrumentation/opentelemetry-instrumentation-sqlalchemy/src/opentelemetry/instrumentation/sqlalchemy/__init__.py index 9889e18b5a..4182c0034e 100644 --- a/instrumentation/opentelemetry-instrumentation-sqlalchemy/src/opentelemetry/instrumentation/sqlalchemy/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-sqlalchemy/src/opentelemetry/instrumentation/sqlalchemy/__init__.py @@ -181,6 +181,18 @@ def _instrument(self, **kwargs): tracer, connections_usage, enable_commenter, commenter_options ), ) + # sqlalchemy.engine.create is not present in earlier versions of sqlalchemy (which we support) + if parse_version(sqlalchemy.__version__).release >= (1, 4): + _w( + "sqlalchemy.engine.create", + "create_engine", + _wrap_create_engine( + tracer, + connections_usage, + enable_commenter, + commenter_options, + ), + ) _w( "sqlalchemy.engine.base", "Engine.connect", @@ -224,6 +236,8 @@ def _instrument(self, **kwargs): def _uninstrument(self, **kwargs): unwrap(sqlalchemy, "create_engine") unwrap(sqlalchemy.engine, "create_engine") + if parse_version(sqlalchemy.__version__).release >= (1, 4): + unwrap(sqlalchemy.engine.create, "create_engine") unwrap(Engine, "connect") if parse_version(sqlalchemy.__version__).release >= (1, 4): unwrap(sqlalchemy.ext.asyncio, "create_async_engine") diff --git a/instrumentation/opentelemetry-instrumentation-sqlalchemy/tests/test_sqlalchemy.py b/instrumentation/opentelemetry-instrumentation-sqlalchemy/tests/test_sqlalchemy.py index 18b9fa65f7..27a253decb 100644 --- a/instrumentation/opentelemetry-instrumentation-sqlalchemy/tests/test_sqlalchemy.py +++ b/instrumentation/opentelemetry-instrumentation-sqlalchemy/tests/test_sqlalchemy.py @@ -182,6 +182,17 @@ def test_create_engine_wrapper(self): "opentelemetry.instrumentation.sqlalchemy", ) + def test_instrument_engine_from_config(self): + SQLAlchemyInstrumentor().instrument() + from sqlalchemy import engine_from_config # pylint: disable-all + + engine = engine_from_config({"sqlalchemy.url": "sqlite:///:memory:"}) + cnx = engine.connect() + cnx.execute(text("SELECT 1 + 1;")).fetchall() + spans = self.memory_exporter.get_finished_spans() + + self.assertEqual(len(spans), 2) + def test_create_engine_wrapper_enable_commenter(self): logging.getLogger("sqlalchemy.engine").setLevel(logging.INFO) SQLAlchemyInstrumentor().instrument( diff --git a/instrumentation/opentelemetry-instrumentation-sqlite3/src/opentelemetry/instrumentation/sqlite3/__init__.py b/instrumentation/opentelemetry-instrumentation-sqlite3/src/opentelemetry/instrumentation/sqlite3/__init__.py index 9b3ae28a95..1ec4794e96 100644 --- a/instrumentation/opentelemetry-instrumentation-sqlite3/src/opentelemetry/instrumentation/sqlite3/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-sqlite3/src/opentelemetry/instrumentation/sqlite3/__init__.py @@ -39,20 +39,27 @@ --- """ +from __future__ import annotations + import sqlite3 from sqlite3 import dbapi2 -from typing import Collection +from typing import Any, Collection, TypeVar, Union from opentelemetry.instrumentation import dbapi from opentelemetry.instrumentation.instrumentor import BaseInstrumentor from opentelemetry.instrumentation.sqlite3.package import _instruments from opentelemetry.instrumentation.sqlite3.version import __version__ +from opentelemetry.trace import TracerProvider # No useful attributes of sqlite3 connection object _CONNECTION_ATTRIBUTES = {} _DATABASE_SYSTEM = "sqlite" +SQLite3Connection = TypeVar( # pylint: disable=invalid-name + "SQLite3Connection", bound=Union[sqlite3.Connection, None] +) + class SQLite3Instrumentor(BaseInstrumentor): _TO_WRAP = [sqlite3, dbapi2] @@ -60,7 +67,7 @@ class SQLite3Instrumentor(BaseInstrumentor): def instrumentation_dependencies(self) -> Collection[str]: return _instruments - def _instrument(self, **kwargs): + def _instrument(self, **kwargs: Any) -> None: """Integrate with SQLite3 Python library. https://docs.python.org/3/library/sqlite3.html """ @@ -77,13 +84,16 @@ def _instrument(self, **kwargs): tracer_provider=tracer_provider, ) - def _uninstrument(self, **kwargs): + def _uninstrument(self, **kwargs: Any) -> None: """ "Disable SQLite3 instrumentation""" for module in self._TO_WRAP: dbapi.unwrap_connect(module, "connect") @staticmethod - def instrument_connection(connection, tracer_provider=None): + def instrument_connection( + connection: SQLite3Connection, + tracer_provider: TracerProvider | None = None, + ) -> SQLite3Connection: """Enable instrumentation in a SQLite connection. Args: @@ -105,7 +115,9 @@ def instrument_connection(connection, tracer_provider=None): ) @staticmethod - def uninstrument_connection(connection): + def uninstrument_connection( + connection: SQLite3Connection, + ) -> SQLite3Connection: """Disable instrumentation in a SQLite connection. Args: diff --git a/instrumentation/opentelemetry-instrumentation-sqlite3/src/opentelemetry/instrumentation/sqlite3/package.py b/instrumentation/opentelemetry-instrumentation-sqlite3/src/opentelemetry/instrumentation/sqlite3/package.py index 7a66a17a93..0de6133b4a 100644 --- a/instrumentation/opentelemetry-instrumentation-sqlite3/src/opentelemetry/instrumentation/sqlite3/package.py +++ b/instrumentation/opentelemetry-instrumentation-sqlite3/src/opentelemetry/instrumentation/sqlite3/package.py @@ -11,6 +11,6 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +from __future__ import annotations - -_instruments = tuple() +_instruments: tuple[str, ...] = tuple() diff --git a/instrumentation/opentelemetry-instrumentation-tornado/test-requirements.txt b/instrumentation/opentelemetry-instrumentation-tornado/test-requirements.txt index 56a088ec62..2df7df38ec 100644 --- a/instrumentation/opentelemetry-instrumentation-tornado/test-requirements.txt +++ b/instrumentation/opentelemetry-instrumentation-tornado/test-requirements.txt @@ -17,10 +17,10 @@ py-cpuinfo==9.0.0 pytest==7.4.4 requests==2.32.3 tomli==2.0.1 -tornado==6.4.1 +tornado==6.4.2 typing_extensions==4.12.2 urllib3==2.2.2 -Werkzeug==3.0.3 +Werkzeug==3.0.6 wrapt==1.16.0 zipp==3.19.2 -e opentelemetry-instrumentation diff --git a/rtd-requirements.txt b/rtd-requirements.txt new file mode 100644 index 0000000000..b68781bd8c --- /dev/null +++ b/rtd-requirements.txt @@ -0,0 +1,7 @@ +# Need to install the api/sdk in the venv for autodoc. Used by .readthedocs.yml +opentelemetry-api @ git+https://github.com/open-telemetry/opentelemetry-python.git@main#egg=opentelemetry-api&subdirectory=opentelemetry-api +opentelemetry-semantic-conventions @ git+https://github.com/open-telemetry/opentelemetry-python.git@main#egg=opentelemetry-semantic-conventions&subdirectory=opentelemetry-semantic-conventions +opentelemetry-sdk @ git+https://github.com/open-telemetry/opentelemetry-python.git@main#egg=opentelemetry-sdk&subdirectory=opentelemetry-sdk +./opentelemetry-instrumentation +./util/opentelemetry-util-http +-r ./docs-requirements.txt