opentelemetry-instrumentation 0.52b1__tar.gz → 0.53b1__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.53b1}/PKG-INFO +2 -2
  2. {opentelemetry_instrumentation-0.52b1 → opentelemetry_instrumentation-0.53b1}/pyproject.toml +1 -1
  3. {opentelemetry_instrumentation-0.52b1 → opentelemetry_instrumentation-0.53b1}/src/opentelemetry/instrumentation/_semconv.py +2 -1
  4. {opentelemetry_instrumentation-0.52b1 → opentelemetry_instrumentation-0.53b1}/src/opentelemetry/instrumentation/auto_instrumentation/_load.py +20 -43
  5. {opentelemetry_instrumentation-0.52b1 → opentelemetry_instrumentation-0.53b1}/src/opentelemetry/instrumentation/bootstrap_gen.py +57 -53
  6. {opentelemetry_instrumentation-0.52b1 → opentelemetry_instrumentation-0.53b1}/src/opentelemetry/instrumentation/dependencies.py +8 -18
  7. {opentelemetry_instrumentation-0.52b1 → opentelemetry_instrumentation-0.53b1}/src/opentelemetry/instrumentation/instrumentor.py +6 -0
  8. {opentelemetry_instrumentation-0.52b1 → opentelemetry_instrumentation-0.53b1}/src/opentelemetry/instrumentation/sqlcommenter_utils.py +1 -1
  9. {opentelemetry_instrumentation-0.52b1 → opentelemetry_instrumentation-0.53b1}/src/opentelemetry/instrumentation/version.py +1 -1
  10. {opentelemetry_instrumentation-0.52b1 → opentelemetry_instrumentation-0.53b1}/tests/auto_instrumentation/test_load.py +85 -58
  11. {opentelemetry_instrumentation-0.52b1 → opentelemetry_instrumentation-0.53b1}/tests/test_dependencies.py +0 -40
  12. {opentelemetry_instrumentation-0.52b1 → opentelemetry_instrumentation-0.53b1}/tests/test_instrumentor.py +23 -0
  13. {opentelemetry_instrumentation-0.52b1 → opentelemetry_instrumentation-0.53b1}/.gitignore +0 -0
  14. {opentelemetry_instrumentation-0.52b1 → opentelemetry_instrumentation-0.53b1}/LICENSE +0 -0
  15. {opentelemetry_instrumentation-0.52b1 → opentelemetry_instrumentation-0.53b1}/README.rst +0 -0
  16. {opentelemetry_instrumentation-0.52b1 → opentelemetry_instrumentation-0.53b1}/src/opentelemetry/instrumentation/auto_instrumentation/__init__.py +0 -0
  17. {opentelemetry_instrumentation-0.52b1 → opentelemetry_instrumentation-0.53b1}/src/opentelemetry/instrumentation/auto_instrumentation/sitecustomize.py +0 -0
  18. {opentelemetry_instrumentation-0.52b1 → opentelemetry_instrumentation-0.53b1}/src/opentelemetry/instrumentation/bootstrap.py +0 -0
  19. {opentelemetry_instrumentation-0.52b1 → opentelemetry_instrumentation-0.53b1}/src/opentelemetry/instrumentation/distro.py +0 -0
  20. {opentelemetry_instrumentation-0.52b1 → opentelemetry_instrumentation-0.53b1}/src/opentelemetry/instrumentation/environment_variables.py +0 -0
  21. {opentelemetry_instrumentation-0.52b1 → opentelemetry_instrumentation-0.53b1}/src/opentelemetry/instrumentation/propagators.py +0 -0
  22. {opentelemetry_instrumentation-0.52b1 → opentelemetry_instrumentation-0.53b1}/src/opentelemetry/instrumentation/py.typed +0 -0
  23. {opentelemetry_instrumentation-0.52b1 → opentelemetry_instrumentation-0.53b1}/src/opentelemetry/instrumentation/utils.py +0 -0
  24. {opentelemetry_instrumentation-0.52b1 → opentelemetry_instrumentation-0.53b1}/tests/__init__.py +0 -0
  25. {opentelemetry_instrumentation-0.52b1 → opentelemetry_instrumentation-0.53b1}/tests/auto_instrumentation/test_initialize.py +0 -0
  26. {opentelemetry_instrumentation-0.52b1 → opentelemetry_instrumentation-0.53b1}/tests/auto_instrumentation/test_run.py +0 -0
  27. {opentelemetry_instrumentation-0.52b1 → opentelemetry_instrumentation-0.53b1}/tests/auto_instrumentation/test_sitecustomize.py +0 -0
  28. {opentelemetry_instrumentation-0.52b1 → opentelemetry_instrumentation-0.53b1}/tests/test_bootstrap.py +0 -0
  29. {opentelemetry_instrumentation-0.52b1 → opentelemetry_instrumentation-0.53b1}/tests/test_distro.py +0 -0
  30. {opentelemetry_instrumentation-0.52b1 → opentelemetry_instrumentation-0.53b1}/tests/test_propagators.py +0 -0
  31. {opentelemetry_instrumentation-0.52b1 → opentelemetry_instrumentation-0.53b1}/tests/test_semconv.py +0 -0
  32. {opentelemetry_instrumentation-0.52b1 → opentelemetry_instrumentation-0.53b1}/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.53b1
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.53b1
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.53b1",
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,25 @@ 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
85
+ except ModuleNotFoundError as exc:
86
+ # ModuleNotFoundError is raised when the library is not installed
87
+ # and the instrumentation is not required to be loaded.
88
+ # See https://github.com/open-telemetry/opentelemetry-python-contrib/issues/3421
89
+ _logger.debug(
90
+ "Skipping instrumentation %s: %s", entry_point.name, exc.msg
91
+ )
92
+ continue
116
93
  except ImportError:
