opentelemetry-instrumentation 0.52b1__tar.gz → 0.53b0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. {opentelemetry_instrumentation-0.52b1 → opentelemetry_instrumentation-0.53b0}/PKG-INFO +2 -2
  2. {opentelemetry_instrumentation-0.52b1 → opentelemetry_instrumentation-0.53b0}/pyproject.toml +1 -1
  3. {opentelemetry_instrumentation-0.52b1 → opentelemetry_instrumentation-0.53b0}/src/opentelemetry/instrumentation/_semconv.py +2 -1
  4. {opentelemetry_instrumentation-0.52b1 → opentelemetry_instrumentation-0.53b0}/src/opentelemetry/instrumentation/auto_instrumentation/_load.py +12 -43
  5. {opentelemetry_instrumentation-0.52b1 → opentelemetry_instrumentation-0.53b0}/src/opentelemetry/instrumentation/bootstrap_gen.py +57 -53
  6. {opentelemetry_instrumentation-0.52b1 → opentelemetry_instrumentation-0.53b0}/src/opentelemetry/instrumentation/dependencies.py +8 -18
  7. {opentelemetry_instrumentation-0.52b1 → opentelemetry_instrumentation-0.53b0}/src/opentelemetry/instrumentation/instrumentor.py +6 -0
  8. {opentelemetry_instrumentation-0.52b1 → opentelemetry_instrumentation-0.53b0}/src/opentelemetry/instrumentation/sqlcommenter_utils.py +1 -1
  9. {opentelemetry_instrumentation-0.52b1 → opentelemetry_instrumentation-0.53b0}/src/opentelemetry/instrumentation/version.py +1 -1
  10. {opentelemetry_instrumentation-0.52b1 → opentelemetry_instrumentation-0.53b0}/tests/auto_instrumentation/test_load.py +38 -58
  11. {opentelemetry_instrumentation-0.52b1 → opentelemetry_instrumentation-0.53b0}/tests/test_dependencies.py +0 -40
  12. {opentelemetry_instrumentation-0.52b1 → opentelemetry_instrumentation-0.53b0}/tests/test_instrumentor.py +23 -0
  13. {opentelemetry_instrumentation-0.52b1 → opentelemetry_instrumentation-0.53b0}/.gitignore +0 -0
  14. {opentelemetry_instrumentation-0.52b1 → opentelemetry_instrumentation-0.53b0}/LICENSE +0 -0
  15. {opentelemetry_instrumentation-0.52b1 → opentelemetry_instrumentation-0.53b0}/README.rst +0 -0
  16. {opentelemetry_instrumentation-0.52b1 → opentelemetry_instrumentation-0.53b0}/src/opentelemetry/instrumentation/auto_instrumentation/__init__.py +0 -0
  17. {opentelemetry_instrumentation-0.52b1 → opentelemetry_instrumentation-0.53b0}/src/opentelemetry/instrumentation/auto_instrumentation/sitecustomize.py +0 -0
  18. {opentelemetry_instrumentation-0.52b1 → opentelemetry_instrumentation-0.53b0}/src/opentelemetry/instrumentation/bootstrap.py +0 -0
  19. {opentelemetry_instrumentation-0.52b1 → opentelemetry_instrumentation-0.53b0}/src/opentelemetry/instrumentation/distro.py +0 -0
  20. {opentelemetry_instrumentation-0.52b1 → opentelemetry_instrumentation-0.53b0}/src/opentelemetry/instrumentation/environment_variables.py +0 -0
  21. {opentelemetry_instrumentation-0.52b1 → opentelemetry_instrumentation-0.53b0}/src/opentelemetry/instrumentation/propagators.py +0 -0
  22. {opentelemetry_instrumentation-0.52b1 → opentelemetry_instrumentation-0.53b0}/src/opentelemetry/instrumentation/py.typed +0 -0
  23. {opentelemetry_instrumentation-0.52b1 → opentelemetry_instrumentation-0.53b0}/src/opentelemetry/instrumentation/utils.py +0 -0
  24. {opentelemetry_instrumentation-0.52b1 → opentelemetry_instrumentation-0.53b0}/tests/__init__.py +0 -0
  25. {opentelemetry_instrumentation-0.52b1 → opentelemetry_instrumentation-0.53b0}/tests/auto_instrumentation/test_initialize.py +0 -0
  26. {opentelemetry_instrumentation-0.52b1 → opentelemetry_instrumentation-0.53b0}/tests/auto_instrumentation/test_run.py +0 -0
  27. {opentelemetry_instrumentation-0.52b1 → opentelemetry_instrumentation-0.53b0}/tests/auto_instrumentation/test_sitecustomize.py +0 -0
  28. {opentelemetry_instrumentation-0.52b1 → opentelemetry_instrumentation-0.53b0}/tests/test_bootstrap.py +0 -0
  29. {opentelemetry_instrumentation-0.52b1 → opentelemetry_instrumentation-0.53b0}/tests/test_distro.py +0 -0
  30. {opentelemetry_instrumentation-0.52b1 → opentelemetry_instrumentation-0.53b0}/tests/test_propagators.py +0 -0
  31. {opentelemetry_instrumentation-0.52b1 → opentelemetry_instrumentation-0.53b0}/tests/test_semconv.py +0 -0
  32. {opentelemetry_instrumentation-0.52b1 → opentelemetry_instrumentation-0.53b0}/tests/test_utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: opentelemetry-instrumentation
