opentelemetry-instrumentation 0.56b0__tar.gz → 0.58b0__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 (34) hide show
  1. {opentelemetry_instrumentation-0.56b0 → opentelemetry_instrumentation-0.58b0}/PKG-INFO +9 -3
  2. {opentelemetry_instrumentation-0.56b0 → opentelemetry_instrumentation-0.58b0}/README.rst +7 -1
  3. {opentelemetry_instrumentation-0.56b0 → opentelemetry_instrumentation-0.58b0}/pyproject.toml +1 -1
  4. {opentelemetry_instrumentation-0.56b0 → opentelemetry_instrumentation-0.58b0}/src/opentelemetry/instrumentation/_semconv.py +72 -48
  5. {opentelemetry_instrumentation-0.56b0 → opentelemetry_instrumentation-0.58b0}/src/opentelemetry/instrumentation/auto_instrumentation/__init__.py +29 -0
  6. {opentelemetry_instrumentation-0.56b0 → opentelemetry_instrumentation-0.58b0}/src/opentelemetry/instrumentation/auto_instrumentation/_load.py +48 -5
  7. {opentelemetry_instrumentation-0.56b0 → opentelemetry_instrumentation-0.58b0}/src/opentelemetry/instrumentation/bootstrap_gen.py +55 -55
  8. opentelemetry_instrumentation-0.58b0/src/opentelemetry/instrumentation/dependencies.py +187 -0
  9. {opentelemetry_instrumentation-0.56b0 → opentelemetry_instrumentation-0.58b0}/src/opentelemetry/instrumentation/environment_variables.py +7 -0
  10. {opentelemetry_instrumentation-0.56b0 → opentelemetry_instrumentation-0.58b0}/src/opentelemetry/instrumentation/utils.py +2 -1
  11. {opentelemetry_instrumentation-0.56b0 → opentelemetry_instrumentation-0.58b0}/src/opentelemetry/instrumentation/version.py +1 -1
  12. {opentelemetry_instrumentation-0.56b0 → opentelemetry_instrumentation-0.58b0}/tests/auto_instrumentation/test_initialize.py +27 -0
  13. {opentelemetry_instrumentation-0.56b0 → opentelemetry_instrumentation-0.58b0}/tests/auto_instrumentation/test_load.py +85 -27
  14. opentelemetry_instrumentation-0.58b0/tests/test_dependencies.py +279 -0
  15. {opentelemetry_instrumentation-0.56b0 → opentelemetry_instrumentation-0.58b0}/tests/test_semconv.py +22 -1
  16. opentelemetry_instrumentation-0.56b0/src/opentelemetry/instrumentation/dependencies.py +0 -76
  17. opentelemetry_instrumentation-0.56b0/tests/test_dependencies.py +0 -64
  18. {opentelemetry_instrumentation-0.56b0 → opentelemetry_instrumentation-0.58b0}/.gitignore +0 -0
  19. {opentelemetry_instrumentation-0.56b0 → opentelemetry_instrumentation-0.58b0}/LICENSE +0 -0
  20. {opentelemetry_instrumentation-0.56b0 → opentelemetry_instrumentation-0.58b0}/src/opentelemetry/instrumentation/auto_instrumentation/sitecustomize.py +0 -0
  21. {opentelemetry_instrumentation-0.56b0 → opentelemetry_instrumentation-0.58b0}/src/opentelemetry/instrumentation/bootstrap.py +0 -0
  22. {opentelemetry_instrumentation-0.56b0 → opentelemetry_instrumentation-0.58b0}/src/opentelemetry/instrumentation/distro.py +0 -0
  23. {opentelemetry_instrumentation-0.56b0 → opentelemetry_instrumentation-0.58b0}/src/opentelemetry/instrumentation/instrumentor.py +0 -0
  24. {opentelemetry_instrumentation-0.56b0 → opentelemetry_instrumentation-0.58b0}/src/opentelemetry/instrumentation/propagators.py +0 -0
  25. {opentelemetry_instrumentation-0.56b0 → opentelemetry_instrumentation-0.58b0}/src/opentelemetry/instrumentation/py.typed +0 -0
  26. {opentelemetry_instrumentation-0.56b0 → opentelemetry_instrumentation-0.58b0}/src/opentelemetry/instrumentation/sqlcommenter_utils.py +0 -0
  27. {opentelemetry_instrumentation-0.56b0 → opentelemetry_instrumentation-0.58b0}/tests/__init__.py +0 -0
  28. {opentelemetry_instrumentation-0.56b0 → opentelemetry_instrumentation-0.58b0}/tests/auto_instrumentation/test_run.py +0 -0
  29. {opentelemetry_instrumentation-0.56b0 → opentelemetry_instrumentation-0.58b0}/tests/auto_instrumentation/test_sitecustomize.py +0 -0
  30. {opentelemetry_instrumentation-0.56b0 → opentelemetry_instrumentation-0.58b0}/tests/test_bootstrap.py +0 -0
  31. {opentelemetry_instrumentation-0.56b0 → opentelemetry_instrumentation-0.58b0}/tests/test_distro.py +0 -0
  32. {opentelemetry_instrumentation-0.56b0 → opentelemetry_instrumentation-0.58b0}/tests/test_instrumentor.py +0 -0
  33. {opentelemetry_instrumentation-0.56b0 → opentelemetry_instrumentation-0.58b0}/tests/test_propagators.py +0 -0
  34. {opentelemetry_instrumentation-0.56b0 → opentelemetry_instrumentation-0.58b0}/tests/test_utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: opentelemetry-instrumentation