117
94
  # in scenarios using the kubernetes operator to do autoinstrumentation some
118
95
  # 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.53b1",
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.53b1",
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.53b1",
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.53b1",
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.53b1",
46
46
  },
47
47
  {
48
48
  "library": "asgiref ~= 3.0",
49
- "instrumentation": "opentelemetry-instrumentation-asgi==0.52b1",
49
+ "instrumentation": "opentelemetry-instrumentation-asgi==0.53b1",
50
+ },
51
+ {
52
+ "library": "asyncclick ~= 8.0",
53
+ "instrumentation": "opentelemetry-instrumentation-asyncclick==0.53b1",
50
54
  },
51
55
  {
52
56
  "library": "asyncpg >= 0.12.0",
53
- "instrumentation": "opentelemetry-instrumentation-asyncpg==0.52b1",
57
+ "instrumentation": "opentelemetry-instrumentation-asyncpg==0.53b1",
54
58
  },
55
59
  {
56
60
  "library": "boto~=2.0",
57
- "instrumentation": "opentelemetry-instrumentation-boto==0.52b1",
61
+ "instrumentation": "opentelemetry-instrumentation-boto==0.53b1",
58
62
  },
59
63
  {
60
64
  "library": "boto3 ~= 1.0",
61
- "instrumentation": "opentelemetry-instrumentation-boto3sqs==0.52b1",
65
+ "instrumentation": "opentelemetry-instrumentation-boto3sqs==0.53b1",
62
66
  },
63
67
  {
64
68
  "library": "botocore ~= 1.0",
65
- "instrumentation": "opentelemetry-instrumentation-botocore==0.52b1",
69
+ "instrumentation": "opentelemetry-instrumentation-botocore==0.53b1",
66
70
  },
67
71
  {
68
72
  "library": "cassandra-driver ~= 3.25",
69
- "instrumentation": "opentelemetry-instrumentation-cassandra==0.52b1",
73
+ "instrumentation": "opentelemetry-instrumentation-cassandra==0.53b1",
70
74
  },
71
75
  {
72
76
  "library": "scylla-driver ~= 3.25",
73
- "instrumentation": "opentelemetry-instrumentation-cassandra==0.52b1",
77
+ "instrumentation": "opentelemetry-instrumentation-cassandra==0.53b1",
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.53b1",
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.53b1",
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.53b1",
86
90
  },
87
91
  {
88
92
  "library": "django >= 1.10",
89
- "instrumentation": "opentelemetry-instrumentation-django==0.52b1",
93
+ "instrumentation": "opentelemetry-instrumentation-django==0.53b1",
90
94
  },
91
95
  {
92
96
  "library": "elasticsearch >= 6.0",
93
- "instrumentation": "opentelemetry-instrumentation-elasticsearch==0.52b1",
97
+ "instrumentation": "opentelemetry-instrumentation-elasticsearch==0.53b1",
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.53b1",
98
102
  },
99
103
  {
100
104
  "library": "fastapi ~= 0.58",
101
- "instrumentation": "opentelemetry-instrumentation-fastapi==0.52b1",
105
+ "instrumentation": "opentelemetry-instrumentation-fastapi==0.53b1",
102
106
  },
103
107
  {
104
108
  "library": "flask >= 1.0",
105
- "instrumentation": "opentelemetry-instrumentation-flask==0.52b1",
109
+ "instrumentation": "opentelemetry-instrumentation-flask==0.53b1",
106
110
  },