3
- Version: 0.52b1
3
+ Version: 0.53b0
4
4
  Summary: Instrumentation Tools & Auto Instrumentation for OpenTelemetry Python
5
5
  Project-URL: Homepage, https://github.com/open-telemetry/opentelemetry-python-contrib/tree/main/opentelemetry-instrumentation
6
6
  Project-URL: Repository, https://github.com/open-telemetry/opentelemetry-python-contrib
@@ -20,7 +20,7 @@ Classifier: Programming Language :: Python :: 3.12
20
20
  Classifier: Programming Language :: Python :: 3.13
21
21
  Requires-Python: >=3.8
22
22
  Requires-Dist: opentelemetry-api~=1.4
23
- Requires-Dist: opentelemetry-semantic-conventions==0.52b1
23
+ Requires-Dist: opentelemetry-semantic-conventions==0.53b0
24
24
  Requires-Dist: packaging>=18.0
25
25
  Requires-Dist: wrapt<2.0.0,>=1.0.0
26
26
  Description-Content-Type: text/x-rst
@@ -27,7 +27,7 @@ classifiers = [
27
27
  ]
28
28
  dependencies = [
29
29
  "opentelemetry-api ~= 1.4",
30
- "opentelemetry-semantic-conventions == 0.52b1",
30
+ "opentelemetry-semantic-conventions == 0.53b0",
31
31
  "wrapt >= 1.0.0, < 2.0.0",
32
32
  "packaging >= 18.0",
33
33
  ]
@@ -354,7 +354,8 @@ def _set_http_host_server(result, host, sem_conv_opt_in_mode):
354
354
  if _report_old(sem_conv_opt_in_mode):
355
355
  set_string_attribute(result, SpanAttributes.HTTP_HOST, host)
356
356
  if _report_new(sem_conv_opt_in_mode):
357
- set_string_attribute(result, CLIENT_ADDRESS, host)
357
+ if not result.get(SERVER_ADDRESS):
358
+ set_string_attribute(result, SERVER_ADDRESS, host)
358
359
 
359
360
 
360
361
  # net.peer.ip -> net.sock.peer.addr
@@ -12,13 +12,10 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
- from functools import cached_property
16
15
  from logging import getLogger
17
16
  from os import environ
18
17
 
19
- from opentelemetry.instrumentation.dependencies import (
20
- get_dist_dependency_conflicts,
21
- )
18
+ from opentelemetry.instrumentation.dependencies import DependencyConflictError
22
19
  from opentelemetry.instrumentation.distro import BaseDistro, DefaultDistro