3
- Version: 0.56b0
3
+ Version: 0.58b0
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
@@ -19,7 +19,7 @@ Classifier: Programming Language :: Python :: 3.12
19
19
  Classifier: Programming Language :: Python :: 3.13
20
20
  Requires-Python: >=3.9
21
21
  Requires-Dist: opentelemetry-api~=1.4
22
- Requires-Dist: opentelemetry-semantic-conventions==0.56b0
22
+ Requires-Dist: opentelemetry-semantic-conventions==0.58b0
23
23
  Requires-Dist: packaging>=18.0
24
24
  Requires-Dist: wrapt<2.0.0,>=1.0.0
25
25
  Description-Content-Type: text/x-rst
@@ -130,7 +130,13 @@ check `here <https://opentelemetry-python.readthedocs.io/en/stable/index.html#in
130
130
  * ``OTEL_PYTHON_DISABLED_INSTRUMENTATIONS``
131
131
 
132
132
  If set by the user, opentelemetry-instrument will read this environment variable to disable specific instrumentations.
133
- e.g OTEL_PYTHON_DISABLED_INSTRUMENTATIONS = "requests,django"
133
+ e.g OTEL_PYTHON_DISABLED_INSTRUMENTATIONS="requests,django"
134
+
135
+ * ``OTEL_PYTHON_AUTO_INSTRUMENTATION_EXPERIMENTAL_GEVENT_PATCH``
136
+
137
+ If set by the user to `patch_all` , opentelemetry instrument will call the gevent monkeypatching method ``patch_all``.
138
+ This is considered experimental but can be useful to instrument gevent applications.
139
+ e.g OTEL_PYTHON_AUTO_INSTRUMENTATION_EXPERIMENTAL_GEVENT_PATCH=patch_all
134
140
 
135
141
 
136
142
  Examples
@@ -104,7 +104,13 @@ check `here <https://opentelemetry-python.readthedocs.io/en/stable/index.html#in
104
104
  * ``OTEL_PYTHON_DISABLED_INSTRUMENTATIONS``
105
105
 
106
106
  If set by the user, opentelemetry-instrument will read this environment variable to disable specific instrumentations.
107
- e.g OTEL_PYTHON_DISABLED_INSTRUMENTATIONS = "requests,django"
107
+ e.g OTEL_PYTHON_DISABLED_INSTRUMENTATIONS="requests,django"
108
+
109
+ * ``OTEL_PYTHON_AUTO_INSTRUMENTATION_EXPERIMENTAL_GEVENT_PATCH``
110
+
111
+ If set by the user to `patch_all` , opentelemetry instrument will call the gevent monkeypatching method ``patch_all``.
112
+ This is considered experimental but can be useful to instrument gevent applications.
113
+ e.g OTEL_PYTHON_AUTO_INSTRUMENTATION_EXPERIMENTAL_GEVENT_PATCH=patch_all
108
114
 