107
111
  {
108
112
  "library": "grpcio >= 1.42.0",
109
- "instrumentation": "opentelemetry-instrumentation-grpc==0.52b1",
113
+ "instrumentation": "opentelemetry-instrumentation-grpc==0.53b1",
110
114
  },
111
115
  {
112
116
  "library": "httpx >= 0.18.0",
113
- "instrumentation": "opentelemetry-instrumentation-httpx==0.52b1",
117
+ "instrumentation": "opentelemetry-instrumentation-httpx==0.53b1",
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.53b1",
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.53b1",
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.53b1",
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.53b1",
130
134
  },
131
135
  {
132
136
  "library": "mysqlclient < 3",
133
- "instrumentation": "opentelemetry-instrumentation-mysqlclient==0.52b1",
137
+ "instrumentation": "opentelemetry-instrumentation-mysqlclient==0.53b1",
134
138
  },
135
139
  {
136
140
  "library": "pika >= 0.12.0",
137
- "instrumentation": "opentelemetry-instrumentation-pika==0.52b1",
141
+ "instrumentation": "opentelemetry-instrumentation-pika==0.53b1",
138
142
  },
139
143
  {
140
144
  "library": "psycopg >= 3.1.0",
141
- "instrumentation": "opentelemetry-instrumentation-psycopg==0.52b1",
145
+ "instrumentation": "opentelemetry-instrumentation-psycopg==0.53b1",
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.53b1",
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.53b1",
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.53b1",
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.53b1",
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.53b1",
162
166
  },
163
167
  {
164
168
  "library": "PyMySQL < 2",
165
- "instrumentation": "opentelemetry-instrumentation-pymysql==0.52b1",
169
+ "instrumentation": "opentelemetry-instrumentation-pymysql==0.53b1",
166
170
  },
167
171
  {
168
172
  "library": "pyramid >= 1.7",
169
- "instrumentation": "opentelemetry-instrumentation-pyramid==0.52b1",
173
+ "instrumentation": "opentelemetry-instrumentation-pyramid==0.53b1",
170
174
  },
171
175
  {
172
176
  "library": "redis >= 2.6",
173
- "instrumentation": "opentelemetry-instrumentation-redis==0.52b1",
177
+ "instrumentation": "opentelemetry-instrumentation-redis==0.53b1",
174
178
  },
175
179
  {
176
180
  "library": "remoulade >= 0.50",
177
- "instrumentation": "opentelemetry-instrumentation-remoulade==0.52b1",
181
+ "instrumentation": "opentelemetry-instrumentation-remoulade==0.53b1",
178
182
  },
179
183
  {
180
184
  "library": "requests ~= 2.0",
181
- "instrumentation": "opentelemetry-instrumentation-requests==0.52b1",
185
+ "instrumentation": "opentelemetry-instrumentation-requests==0.53b1",
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.53b1",
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.53b1",
190
194
  },
191
195
  {
192
196
  "library": "psutil >= 5",
193
- "instrumentation": "opentelemetry-instrumentation-system-metrics==0.52b1",
197
+ "instrumentation": "opentelemetry-instrumentation-system-metrics==0.53b1",
194
198
  },
195
199
  {
196
200
  "library": "tornado >= 5.1.1",
197
- "instrumentation": "opentelemetry-instrumentation-tornado==0.52b1",
201
+ "instrumentation": "opentelemetry-instrumentation-tornado==0.53b1",
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.53b1",
202
206
  },
203
207
  {
204
208
  "library": "pydantic >= 1.10.2",
205
- "instrumentation": "opentelemetry-instrumentation-tortoiseorm==0.52b1",
209
+ "instrumentation": "opentelemetry-instrumentation-tortoiseorm==0.53b1",
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.53b1",
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.53b1",
218
+ "opentelemetry-instrumentation-dbapi==0.53b1",
219
+ "opentelemetry-instrumentation-logging==0.53b1",
220
+ "opentelemetry-instrumentation-sqlite3==0.53b1",
221
+ "opentelemetry-instrumentation-threading==0.53b1",
222
+ "opentelemetry-instrumentation-urllib==0.53b1",
223
+ "opentelemetry-instrumentation-wsgi==0.53b1",
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.53b1"
@@ -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,39 @@ 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
- )
329
+ @patch("opentelemetry.instrumentation.auto_instrumentation._load._logger")
316
330
  @patch(
317
331
  "opentelemetry.instrumentation.auto_instrumentation._load.entry_points"
318
332
  )
319
333
  def test_load_instrumentors_import_error_does_not_stop_everything(
320
- self, iter_mock, dep_mock
334
+ self, iter_mock, mock_logger
321
335
  ):
322
336
  ep_mock1 = Mock(name="instr1")
323
337
  ep_mock2 = Mock(name="instr2")