23
20
  from opentelemetry.instrumentation.environment_variables import (
24
21
  OTEL_PYTHON_CONFIGURATOR,
@@ -26,36 +23,11 @@ from opentelemetry.instrumentation.environment_variables import (
26
23
  OTEL_PYTHON_DISTRO,
27
24
  )
28
25
  from opentelemetry.instrumentation.version import __version__
29
- from opentelemetry.util._importlib_metadata import (
30
- EntryPoint,
31
- distributions,
32
- entry_points,
33
- )
26
+ from opentelemetry.util._importlib_metadata import entry_points
34
27
 
35
28
  _logger = getLogger(__name__)
36
29
 
37
30
 
38
- class _EntryPointDistFinder:
39
- @cached_property
40
- def _mapping(self):
41
- return {
42
- self._key_for(ep): dist
43
- for dist in distributions()
44
- for ep in dist.entry_points
45
- }
46
-
47
- def dist_for(self, entry_point: EntryPoint):
48
- dist = getattr(entry_point, "dist", None)
49
- if dist:
50
- return dist
51
-
52
- return self._mapping.get(self._key_for(entry_point))
53
-
54
- @staticmethod
55
- def _key_for(entry_point: EntryPoint):
56
- return f"{entry_point.group}:{entry_point.name}:{entry_point.value}"
57
-
58
-
59
31
  def _load_distro() -> BaseDistro:
60
32
  distro_name = environ.get(OTEL_PYTHON_DISTRO, None)
61
33
  for entry_point in entry_points(group="opentelemetry_distro"):
@@ -83,7 +55,6 @@ def _load_distro() -> BaseDistro:
83
55
 
84
56
  def _load_instrumentors(distro):
85
57
  package_to_exclude = environ.get(OTEL_PYTHON_DISABLED_INSTRUMENTATIONS, [])
86
- entry_point_finder = _EntryPointDistFinder()
87
58
  if isinstance(package_to_exclude, str):
88
59
  package_to_exclude = package_to_exclude.split(",")
89
60
  # to handle users entering "requests , flask" or "requests, flask" with spaces
@@ -100,19 +71,17 @@ def _load_instrumentors(distro):
100
71
  continue
101
72
 
102
73
  try:
103
- entry_point_dist = entry_point_finder.dist_for(entry_point)
104
- conflict = get_dist_dependency_conflicts(entry_point_dist)
105
- if conflict:
106
- _logger.debug(
107
- "Skipping instrumentation %s: %s",
108
- entry_point.name,
109
- conflict,
110
- )
111
- continue
112
-
113
- # tell instrumentation to not run dep checks again as we already did it above
114
- distro.load_instrumentor(entry_point, skip_dep_check=True)
74
+ distro.load_instrumentor(
75
+ entry_point, raise_exception_on_conflict=True
76
+ )
115
77
  _logger.debug("Instrumented %s", entry_point.name)
78
+ except DependencyConflictError as exc:
79
+ _logger.debug(
80
+ "Skipping instrumentation %s: %s",
81
+ entry_point.name,
82
+ exc.conflict,
83
+ )
84
+ continue
116
85
  except ImportError:
117
86
  # in scenarios using the kubernetes operator to do autoinstrumentation some
118
87
  # instrumentors (usually requiring binary extensions) may fail to load
@@ -26,195 +26,199 @@ libraries = [
26
26
  },
27
27
  {
28
28
  "library": "aio_pika >= 7.2.0, < 10.0.0",
29
- "instrumentation": "opentelemetry-instrumentation-aio-pika==0.52b1",
29
+ "instrumentation": "opentelemetry-instrumentation-aio-pika==0.53b0",
30
30
  },
31
31
  {
32
32
  "library": "aiohttp ~= 3.0",
33
- "instrumentation": "opentelemetry-instrumentation-aiohttp-client==0.52b1",
33
+ "instrumentation": "opentelemetry-instrumentation-aiohttp-client==0.53b0",
34
34
  },
35
35
  {
36
36
  "library": "aiohttp ~= 3.0",
37
- "instrumentation": "opentelemetry-instrumentation-aiohttp-server==0.52b1",
37
+ "instrumentation": "opentelemetry-instrumentation-aiohttp-server==0.53b0",
38
38
  },
39
39
  {
40
40
  "library": "aiokafka >= 0.8, < 1.0",
41
- "instrumentation": "opentelemetry-instrumentation-aiokafka==0.52b1",
41
+ "instrumentation": "opentelemetry-instrumentation-aiokafka==0.53b0",
42
42
  },
43
43
  {
44
44
  "library": "aiopg >= 0.13.0, < 2.0.0",
45
- "instrumentation": "opentelemetry-instrumentation-aiopg==0.52b1",
45
+ "instrumentation": "opentelemetry-instrumentation-aiopg==0.53b0",
46
46
  },
47
47
  {
48
48
  "library": "asgiref ~= 3.0",
49
- "instrumentation": "opentelemetry-instrumentation-asgi==0.52b1",
49
+ "instrumentation": "opentelemetry-instrumentation-asgi==0.53b0",
50
+ },
51
+ {
52
+ "library": "asyncclick ~= 8.0",
53
+ "instrumentation": "opentelemetry-instrumentation-asyncclick==0.53b0",
50
54
  },
51
55
  {
52
56
  "library": "asyncpg >= 0.12.0",
53
- "instrumentation": "opentelemetry-instrumentation-asyncpg==0.52b1",
57
+ "instrumentation": "opentelemetry-instrumentation-asyncpg==0.53b0",
54
58
  },
55
59
  {
56
60
  "library": "boto~=2.0",
57
- "instrumentation": "opentelemetry-instrumentation-boto==0.52b1",
61
+ "instrumentation": "opentelemetry-instrumentation-boto==0.53b0",
58
62
  },
59
63
  {
60
64
  "library": "boto3 ~= 1.0",
61
- "instrumentation": "opentelemetry-instrumentation-boto3sqs==0.52b1",
65
+ "instrumentation": "opentelemetry-instrumentation-boto3sqs==0.53b0",
62
66
  },
63
67
  {
64
68
  "library": "botocore ~= 1.0",
65
- "instrumentation": "opentelemetry-instrumentation-botocore==0.52b1",
69
+ "instrumentation": "opentelemetry-instrumentation-botocore==0.53b0",
66
70
  },
67
71
  {
68
72
  "library": "cassandra-driver ~= 3.25",
69
- "instrumentation": "opentelemetry-instrumentation-cassandra==0.52b1",
73
+ "instrumentation": "opentelemetry-instrumentation-cassandra==0.53b0",
70
74
  },
71
75
  {
72
76
  "library": "scylla-driver ~= 3.25",
73
- "instrumentation": "opentelemetry-instrumentation-cassandra==0.52b1",
77
+ "instrumentation": "opentelemetry-instrumentation-cassandra==0.53b0",
74
78
  },
75
79
  {
76
80
  "library": "celery >= 4.0, < 6.0",
77
- "instrumentation": "opentelemetry-instrumentation-celery==0.52b1",
81
+ "instrumentation": "opentelemetry-instrumentation-celery==0.53b0",
78
82
  },
79
83
  {
80
84
  "library": "click >= 8.1.3, < 9.0.0",
81
- "instrumentation": "opentelemetry-instrumentation-click==0.52b1",
85
+ "instrumentation": "opentelemetry-instrumentation-click==0.53b0",
82
86
  },
83
87
  {
84
88
  "library": "confluent-kafka >= 1.8.2, <= 2.7.0",
85
- "instrumentation": "opentelemetry-instrumentation-confluent-kafka==0.52b1",
89
+ "instrumentation": "opentelemetry-instrumentation-confluent-kafka==0.53b0",
86
90
  },
87
91
  {
88
92
  "library": "django >= 1.10",
89
- "instrumentation": "opentelemetry-instrumentation-django==0.52b1",
93
+ "instrumentation": "opentelemetry-instrumentation-django==0.53b0",
90
94
  },
91
95
  {
92
96
  "library": "elasticsearch >= 6.0",
93
- "instrumentation": "opentelemetry-instrumentation-elasticsearch==0.52b1",
97
+ "instrumentation": "opentelemetry-instrumentation-elasticsearch==0.53b0",
94
98
  },
95
99
  {
96
100
  "library": "falcon >= 1.4.1, < 5.0.0",
97
- "instrumentation": "opentelemetry-instrumentation-falcon==0.52b1",
101
+ "instrumentation": "opentelemetry-instrumentation-falcon==0.53b0",
98
102
  },
99
103
  {
100
104
  "library": "fastapi ~= 0.58",
101
- "instrumentation": "opentelemetry-instrumentation-fastapi==0.52b1",
105
+ "instrumentation": "opentelemetry-instrumentation-fastapi==0.53b0",
102
106
  },
103
107
  {
104
108
  "library": "flask >= 1.0",
105
- "instrumentation": "opentelemetry-instrumentation-flask==0.52b1",
109
+ "instrumentation": "opentelemetry-instrumentation-flask==0.53b0",
106
110
  },
107
111
  {
108
112
  "library": "grpcio >= 1.42.0",
109
- "instrumentation": "opentelemetry-instrumentation-grpc==0.52b1",
113
+ "instrumentation": "opentelemetry-instrumentation-grpc==0.53b0",
110
114
  },
111
115
  {
112
116
  "library": "httpx >= 0.18.0",
113
- "instrumentation": "opentelemetry-instrumentation-httpx==0.52b1",
117
+ "instrumentation": "opentelemetry-instrumentation-httpx==0.53b0",
114
118
  },
115
119
  {
116
120
  "library": "jinja2 >= 2.7, < 4.0",
117
- "instrumentation": "opentelemetry-instrumentation-jinja2==0.52b1",
121
+ "instrumentation": "opentelemetry-instrumentation-jinja2==0.53b0",
118
122
  },
119
123
  {
120
124
  "library": "kafka-python >= 2.0, < 3.0",
121
- "instrumentation": "opentelemetry-instrumentation-kafka-python==0.52b1",
125
+ "instrumentation": "opentelemetry-instrumentation-kafka-python==0.53b0",
122
126
  },
123
127
  {
124
128
  "library": "kafka-python-ng >= 2.0, < 3.0",
125
- "instrumentation": "opentelemetry-instrumentation-kafka-python==0.52b1",
129
+ "instrumentation": "opentelemetry-instrumentation-kafka-python==0.53b0",
126
130
  },
127
131
  {
128
132
  "library": "mysql-connector-python >= 8.0, < 10.0",
129
- "instrumentation": "opentelemetry-instrumentation-mysql==0.52b1",
133
+ "instrumentation": "opentelemetry-instrumentation-mysql==0.53b0",
130
134
  },
131
135
  {
132
136
  "library": "mysqlclient < 3",
133
- "instrumentation": "opentelemetry-instrumentation-mysqlclient==0.52b1",
137
+ "instrumentation": "opentelemetry-instrumentation-mysqlclient==0.53b0",
134
138
  },
135
139
  {
136
140
  "library": "pika >= 0.12.0",
137
- "instrumentation": "opentelemetry-instrumentation-pika==0.52b1",
141
+ "instrumentation": "opentelemetry-instrumentation-pika==0.53b0",
138
142
  },
139
143
  {
140
144
  "library": "psycopg >= 3.1.0",
141
- "instrumentation": "opentelemetry-instrumentation-psycopg==0.52b1",
145
+ "instrumentation": "opentelemetry-instrumentation-psycopg==0.53b0",
142
146
  },
143
147
  {
144
148
  "library": "psycopg2 >= 2.7.3.1",
145
- "instrumentation": "opentelemetry-instrumentation-psycopg2==0.52b1",
149
+ "instrumentation": "opentelemetry-instrumentation-psycopg2==0.53b0",
146
150
  },
147
151
  {
148
152
  "library": "psycopg2-binary >= 2.7.3.1",
149
- "instrumentation": "opentelemetry-instrumentation-psycopg2==0.52b1",
153
+ "instrumentation": "opentelemetry-instrumentation-psycopg2==0.53b0",
150
154
  },
151
155
  {
152
156
  "library": "pymemcache >= 1.3.5, < 5",
153
- "instrumentation": "opentelemetry-instrumentation-pymemcache==0.52b1",
157
+ "instrumentation": "opentelemetry-instrumentation-pymemcache==0.53b0",
154
158
  },
155
159
  {
156
160
  "library": "pymongo >= 3.1, < 5.0",
157
- "instrumentation": "opentelemetry-instrumentation-pymongo==0.52b1",
161
+ "instrumentation": "opentelemetry-instrumentation-pymongo==0.53b0",
158
162
  },
159
163
  {
160
164
  "library": "pymssql >= 2.1.5, < 3",
161
- "instrumentation": "opentelemetry-instrumentation-pymssql==0.52b1",
165
+ "instrumentation": "opentelemetry-instrumentation-pymssql==0.53b0",
162
166
  },
163
167
  {
164
168
  "library": "PyMySQL < 2",
165
- "instrumentation": "opentelemetry-instrumentation-pymysql==0.52b1",
169
+ "instrumentation": "opentelemetry-instrumentation-pymysql==0.53b0",
166
170
  },
167
171
  {
168
172
  "library": "pyramid >= 1.7",
169
- "instrumentation": "opentelemetry-instrumentation-pyramid==0.52b1",
173
+ "instrumentation": "opentelemetry-instrumentation-pyramid==0.53b0",
170
174
  },
171
175
  {
172
176
  "library": "redis >= 2.6",
173
- "instrumentation": "opentelemetry-instrumentation-redis==0.52b1",
177
+ "instrumentation": "opentelemetry-instrumentation-redis==0.53b0",
174
178
  },
175
179
  {
176
180
  "library": "remoulade >= 0.50",
177
- "instrumentation": "opentelemetry-instrumentation-remoulade==0.52b1",
181
+ "instrumentation": "opentelemetry-instrumentation-remoulade==0.53b0",
178
182
  },
179
183
  {
180
184
  "library": "requests ~= 2.0",
181
- "instrumentation": "opentelemetry-instrumentation-requests==0.52b1",
185
+ "instrumentation": "opentelemetry-instrumentation-requests==0.53b0",
182
186
  },
183
187
  {
184
188
  "library": "sqlalchemy >= 1.0.0, < 2.1.0",
185
- "instrumentation": "opentelemetry-instrumentation-sqlalchemy==0.52b1",
189
+ "instrumentation": "opentelemetry-instrumentation-sqlalchemy==0.53b0",
186
190
  },
187
191
  {
188
192
  "library": "starlette >= 0.13, <0.15",
189
- "instrumentation": "opentelemetry-instrumentation-starlette==0.52b1",
193
+ "instrumentation": "opentelemetry-instrumentation-starlette==0.53b0",
190
194
  },
191
195
  {
192
196
  "library": "psutil >= 5",
193
- "instrumentation": "opentelemetry-instrumentation-system-metrics==0.52b1",
197
+ "instrumentation": "opentelemetry-instrumentation-system-metrics==0.53b0",
194
198
  },
195
199
  {
196
200
  "library": "tornado >= 5.1.1",
197
- "instrumentation": "opentelemetry-instrumentation-tornado==0.52b1",
201
+ "instrumentation": "opentelemetry-instrumentation-tornado==0.53b0",
198
202
  },
199
203
  {
200
204
  "library": "tortoise-orm >= 0.17.0",
201
- "instrumentation": "opentelemetry-instrumentation-tortoiseorm==0.52b1",
205
+ "instrumentation": "opentelemetry-instrumentation-tortoiseorm==0.53b0",
202
206
  },
203
207
  {
204
208
  "library": "pydantic >= 1.10.2",
205
- "instrumentation": "opentelemetry-instrumentation-tortoiseorm==0.52b1",
209
+ "instrumentation": "opentelemetry-instrumentation-tortoiseorm==0.53b0",
206
210
  },
207
211
  {
208
212
  "library": "urllib3 >= 1.0.0, < 3.0.0",
209
- "instrumentation": "opentelemetry-instrumentation-urllib3==0.52b1",
213
+ "instrumentation": "opentelemetry-instrumentation-urllib3==0.53b0",
210
214
  },
211
215
  ]