109
115
 
110
116
  Examples
@@ -26,7 +26,7 @@ classifiers = [
26
26
  ]
27
27
  dependencies = [
28
28
  "opentelemetry-api ~= 1.4",
29
- "opentelemetry-semantic-conventions == 0.56b0",
29
+ "opentelemetry-semantic-conventions == 0.58b0",
30
30
  "wrapt >= 1.0.0, < 2.0.0",
31
31
  "packaging >= 18.0",
32
32
  ]
@@ -17,6 +17,24 @@ import threading
17
17
  from enum import Enum
18
18
 
19
19
  from opentelemetry.instrumentation.utils import http_status_to_status_code
20
+ from opentelemetry.semconv._incubating.attributes.http_attributes import (
21
+ HTTP_FLAVOR,
22
+ HTTP_HOST,
23
+ HTTP_METHOD,
24
+ HTTP_SCHEME,
25
+ HTTP_SERVER_NAME,
26
+ HTTP_STATUS_CODE,
27
+ HTTP_TARGET,
28
+ HTTP_URL,
29
+ HTTP_USER_AGENT,
30
+ )
31
+ from opentelemetry.semconv._incubating.attributes.net_attributes import (
32
+ NET_HOST_NAME,
33
+ NET_HOST_PORT,
34
+ NET_PEER_IP,
35
+ NET_PEER_NAME,
36
+ NET_PEER_PORT,
37
+ )
20
38
  from opentelemetry.semconv.attributes.client_attributes import (
21
39
  CLIENT_ADDRESS,
22
40
  CLIENT_PORT,
@@ -44,7 +62,7 @@ from opentelemetry.semconv.attributes.url_attributes import (
44
62
  from opentelemetry.semconv.attributes.user_agent_attributes import (
45
63
  USER_AGENT_ORIGINAL,
46
64
  )
47
- from opentelemetry.semconv.trace import SpanAttributes
65
+ from opentelemetry.semconv.schemas import Schemas
48
66
  from opentelemetry.trace.status import Status, StatusCode
49
67
 
50
68
  # Values defined in milliseconds
@@ -87,13 +105,13 @@ HTTP_DURATION_HISTOGRAM_BUCKETS_NEW = (
87
105
  # These lists represent attributes for metrics that are currently supported
88
106
 
89
107
  _client_duration_attrs_old = [
90
- SpanAttributes.HTTP_STATUS_CODE,
91
- SpanAttributes.HTTP_HOST,
92
- SpanAttributes.NET_PEER_PORT,
93
- SpanAttributes.NET_PEER_NAME,
94
- SpanAttributes.HTTP_METHOD,
95
- SpanAttributes.HTTP_FLAVOR,
96
- SpanAttributes.HTTP_SCHEME,
108
+ HTTP_STATUS_CODE,
109
+ HTTP_HOST,
110
+ HTTP_METHOD,
111
+ HTTP_FLAVOR,
112
+ HTTP_SCHEME,
113
+ NET_PEER_PORT,
114
+ NET_PEER_NAME,
97
115
  ]
98
116
 
99
117
  _client_duration_attrs_new = [
@@ -108,14 +126,14 @@ _client_duration_attrs_new = [
108
126
  ]
109
127
 
110
128
  _server_duration_attrs_old = [
111
- SpanAttributes.HTTP_METHOD,
112
- SpanAttributes.HTTP_HOST,
113
- SpanAttributes.HTTP_SCHEME,
114
- SpanAttributes.HTTP_STATUS_CODE,
115
- SpanAttributes.HTTP_FLAVOR,
116
- SpanAttributes.HTTP_SERVER_NAME,
117
- SpanAttributes.NET_HOST_NAME,
118
- SpanAttributes.NET_HOST_PORT,
129
+ HTTP_METHOD,
130
+ HTTP_HOST,
131
+ HTTP_SCHEME,
132
+ HTTP_STATUS_CODE,
133
+ HTTP_FLAVOR,
134
+ HTTP_SERVER_NAME,
135
+ NET_HOST_NAME,
136
+ NET_HOST_PORT,
119
137
  ]
120
138
 
121
139
  _server_duration_attrs_new = [
@@ -128,11 +146,11 @@ _server_duration_attrs_new = [
128
146
  ]
129
147
 
130
148
  _server_active_requests_count_attrs_old = [
131
- SpanAttributes.HTTP_METHOD,
132
- SpanAttributes.HTTP_HOST,
133
- SpanAttributes.HTTP_SCHEME,
134
- SpanAttributes.HTTP_FLAVOR,
135
- SpanAttributes.HTTP_SERVER_NAME,
149
+ HTTP_METHOD,
150
+ HTTP_HOST,
151
+ HTTP_SCHEME,
152
+ HTTP_FLAVOR,
153
+ HTTP_SERVER_NAME,
136
154
  ]
137
155
 
138
156
  _server_active_requests_count_attrs_new = [
@@ -144,9 +162,10 @@ _server_active_requests_count_attrs_new = [
144
162
  OTEL_SEMCONV_STABILITY_OPT_IN = "OTEL_SEMCONV_STABILITY_OPT_IN"
145
163
 
146
164
 
147
- class _OpenTelemetryStabilitySignalType:
165
+ class _OpenTelemetryStabilitySignalType(Enum):
148
166
  HTTP = "http"
149
167
  DATABASE = "database"
168
+ GEN_AI = "gen_ai"
150
169
 
151
170
 
152
171
  class _StabilityMode(Enum):
@@ -155,6 +174,7 @@ class _StabilityMode(Enum):
155
174
  HTTP_DUP = "http/dup"
156
175
  DATABASE = "database"
157
176
  DATABASE_DUP = "database/dup"
177
+ GEN_AI_LATEST_EXPERIMENTAL = "gen_ai_latest_experimental"
158
178
 
159
179
 
160
180
  def _report_new(mode: _StabilityMode):
@@ -177,7 +197,7 @@ class _OpenTelemetrySemanticConventionStability:
177
197
  return
178
198
 
179
199
  # Users can pass in comma delimited string for opt-in options
180
- # Only values for http and database stability are supported for now
200
+ # Only values for http, gen ai, and database stability are supported for now
181
201
  opt_in = os.environ.get(OTEL_SEMCONV_STABILITY_OPT_IN)
182
202
 
183
203
  if not opt_in:
@@ -185,6 +205,7 @@ class _OpenTelemetrySemanticConventionStability:
185
205
  cls._OTEL_SEMCONV_STABILITY_SIGNAL_MAPPING = {
186
206
  _OpenTelemetryStabilitySignalType.HTTP: _StabilityMode.DEFAULT,
187
207
  _OpenTelemetryStabilitySignalType.DATABASE: _StabilityMode.DEFAULT,
208
+ _OpenTelemetryStabilitySignalType.GEN_AI: _StabilityMode.DEFAULT,
188
209
  }
189
210
  cls._initialized = True
190
211
  return
@@ -197,6 +218,14 @@ class _OpenTelemetrySemanticConventionStability:
197
218
  opt_in_list, _StabilityMode.HTTP, _StabilityMode.HTTP_DUP
198
219
  )
199
220
 
221
+ cls._OTEL_SEMCONV_STABILITY_SIGNAL_MAPPING[
222
+ _OpenTelemetryStabilitySignalType.GEN_AI
223
+ ] = cls._filter_mode(
224
+ opt_in_list,
225
+ _StabilityMode.DEFAULT,
226
+ _StabilityMode.GEN_AI_LATEST_EXPERIMENTAL,
227
+ )
228
+
200
229
  cls._OTEL_SEMCONV_STABILITY_SIGNAL_MAPPING[
201
230
  _OpenTelemetryStabilitySignalType.DATABASE
202
231
  ] = cls._filter_mode(
@@ -204,7 +233,6 @@ class _OpenTelemetrySemanticConventionStability:
204
233
  _StabilityMode.DATABASE,
205
234
  _StabilityMode.DATABASE_DUP,
206
235
  )
207
-
208
236
  cls._initialized = True
209
237
 
210
238
  @staticmethod
@@ -287,44 +315,42 @@ def _set_http_method(result, original, normalized, sem_conv_opt_in_mode):
287
315
  set_string_attribute(result, HTTP_REQUEST_METHOD_ORIGINAL, original)
288
316
 
289
317
  if _report_old(sem_conv_opt_in_mode):
290
- set_string_attribute(result, SpanAttributes.HTTP_METHOD, normalized)
318
+ set_string_attribute(result, HTTP_METHOD, normalized)
291
319
  if _report_new(sem_conv_opt_in_mode):
292
320
  set_string_attribute(result, HTTP_REQUEST_METHOD, normalized)
293
321
 
294
322
 
295
323
  def _set_http_status_code(result, code, sem_conv_opt_in_mode):
296
324
  if _report_old(sem_conv_opt_in_mode):
297
- set_int_attribute(result, SpanAttributes.HTTP_STATUS_CODE, code)
325
+ set_int_attribute(result, HTTP_STATUS_CODE, code)
298
326
  if _report_new(sem_conv_opt_in_mode):
299
327
  set_int_attribute(result, HTTP_RESPONSE_STATUS_CODE, code)
300
328
 
301
329
 
302
330
  def _set_http_url(result, url, sem_conv_opt_in_mode):
303
331
  if _report_old(sem_conv_opt_in_mode):
304
- set_string_attribute(result, SpanAttributes.HTTP_URL, url)
332
+ set_string_attribute(result, HTTP_URL, url)
305
333
  if _report_new(sem_conv_opt_in_mode):
306
334
  set_string_attribute(result, URL_FULL, url)
307
335
 
308
336
 
309
337
  def _set_http_scheme(result, scheme, sem_conv_opt_in_mode):
310
338
  if _report_old(sem_conv_opt_in_mode):
311
- set_string_attribute(result, SpanAttributes.HTTP_SCHEME, scheme)
339
+ set_string_attribute(result, HTTP_SCHEME, scheme)
312
340
  if _report_new(sem_conv_opt_in_mode):
313
341
  set_string_attribute(result, URL_SCHEME, scheme)
314
342
 
315
343
 
316
344
  def _set_http_flavor_version(result, version, sem_conv_opt_in_mode):
317
345
  if _report_old(sem_conv_opt_in_mode):
318
- set_string_attribute(result, SpanAttributes.HTTP_FLAVOR, version)
346
+ set_string_attribute(result, HTTP_FLAVOR, version)
319
347
  if _report_new(sem_conv_opt_in_mode):
320
348
  set_string_attribute(result, NETWORK_PROTOCOL_VERSION, version)
321
349
 
322
350
 
323
351
  def _set_http_user_agent(result, user_agent, sem_conv_opt_in_mode):
324
352
  if _report_old(sem_conv_opt_in_mode):
325
- set_string_attribute(
326
- result, SpanAttributes.HTTP_USER_AGENT, user_agent
327
- )
353
+ set_string_attribute(result, HTTP_USER_AGENT, user_agent)
328
354
  if _report_new(sem_conv_opt_in_mode):
329
355
  set_string_attribute(result, USER_AGENT_ORIGINAL, user_agent)
330
356
 
@@ -334,28 +360,28 @@ def _set_http_user_agent(result, user_agent, sem_conv_opt_in_mode):
334
360
 
335
361
  def _set_http_host_client(result, host, sem_conv_opt_in_mode):
336
362
  if _report_old(sem_conv_opt_in_mode):
337
- set_string_attribute(result, SpanAttributes.HTTP_HOST, host)
363
+ set_string_attribute(result, HTTP_HOST, host)
338
364
  if _report_new(sem_conv_opt_in_mode):
339
365
  set_string_attribute(result, SERVER_ADDRESS, host)
340
366
 
341
367
 
342
368
  def _set_http_net_peer_name_client(result, peer_name, sem_conv_opt_in_mode):
343
369
  if _report_old(sem_conv_opt_in_mode):
344
- set_string_attribute(result, SpanAttributes.NET_PEER_NAME, peer_name)
370
+ set_string_attribute(result, NET_PEER_NAME, peer_name)
345
371
  if _report_new(sem_conv_opt_in_mode):
346
372
  set_string_attribute(result, SERVER_ADDRESS, peer_name)
347
373
 
348
374
 
349
375
  def _set_http_peer_port_client(result, port, sem_conv_opt_in_mode):
350
376
  if _report_old(sem_conv_opt_in_mode):
351
- set_int_attribute(result, SpanAttributes.NET_PEER_PORT, port)
377
+ set_int_attribute(result, NET_PEER_PORT, port)
352
378
  if _report_new(sem_conv_opt_in_mode):
353
379
  set_int_attribute(result, SERVER_PORT, port)
354
380
 
355
381
 
356
382
  def _set_http_network_protocol_version(result, version, sem_conv_opt_in_mode):
357
383
  if _report_old(sem_conv_opt_in_mode):
358
- set_string_attribute(result, SpanAttributes.HTTP_FLAVOR, version)
384
+ set_string_attribute(result, HTTP_FLAVOR, version)
359
385
  if _report_new(sem_conv_opt_in_mode):
360
386
  set_string_attribute(result, NETWORK_PROTOCOL_VERSION, version)
361
387
 
@@ -365,21 +391,21 @@ def _set_http_network_protocol_version(result, version, sem_conv_opt_in_mode):
365
391
 
366
392
  def _set_http_net_host(result, host, sem_conv_opt_in_mode):
367
393
  if _report_old(sem_conv_opt_in_mode):
368
- set_string_attribute(result, SpanAttributes.NET_HOST_NAME, host)
394
+ set_string_attribute(result, NET_HOST_NAME, host)
369
395
  if _report_new(sem_conv_opt_in_mode):
370
396
  set_string_attribute(result, SERVER_ADDRESS, host)
371
397
 
372
398
 
373
399
  def _set_http_net_host_port(result, port, sem_conv_opt_in_mode):
374
400
  if _report_old(sem_conv_opt_in_mode):
375
- set_int_attribute(result, SpanAttributes.NET_HOST_PORT, port)
401
+ set_int_attribute(result, NET_HOST_PORT, port)
376
402
  if _report_new(sem_conv_opt_in_mode):
377
403
  set_int_attribute(result, SERVER_PORT, port)
378
404
 
379
405
 
380
406
  def _set_http_target(result, target, path, query, sem_conv_opt_in_mode):
381
407
  if _report_old(sem_conv_opt_in_mode):
382
- set_string_attribute(result, SpanAttributes.HTTP_TARGET, target)
408
+ set_string_attribute(result, HTTP_TARGET, target)
383
409
  if _report_new(sem_conv_opt_in_mode):
384
410
  if path:
385
411
  set_string_attribute(result, URL_PATH, path)
@@ -389,7 +415,7 @@ def _set_http_target(result, target, path, query, sem_conv_opt_in_mode):
389
415
 
390
416
  def _set_http_host_server(result, host, sem_conv_opt_in_mode):
391
417
  if _report_old(sem_conv_opt_in_mode):
392
- set_string_attribute(result, SpanAttributes.HTTP_HOST, host)
418
+ set_string_attribute(result, HTTP_HOST, host)
393
419
  if _report_new(sem_conv_opt_in_mode):
394
420
  if not result.get(SERVER_ADDRESS):
395
421
  set_string_attribute(result, SERVER_ADDRESS, host)
@@ -402,7 +428,7 @@ def _set_http_host_server(result, host, sem_conv_opt_in_mode):
402
428
  # https://github.com/open-telemetry/semantic-conventions/blob/main/docs/non-normative/http-migration.md#common-attributes-across-http-client-and-server-spans
403
429
  def _set_http_peer_ip_server(result, ip, sem_conv_opt_in_mode):
404
430
  if _report_old(sem_conv_opt_in_mode):
405
- set_string_attribute(result, SpanAttributes.NET_PEER_IP, ip)
431
+ set_string_attribute(result, NET_PEER_IP, ip)
406
432
  if _report_new(sem_conv_opt_in_mode):
407
433
  # Only populate if not already populated
408
434
  if not result.get(CLIENT_ADDRESS):
@@ -411,14 +437,14 @@ def _set_http_peer_ip_server(result, ip, sem_conv_opt_in_mode):
411
437
 
412
438
  def _set_http_peer_port_server(result, port, sem_conv_opt_in_mode):
413
439
  if _report_old(sem_conv_opt_in_mode):
414
- set_int_attribute(result, SpanAttributes.NET_PEER_PORT, port)
440
+ set_int_attribute(result, NET_PEER_PORT, port)
415
441
  if _report_new(sem_conv_opt_in_mode):
416
442
  set_int_attribute(result, CLIENT_PORT, port)
417
443
 
418
444
 
419
445
  def _set_http_net_peer_name_server(result, name, sem_conv_opt_in_mode):
420
446
  if _report_old(sem_conv_opt_in_mode):
421
- set_string_attribute(result, SpanAttributes.NET_PEER_NAME, name)
447
+ set_string_attribute(result, NET_PEER_NAME, name)
422
448
  if _report_new(sem_conv_opt_in_mode):
423
449
  set_string_attribute(result, CLIENT_ADDRESS, name)
424
450
 
@@ -450,10 +476,8 @@ def _set_status(
450
476
 
451
477
  if _report_old(sem_conv_opt_in_mode):
452
478
  if span.is_recording():
453
- span.set_attribute(
454
- SpanAttributes.HTTP_STATUS_CODE, status_code
455
- )
456
- metrics_attributes[SpanAttributes.HTTP_STATUS_CODE] = status_code
479
+ span.set_attribute(HTTP_STATUS_CODE, status_code)
480
+ metrics_attributes[HTTP_STATUS_CODE] = status_code
457
481
  if _report_new(sem_conv_opt_in_mode):
458
482
  if span.is_recording():
459
483
  span.set_attribute(HTTP_RESPONSE_STATUS_CODE, status_code)
@@ -470,4 +494,4 @@ def _set_status(
470
494
  def _get_schema_url(mode: _StabilityMode) -> str:
471
495
  if mode is _StabilityMode.DEFAULT:
472
496
  return "https://opentelemetry.io/schemas/1.11.0"
473
- return SpanAttributes.SCHEMA_URL
497
+ return Schemas.V1_21_0.value
@@ -12,6 +12,8 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
+ from __future__ import annotations
16
+
15
17
  from argparse import REMAINDER, ArgumentParser
16
18
  from logging import getLogger
17
19
  from os import environ, execl, getcwd
@@ -24,6 +26,9 @@ from opentelemetry.instrumentation.auto_instrumentation._load import (
24
26
  _load_distro,
25
27
  _load_instrumentors,
26
28
  )
29
+ from opentelemetry.instrumentation.environment_variables import (
30
+ OTEL_PYTHON_AUTO_INSTRUMENTATION_EXPERIMENTAL_GEVENT_PATCH,
31
+ )
27
32
  from opentelemetry.instrumentation.utils import _python_path_without_directory
28
33
  from opentelemetry.instrumentation.version import __version__
29
34
  from opentelemetry.util._importlib_metadata import entry_points
@@ -130,6 +135,30 @@ def initialize(*, swallow_exceptions: bool = True) -> None:
130
135
  environ["PYTHONPATH"], dirname(abspath(__file__)), pathsep
131
136
  )
132
137
 
138
+ # handle optional gevent monkey patching. This is done via environment variables so it may be used from the
139
+ # opentelemetry operator
140
+ gevent_patch: str | None = environ.get(
141
+ OTEL_PYTHON_AUTO_INSTRUMENTATION_EXPERIMENTAL_GEVENT_PATCH
142
+ )
143
+ if gevent_patch is not None:
144
+ if gevent_patch != "patch_all":
145
+ _logger.error(
146
+ "%s value must be `patch_all`",
147
+ OTEL_PYTHON_AUTO_INSTRUMENTATION_EXPERIMENTAL_GEVENT_PATCH,
148
+ )
149
+ else:
150
+ try:
151
+ # pylint: disable=import-outside-toplevel
152
+ from gevent import monkey
153
+
154
+ getattr(monkey, gevent_patch)()
155
+ except ImportError:
156
+ _logger.exception(
157
+ "Failed to monkey patch with gevent because gevent is not available"
158
+ )
159
+ if not swallow_exceptions:
160
+ raise
161
+
133
162
  try:
134
163
  distro = _load_distro()
135
164
  distro.configure()
@@ -12,10 +12,14 @@
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
15
16
  from logging import getLogger
16
17
  from os import environ
17
18
 
18
- from opentelemetry.instrumentation.dependencies import DependencyConflictError
19
+ from opentelemetry.instrumentation.dependencies import (
20
+ DependencyConflictError,
21
+ get_dist_dependency_conflicts,
22
+ )
19
23
  from opentelemetry.instrumentation.distro import BaseDistro, DefaultDistro
20
24
  from opentelemetry.instrumentation.environment_variables import (
21
25
  OTEL_PYTHON_CONFIGURATOR,
@@ -23,11 +27,36 @@ from opentelemetry.instrumentation.environment_variables import (
23
27
  OTEL_PYTHON_DISTRO,
24
28
  )
25
29
  from opentelemetry.instrumentation.version import __version__
26
- from opentelemetry.util._importlib_metadata import entry_points
30
+ from opentelemetry.util._importlib_metadata import (
31
+ EntryPoint,
32
+ distributions,
33
+ entry_points,
34
+ )
27
35
 
28
36
  _logger = getLogger(__name__)
29
37
 
30
38
 
39
+ class _EntryPointDistFinder:
40
+ @cached_property
41
+ def _mapping(self):
42
+ return {
43
+ self._key_for(ep): dist
44
+ for dist in distributions()
45
+ for ep in dist.entry_points
46
+ }
47
+
48
+ def dist_for(self, entry_point: EntryPoint):
49
+ dist = getattr(entry_point, "dist", None)
50
+ if dist:
51
+ return dist
52
+
53
+ return self._mapping.get(self._key_for(entry_point))
54
+
55
+ @staticmethod
56
+ def _key_for(entry_point: EntryPoint):
57
+ return f"{entry_point.group}:{entry_point.name}:{entry_point.value}"
58
+
59
+
31
60
  def _load_distro() -> BaseDistro:
32
61
  distro_name = environ.get(OTEL_PYTHON_DISTRO, None)
33
62
  for entry_point in entry_points(group="opentelemetry_distro"):
@@ -55,6 +84,7 @@ def _load_distro() -> BaseDistro:
55
84
 
56
85
  def _load_instrumentors(distro):
57
86
  package_to_exclude = environ.get(OTEL_PYTHON_DISABLED_INSTRUMENTATIONS, [])
87
+ entry_point_finder = _EntryPointDistFinder()
58
88
  if isinstance(package_to_exclude, str):
59
89
  package_to_exclude = package_to_exclude.split(",")
60
90
  # to handle users entering "requests , flask" or "requests, flask" with spaces
@@ -71,11 +101,24 @@ def _load_instrumentors(distro):
71
101
  continue
72
102
 
73
103
  try:
74
- distro.load_instrumentor(
75
- entry_point, raise_exception_on_conflict=True
76
- )
104
+ entry_point_dist = entry_point_finder.dist_for(entry_point)
105
+ conflict = get_dist_dependency_conflicts(entry_point_dist)
106
+ if conflict:
107
+ _logger.debug(
108
+ "Skipping instrumentation %s: %s",
109
+ entry_point.name,
110
+ conflict,
111
+ )
112
+ continue
113
+
114
+ # tell instrumentation to not run dep checks again as we already did it above
115
+ distro.load_instrumentor(entry_point, skip_dep_check=True)
77
116
  _logger.debug("Instrumented %s", entry_point.name)
78
117
  except DependencyConflictError as exc:
118
+ # Dependency conflicts are generally caught from get_dist_dependency_conflicts
119
+ # returning a DependencyConflict. Keeping this error handling in case custom
120
+ # distro and instrumentor behavior raises a DependencyConflictError later.
121
+ # See https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3610
79
122
  _logger.debug(
80
123
  "Skipping instrumentation %s: %s",
81
124
  entry_point.name,