@@ -331,25 +345,27 @@ class TestLoad(TestCase):
331
345
  (ep_mock1, ep_mock2),
332
346
  (),
333
347
  ]
334
- dep_mock.return_value = None
335
348
 
336
349
  _load._load_instrumentors(distro_mock)
337
350
 
338
351
  distro_mock.load_instrumentor.assert_has_calls(
339
352
  [
340
- call(ep_mock1, skip_dep_check=True),
341
- call(ep_mock2, skip_dep_check=True),
353
+ call(ep_mock1, raise_exception_on_conflict=True),
354
+ call(ep_mock2, raise_exception_on_conflict=True),
342
355
  ]
343
356
  )
344
357
  self.assertEqual(distro_mock.load_instrumentor.call_count, 2)
358
+ mock_logger.exception.assert_any_call(
359
+ "Importing of %s failed, skipping it",
360
+ ep_mock1.name,
361
+ )
362
+
363
+ mock_logger.debug.assert_any_call("Instrumented %s", ep_mock2.name)
345
364
 
346
- @patch(
347
- "opentelemetry.instrumentation.auto_instrumentation._load.get_dist_dependency_conflicts"
348
- )
349
365
  @patch(
350
366
  "opentelemetry.instrumentation.auto_instrumentation._load.entry_points"
351
367
  )
352
- def test_load_instrumentors_raises_exception(self, iter_mock, dep_mock):
368
+ def test_load_instrumentors_raises_exception(self, iter_mock):
353
369
  ep_mock1 = Mock(name="instr1")
354
370
  ep_mock2 = Mock(name="instr2")
355
371
 
@@ -362,48 +378,59 @@ class TestLoad(TestCase):
362
378
  (ep_mock1, ep_mock2),
363
379
  (),
364
380
  ]
365
- dep_mock.return_value = None
366
381
 
367
382
  with self.assertRaises(ValueError):
368
383
  _load._load_instrumentors(distro_mock)
369
384
 
370
385
  distro_mock.load_instrumentor.assert_has_calls(
371
386
  [
372
- call(ep_mock1, skip_dep_check=True),
387
+ call(ep_mock1, raise_exception_on_conflict=True),
373
388
  ]
374
389
  )
375
390
  self.assertEqual(distro_mock.load_instrumentor.call_count, 1)
376
391
 
377
- def test_load_instrumentors_no_entry_point_mocks(self):
392
+ @patch("opentelemetry.instrumentation.auto_instrumentation._load._logger")
393
+ @patch(
394
+ "opentelemetry.instrumentation.auto_instrumentation._load.entry_points"
395
+ )
396
+ def test_load_instrumentors_module_not_found_error(
397
+ self, iter_mock, mock_logger
398
+ ):
399
+ ep_mock1 = Mock()
400
+ ep_mock1.name = "instr1"
401
+
402
+ ep_mock2 = Mock()
403
+ ep_mock2.name = "instr2"
404
+
378
405
  distro_mock = Mock()
406
+
407
+ distro_mock.load_instrumentor.side_effect = [
408
+ ModuleNotFoundError("No module named 'fake_module'"),
409
+ None,
410
+ ]
411
+
412
+ iter_mock.side_effect = [(), (ep_mock1, ep_mock2), ()]
413
+
379
414
  _load._load_instrumentors(distro_mock)
380
- # this has no specific assert because it is run for every instrumentation
381
- self.assertTrue(distro_mock)
382
415
 
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,
416
+ distro_mock.load_instrumentor.assert_has_calls(
417
+ [
418
+ call(ep_mock1, raise_exception_on_conflict=True),
419
+ call(ep_mock2, raise_exception_on_conflict=True),
420
+ ]
403
421
  )
404
- self.assertIsNone(entry_point_without_dist.dist)
405
- new_entry_point_dist = entry_point_finder.dist_for(
406
- entry_point_without_dist
422
+ self.assertEqual(distro_mock.load_instrumentor.call_count, 2)
423
+
424
+ mock_logger.debug.assert_any_call(
425
+ "Skipping instrumentation %s: %s",
426
+ "instr1",
427
+ "No module named 'fake_module'",
407
428
  )
408
- # dist are not comparable, being truthy is enough
409
- self.assertTrue(new_entry_point_dist)
429
+
430
+ mock_logger.debug.assert_any_call("Instrumented %s", ep_mock2.name)
431
+
432
+ def test_load_instrumentors_no_entry_point_mocks(self):
433
+ distro_mock = Mock()
434
+ _load._load_instrumentors(distro_mock)
435
+ # this has no specific assert because it is run for every instrumentation
436
+ self.assertTrue(distro_mock)
@@ -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
+ )