212
216
  default_instrumentations = [
213
- "opentelemetry-instrumentation-asyncio==0.52b1",
214
- "opentelemetry-instrumentation-dbapi==0.52b1",
215
- "opentelemetry-instrumentation-logging==0.52b1",
216
- "opentelemetry-instrumentation-sqlite3==0.52b1",
217
- "opentelemetry-instrumentation-threading==0.52b1",
218
- "opentelemetry-instrumentation-urllib==0.52b1",
219
- "opentelemetry-instrumentation-wsgi==0.52b1",
217
+ "opentelemetry-instrumentation-asyncio==0.53b0",
218
+ "opentelemetry-instrumentation-dbapi==0.53b0",
219
+ "opentelemetry-instrumentation-logging==0.53b0",
220
+ "opentelemetry-instrumentation-sqlite3==0.53b0",
221
+ "opentelemetry-instrumentation-threading==0.53b0",
222
+ "opentelemetry-instrumentation-urllib==0.53b0",
223
+ "opentelemetry-instrumentation-wsgi==0.53b0",
220
224
  ]
@@ -20,7 +20,6 @@ from typing import Collection
20
20
  from packaging.requirements import InvalidRequirement, Requirement
21
21
 
22
22
  from opentelemetry.util._importlib_metadata import (
23
- Distribution,
24
23
  PackageNotFoundError,
25
24
  version,
26
25
  )
@@ -40,23 +39,14 @@ class DependencyConflict:
40
39
  return f'DependencyConflict: requested: "{self.required}" but found: "{self.found}"'
41
40
 
42
41
 
43
- def get_dist_dependency_conflicts(
44
- dist: Distribution,
45
- ) -> DependencyConflict | None:
46
- instrumentation_deps = []
47
- extra = "extra"
48
- instruments = "instruments"
49
- instruments_marker = {extra: instruments}
50
- if dist.requires:
51
- for dep in dist.requires:
52
- if extra not in dep or instruments not in dep:
53
- continue
54
-
55
- req = Requirement(dep)
56
- if req.marker.evaluate(instruments_marker):
57
- instrumentation_deps.append(req)
58
-
59
- return get_dependency_conflicts(instrumentation_deps)
42
+ class DependencyConflictError(Exception):
43
+ conflict: DependencyConflict
44
+
45
+ def __init__(self, conflict: DependencyConflict):
46
+ self.conflict = conflict
47
+
48
+ def __str__(self):
49
+ return str(self.conflict)
60
50
 
61
51
 
62
52
  def get_dependency_conflicts(
@@ -28,6 +28,7 @@ from opentelemetry.instrumentation._semconv import (
28
28
  )
29
29
  from opentelemetry.instrumentation.dependencies import (
30
30
  DependencyConflict,
31
+ DependencyConflictError,
31
32
  get_dependency_conflicts,
32
33
  )
33
34
 
@@ -104,10 +105,15 @@ class BaseInstrumentor(ABC):
104
105
 
105
106
  # check if instrumentor has any missing or conflicting dependencies
106
107
  skip_dep_check = kwargs.pop("skip_dep_check", False)
108
+ raise_exception_on_conflict = kwargs.pop(
109
+ "raise_exception_on_conflict", False
110
+ )
107
111
  if not skip_dep_check:
108
112
  conflict = self._check_dependency_conflicts()
109
113
  if conflict:
110
114
  _LOG.error(conflict)
115
+ if raise_exception_on_conflict:
116
+ raise DependencyConflictError(conflict)
111
117
  return None
112
118
 
113
119
  # initialize semantic conventions opt-in if needed
@@ -23,7 +23,7 @@ def _add_sql_comment(sql, **meta) -> str:
23
23
  meta.update(**_add_framework_tags())
24
24
  comment = _generate_sql_comment(**meta)
25
25
  sql = sql.rstrip()
26
- if sql[-1] == ";":
26
+ if sql.endswith(";"):
27
27
  sql = sql[:-1] + comment + ";"
28
28
  else:
29
29
  sql = sql + comment
@@ -12,4 +12,4 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
- __version__ = "0.52b1"
15
+ __version__ = "0.53b0"
@@ -17,13 +17,16 @@ from unittest import TestCase
17
17
  from unittest.mock import Mock, call, patch
18
18
 
19
19
  from opentelemetry.instrumentation.auto_instrumentation import _load
20
+ from opentelemetry.instrumentation.dependencies import (
21
+ DependencyConflict,
22
+ DependencyConflictError,
23
+ )
20
24
  from opentelemetry.instrumentation.environment_variables import (
21
25
  OTEL_PYTHON_CONFIGURATOR,
22
26
  OTEL_PYTHON_DISABLED_INSTRUMENTATIONS,
23
27
  OTEL_PYTHON_DISTRO,
24
28
  )
25
29
  from opentelemetry.instrumentation.version import __version__
26
- from opentelemetry.util._importlib_metadata import EntryPoint, entry_points
27
30
 
28
31
 
29
32
  class TestLoad(TestCase):
@@ -200,17 +203,20 @@ class TestLoad(TestCase):
200
203
  # Confirm method raises exception if it fails to load a distro.
201
204
  self.assertRaises(Exception, _load._load_distro)
202
205
 
206
+ @staticmethod
207
+ def _instrumentation_failed_to_load_call(entry_point, dependency_conflict):
208
+ return call(
209
+ "Skipping instrumentation %s: %s", entry_point, dependency_conflict
210
+ )
211
+
203
212
  @patch.dict(
204
213
  "os.environ",
205
214
  {OTEL_PYTHON_DISABLED_INSTRUMENTATIONS: " instr1 , instr3 "},
206
215
  )
207
- @patch(
208
- "opentelemetry.instrumentation.auto_instrumentation._load.get_dist_dependency_conflicts"
209
- )
210
216
  @patch(
211
217
  "opentelemetry.instrumentation.auto_instrumentation._load.entry_points"
212
218
  )
213
- def test_load_instrumentors(self, iter_mock, dep_mock):
219
+ def test_load_instrumentors(self, iter_mock):
214
220
  # Mock opentelemetry_pre_instrument entry points
215
221
  # pylint: disable=too-many-locals
216
222
  pre_ep_mock1 = Mock()
@@ -255,8 +261,6 @@ class TestLoad(TestCase):
255
261
  (ep_mock1, ep_mock2, ep_mock3, ep_mock4),
256
262
  (post_ep_mock1, post_ep_mock2),
257
263
  ]
258
- # No dependency conflict
259
- dep_mock.return_value = None
260
264
  _load._load_instrumentors(distro_mock)
261
265
  # All opentelemetry_pre_instrument entry points should be loaded
262
266
  pre_mock1.assert_called_once()
@@ -265,8 +269,8 @@ class TestLoad(TestCase):
265
269
  # Only non-disabled instrumentations should be loaded
266
270
  distro_mock.load_instrumentor.assert_has_calls(
267
271
  [
268
- call(ep_mock2, skip_dep_check=True),
269
- call(ep_mock4, skip_dep_check=True),
272
+ call(ep_mock2, raise_exception_on_conflict=True),
273
+ call(ep_mock4, raise_exception_on_conflict=True),
270
274
  ]
271
275
  )
272
276
  self.assertEqual(distro_mock.load_instrumentor.call_count, 2)
@@ -278,13 +282,11 @@ class TestLoad(TestCase):
278
282
  "os.environ",
279
283
  {OTEL_PYTHON_DISABLED_INSTRUMENTATIONS: " instr1 , instr3 "},
280
284
  )
281
- @patch(
282
- "opentelemetry.instrumentation.auto_instrumentation._load.get_dist_dependency_conflicts"
283
- )
285
+ @patch("opentelemetry.instrumentation.auto_instrumentation._load._logger")
284
286
  @patch(
285
287
  "opentelemetry.instrumentation.auto_instrumentation._load.entry_points"
286
288
  )
287
- def test_load_instrumentors_dep_conflict(self, iter_mock, dep_mock): # pylint: disable=no-self-use
289
+ def test_load_instrumentors_dep_conflict(self, iter_mock, mock_logger): # pylint: disable=no-self-use
288
290
  ep_mock1 = Mock()
289
291
  ep_mock1.name = "instr1"
290
292
 
@@ -297,27 +299,38 @@ class TestLoad(TestCase):
297
299
  ep_mock4 = Mock()
298
300
  ep_mock4.name = "instr4"
299
301
 
302
+ dependency_conflict = DependencyConflict("1.2.3", None)
303
+
300
304
  distro_mock = Mock()
305
+ distro_mock.load_instrumentor.side_effect = [
306
+ None,
307
+ DependencyConflictError(dependency_conflict),
308
+ ]
301
309
 
302
- iter_mock.return_value = (ep_mock1, ep_mock2, ep_mock3, ep_mock4)
303
310
  # If a dependency conflict is raised, that instrumentation should not be loaded, but others still should.
304
- dep_mock.side_effect = [None, "DependencyConflict"]
311
+ # In this case, ep_mock4 will fail to load and ep_mock2 will succeed. (ep_mock1 and ep_mock3 are disabled)
312
+ iter_mock.return_value = (ep_mock1, ep_mock2, ep_mock3, ep_mock4)
305
313
  _load._load_instrumentors(distro_mock)
306
314
  distro_mock.load_instrumentor.assert_has_calls(
307
315
  [
308
- call(ep_mock2, skip_dep_check=True),
316
+ call(ep_mock2, raise_exception_on_conflict=True),
317
+ call(ep_mock4, raise_exception_on_conflict=True),
318
+ ]
319
+ )
320
+ assert distro_mock.load_instrumentor.call_count == 2
321
+ mock_logger.debug.assert_has_calls(
322
+ [
323
+ self._instrumentation_failed_to_load_call(
324
+ ep_mock4.name, dependency_conflict
325
+ )
309
326
  ]
310
327
  )
311
- distro_mock.load_instrumentor.assert_called_once()
312
328
 
313
- @patch(
314
- "opentelemetry.instrumentation.auto_instrumentation._load.get_dist_dependency_conflicts"
315
- )
316
329
  @patch(
317
330
  "opentelemetry.instrumentation.auto_instrumentation._load.entry_points"
318
331
  )
319
332
  def test_load_instrumentors_import_error_does_not_stop_everything(
320
- self, iter_mock, dep_mock
333
+ self, iter_mock
321
334
  ):
322
335
  ep_mock1 = Mock(name="instr1")
323
336
  ep_mock2 = Mock(name="instr2")
@@ -331,25 +344,21 @@ class TestLoad(TestCase):
331
344
  (ep_mock1, ep_mock2),
332
345
  (),
333
346
  ]
334
- dep_mock.return_value = None
335
347
 
336
348
  _load._load_instrumentors(distro_mock)
337
349
 
338
350
  distro_mock.load_instrumentor.assert_has_calls(
339
351
  [
340
- call(ep_mock1, skip_dep_check=True),
341
- call(ep_mock2, skip_dep_check=True),
352
+ call(ep_mock1, raise_exception_on_conflict=True),
353
+ call(ep_mock2, raise_exception_on_conflict=True),
342
354
  ]
343
355
  )
344
356
  self.assertEqual(distro_mock.load_instrumentor.call_count, 2)
345
357
 
346
- @patch(
347
- "opentelemetry.instrumentation.auto_instrumentation._load.get_dist_dependency_conflicts"
348
- )
349
358
  @patch(
350
359
  "opentelemetry.instrumentation.auto_instrumentation._load.entry_points"
351
360
  )
352
- def test_load_instrumentors_raises_exception(self, iter_mock, dep_mock):
361
+ def test_load_instrumentors_raises_exception(self, iter_mock):
353
362
  ep_mock1 = Mock(name="instr1")
354
363
  ep_mock2 = Mock(name="instr2")
355
364
 
@@ -362,14 +371,13 @@ class TestLoad(TestCase):
362
371
  (ep_mock1, ep_mock2),
363
372
  (),
364
373
  ]
365
- dep_mock.return_value = None
366
374
 
367
375
  with self.assertRaises(ValueError):
368
376
  _load._load_instrumentors(distro_mock)
369
377
 
370
378
  distro_mock.load_instrumentor.assert_has_calls(
371
379
  [
372
- call(ep_mock1, skip_dep_check=True),
380
+ call(ep_mock1, raise_exception_on_conflict=True),
373
381
  ]
374
382
  )
375
383
  self.assertEqual(distro_mock.load_instrumentor.call_count, 1)
@@ -379,31 +387,3 @@ class TestLoad(TestCase):
379
387
  _load._load_instrumentors(distro_mock)
380
388
  # this has no specific assert because it is run for every instrumentation
381
389
  self.assertTrue(distro_mock)
382
-
383
- def test_entry_point_dist_finder(self):
384
- entry_point_finder = _load._EntryPointDistFinder()
385
- self.assertTrue(entry_point_finder._mapping)
386
- entry_point = list(
387
- entry_points(group="opentelemetry_environment_variables")
388
- )[0]
389
- self.assertTrue(entry_point)
390
- self.assertTrue(entry_point.dist)
391
-
392
- # this will not hit cache
393
- entry_point_dist = entry_point_finder.dist_for(entry_point)
394
- self.assertTrue(entry_point_dist)
395
- # dist are not comparable so we are sure we are not hitting the cache
396
- self.assertEqual(entry_point.dist, entry_point_dist)
397
-
398
- # this will hit cache
399
- entry_point_without_dist = EntryPoint(
400
- name=entry_point.name,
401
- group=entry_point.group,
402
- value=entry_point.value,
403
- )
404
- self.assertIsNone(entry_point_without_dist.dist)
405
- new_entry_point_dist = entry_point_finder.dist_for(
406
- entry_point_without_dist
407
- )
408
- # dist are not comparable, being truthy is enough
409
- self.assertTrue(new_entry_point_dist)
@@ -20,10 +20,8 @@ from packaging.requirements import Requirement
20
20
  from opentelemetry.instrumentation.dependencies import (
21
21
  DependencyConflict,
22
22
  get_dependency_conflicts,
23
- get_dist_dependency_conflicts,
24
23
  )
25
24
  from opentelemetry.test.test_base import TestBase
26
- from opentelemetry.util._importlib_metadata import Distribution
27
25
 
28
26
 
29
27
  class TestDependencyConflicts(TestBase):
@@ -64,41 +62,3 @@ class TestDependencyConflicts(TestBase):
64
62
  str(conflict),
65
63
  f'DependencyConflict: requested: "pytest == 5000" but found: "pytest {pytest.__version__}"',
66
64
  )
67
-
68
- def test_get_dist_dependency_conflicts(self):
69
- class MockDistribution(Distribution):
70
- def locate_file(self, path):
71
- pass
72
-
73
- def read_text(self, filename):
74
- pass
75
-
76
- @property
77
- def requires(self):
78
- return ['test-pkg ~= 1.0; extra == "instruments"']
79
-
80
- dist = MockDistribution()
81
-
82
- conflict = get_dist_dependency_conflicts(dist)
83
- self.assertTrue(conflict is not None)
84
- self.assertTrue(isinstance(conflict, DependencyConflict))
85
- self.assertEqual(
86
- str(conflict),
87
- 'DependencyConflict: requested: "test-pkg~=1.0; extra == "instruments"" but found: "None"',
88
- )
89
-
90
- def test_get_dist_dependency_conflicts_requires_none(self):
91
- class MockDistribution(Distribution):
92
- def locate_file(self, path):
93
- pass
94
-
95
- def read_text(self, filename):
96
- pass
97
-
98
- @property
99
- def requires(self):
100
- return None
101
-
102
- dist = MockDistribution()
103
- conflict = get_dist_dependency_conflicts(dist)
104
- self.assertTrue(conflict is None)
@@ -15,7 +15,12 @@
15
15
 
16
16
  from logging import WARNING
17
17
  from unittest import TestCase
18
+ from unittest.mock import patch
18
19
 
20
+ from opentelemetry.instrumentation.dependencies import (
21
+ DependencyConflict,
22
+ DependencyConflictError,
23
+ )
19
24
  from opentelemetry.instrumentation.instrumentor import BaseInstrumentor
20
25
 
21
26
 
@@ -48,3 +53,21 @@ class TestInstrumentor(TestCase):
48
53
 
49
54
  def test_singleton(self):
50
55
  self.assertIs(self.Instrumentor(), self.Instrumentor())
56
+
57
+ @patch(
58
+ "opentelemetry.instrumentation.instrumentor.BaseInstrumentor._check_dependency_conflicts"
59
+ )
60
+ def test_instrument_missing_dependency_raise(
61
+ self, mock__check_dependency_conflicts
62
+ ):
63
+ instrumentor = self.Instrumentor()
64
+
65
+ mock__check_dependency_conflicts.return_value = DependencyConflict(
66
+ "missing", "missing"
67
+ )
68
+
69
+ self.assertRaises(
70
+ DependencyConflictError,
71
+ instrumentor.instrument,
72
+ raise_exception_on_conflict=True,
73
+ )