Skip to content

Commit b60cfc8

Browse files
committed
Merge branch 'main' into issue_2555
2 parents 18fbf80 + dc711e8 commit b60cfc8

File tree

14 files changed

+212
-82
lines changed

14 files changed

+212
-82
lines changed

CHANGELOG.md

+6-1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
99

1010
### Breaking changes
1111

12+
- Add return statement to Confluent kafka Producer poll() and flush() calls when instrumented by ConfluentKafkaInstrumentor().instrument_producer() ([#2527](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2527))
1213
- Rename `type` attribute to `asgi.event.type` in `opentelemetry-instrumentation-asgi`
1314
([#2300](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2300))
1415
- Rename AwsLambdaInstrumentor span attributes `faas.id` to `cloud.resource_id`, `faas.execution` to `faas.invocation_id`
@@ -41,7 +42,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
4142

4243
### Fixed
4344

44-
- `opentelemetry-instrumentation-dbapi` Fix compatibility with Psycopg3 to extract libpq build version (#2500)[https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2500]
45+
- `opentelemetry-instrumentation-dbapi` Fix compatibility with Psycopg3 to extract libpq build version
46+
([#2500](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2500))
47+
- `opentelemetry-instrumentation-httpx` Ensure httpx.get or httpx.request like methods are instrumented
48+
([#2538](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2538))
4549
- `opentelemetry-instrumentation-grpc` AioClientInterceptor should propagate with a Metadata object
4650
([#2363](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2363))
4751
- `opentelemetry-instrumentation-boto3sqs` Instrument Session and resource
@@ -65,6 +69,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
6569
- `opentelemetry-util-http` Preserve brackets around literal IPv6 hosts ([#2552](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2552))
6670
- `opentelemetry-instrumentation-tornado` Fix not handling a http client exception
6771
([#2563](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2563))
72+
- `opentelemetry-util-redis` Fix net peer attribute for unix socket connection ([#2493](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2493))
6873

6974
## Version 1.24.0/0.45b0 (2024-03-28)
7075

instrumentation/opentelemetry-instrumentation-boto/test-requirements.txt

+2-32
Original file line numberDiff line numberDiff line change
@@ -1,69 +1,39 @@
1-
annotated-types==0.6.0
21
asgiref==3.7.2
32
attrs==23.2.0
4-
aws-sam-translator==1.85.0
5-
aws-xray-sdk==2.12.1
63
boto==2.49.0
74
boto3==1.34.44
85
botocore==1.34.44
96
certifi==2024.2.2
107
cffi==1.16.0
11-
cfn-lint==0.85.2
128
charset-normalizer==3.3.2
139
cryptography==42.0.3
1410
Deprecated==1.2.14
1511
docker==7.0.0
16-
ecdsa==0.18.0
17-
graphql-core==3.2.3
1812
idna==3.6
1913
importlib-metadata==6.11.0
20-
importlib-resources==6.1.1
2114
iniconfig==2.0.0
22-
Jinja2==3.1.3
15+
Jinja2==3.1.4
2316
jmespath==1.0.1
24-
jschema-to-python==1.2.3
25-
jsondiff==2.0.0
26-
jsonpatch==1.33
27-
jsonpickle==3.0.2
28-
jsonpointer==2.4
29-
jsonschema==4.21.1
30-
jsonschema-specifications==2023.12.1
31-
junit-xml==1.9
3217
MarkupSafe==2.1.5
3318
moto==2.3.2
34-
mpmath==1.3.0
35-
networkx==3.1
3619
packaging==23.2
37-
pbr==6.0.0
38-
pkgutil_resolve_name==1.3.10
3920
pluggy==1.4.0
4021
py==1.11.0
4122
py-cpuinfo==9.0.0
42-
pyasn1==0.5.1
4323
pycparser==2.21
44-
pydantic==2.6.1
45-
pydantic_core==2.16.2
4624
pytest==7.1.3
4725
pytest-benchmark==4.0.0
4826
python-dateutil==2.8.2
49-
python-jose==3.3.0
5027
pytz==2024.1
5128
PyYAML==6.0.1
52-
referencing==0.33.0
53-
regex==2023.12.25
5429
requests==2.31.0
5530
responses==0.25.0
56-
rpds-py==0.18.0
57-
rsa==4.9
5831
s3transfer==0.10.0
59-
sarif-om==1.0.4
6032
six==1.16.0
61-
sshpubkeys==3.3.1
62-
sympy==1.12
6333
tomli==2.0.1
6434
typing_extensions==4.9.0
6535
urllib3==1.26.18
66-
Werkzeug==3.0.1
36+
Werkzeug==2.1.2
6737
wrapt==1.16.0
6838
xmltodict==0.13.0
6939
zipp==3.17.0

instrumentation/opentelemetry-instrumentation-botocore/test-requirements.txt

+1-29
Original file line numberDiff line numberDiff line change
@@ -1,63 +1,35 @@
1-
annotated-types==0.6.0
21
asgiref==3.7.2
32
attrs==23.2.0
4-
aws-sam-translator==1.85.0
53
aws-xray-sdk==2.12.1
64
boto3==1.28.80
75
botocore==1.31.80
86
certifi==2024.2.2
97
cffi==1.16.0
10-
cfn-lint==0.85.2
118
charset-normalizer==3.3.2
129
cryptography==42.0.5
1310
Deprecated==1.2.14
1411
docker==7.0.0
15-
ecdsa==0.18.0
1612
idna==3.6
1713
importlib-metadata==6.11.0
18-
importlib-resources==6.1.1
1914
iniconfig==2.0.0
20-
Jinja2==3.1.3
15+
Jinja2==3.1.4
2116
jmespath==1.0.1
22-
jschema-to-python==1.2.3
23-
jsondiff==2.0.0
24-
jsonpatch==1.33
25-
jsonpickle==3.0.3
26-
jsonpointer==2.4
27-
jsonschema==4.21.1
28-
jsonschema-specifications==2023.12.1
29-
junit-xml==1.9
3017
MarkupSafe==2.0.1
3118
moto==3.1.19
32-
mpmath==1.3.0
33-
networkx==3.1
3419
packaging==23.2
35-
pbr==6.0.0
36-
pkgutil_resolve_name==1.3.10
3720
pluggy==1.4.0
3821
py==1.11.0
3922
py-cpuinfo==9.0.0
40-
pyasn1==0.5.1
4123
pycparser==2.21
42-
pydantic==2.6.2
43-
pydantic_core==2.16.3
4424
pytest==7.1.3
4525
pytest-benchmark==4.0.0
4626
python-dateutil==2.8.2
47-
python-jose==3.3.0
4827
pytz==2024.1
4928
PyYAML==6.0.1
50-
referencing==0.33.0
51-
regex==2023.12.25
5229
requests==2.31.0
5330
responses==0.25.0
54-
rpds-py==0.18.0
55-
rsa==4.9
5631
s3transfer==0.7.0
57-
sarif-om==1.0.4
5832
six==1.16.0
59-
sshpubkeys==3.3.1
60-
sympy==1.12
6133
tomli==2.0.1
6234
typing_extensions==4.9.0
6335
urllib3==1.26.18

instrumentation/opentelemetry-instrumentation-confluent-kafka/src/opentelemetry/instrumentation/confluent_kafka/__init__.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -151,10 +151,10 @@ def __init__(self, producer: Producer, tracer: Tracer):
151151
self._tracer = tracer
152152

153153
def flush(self, timeout=-1):
154-
self._producer.flush(timeout)
154+
return self._producer.flush(timeout)
155155

156156
def poll(self, timeout=-1):
157-
self._producer.poll(timeout)
157+
return self._producer.poll(timeout)
158158

159159
def produce(
160160
self, topic, value=None, *args, **kwargs

instrumentation/opentelemetry-instrumentation-confluent-kafka/tests/test_instrumentation.py

+33-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
)
3232
from opentelemetry.test.test_base import TestBase
3333

34-
from .utils import MockConsumer, MockedMessage
34+
from .utils import MockConsumer, MockedMessage, MockedProducer
3535

3636

3737
class TestConfluentKafka(TestBase):
@@ -246,3 +246,35 @@ def _compare_spans(self, spans, expected_spans):
246246
self.assertEqual(
247247
expected_attribute_value, span.attributes[attribute_key]
248248
)
249+
250+
def test_producer_poll(self) -> None:
251+
instrumentation = ConfluentKafkaInstrumentor()
252+
message_queue = []
253+
254+
producer = MockedProducer(
255+
message_queue,
256+
{
257+
"bootstrap.servers": "localhost:29092",
258+
},
259+
)
260+
261+
producer = instrumentation.instrument_producer(producer)
262+
producer.produce(topic="topic-1", key="key-1", value="value-1")
263+
msg = producer.poll()
264+
self.assertIsNotNone(msg)
265+
266+
def test_producer_flush(self) -> None:
267+
instrumentation = ConfluentKafkaInstrumentor()
268+
message_queue = []
269+
270+
producer = MockedProducer(
271+
message_queue,
272+
{
273+
"bootstrap.servers": "localhost:29092",
274+
},
275+
)
276+
277+
producer = instrumentation.instrument_producer(producer)
278+
producer.produce(topic="topic-1", key="key-1", value="value-1")
279+
msg = producer.flush()
280+
self.assertIsNotNone(msg)

instrumentation/opentelemetry-instrumentation-confluent-kafka/tests/utils.py

+46-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
from confluent_kafka import Consumer
1+
from typing import Optional
2+
3+
from confluent_kafka import Consumer, Producer
24

35

46
class MockConsumer(Consumer):
@@ -20,11 +22,21 @@ def poll(self, timeout=None):
2022

2123

2224
class MockedMessage:
23-
def __init__(self, topic: str, partition: int, offset: int, headers):
25+
def __init__(
26+
self,
27+
topic: str,
28+
partition: int,
29+
offset: int,
30+
headers,
31+
key: Optional[str] = None,
32+
value: Optional[str] = None,
33+
):
2434
self._topic = topic
2535
self._partition = partition
2636
self._offset = offset
2737
self._headers = headers
38+
self._key = key
39+
self._value = value
2840

2941
def topic(self):
3042
return self._topic
@@ -37,3 +49,35 @@ def offset(self):
3749

3850
def headers(self):
3951
return self._headers
52+
53+
def key(self):
54+
return self._key
55+
56+
def value(self):
57+
return self._value
58+
59+
60+
class MockedProducer(Producer):
61+
def __init__(self, queue, config):
62+
self._queue = queue
63+
super().__init__(config)
64+
65+
def produce(
66+
self, *args, **kwargs
67+
): # pylint: disable=keyword-arg-before-vararg
68+
self._queue.append(
69+
MockedMessage(
70+
topic=kwargs.get("topic"),
71+
partition=0,
72+
offset=0,
73+
headers=[],
74+
key=kwargs.get("key"),
75+
value=kwargs.get("value"),
76+
)
77+
)
78+
79+
def poll(self, *args, **kwargs):
80+
return len(self._queue)
81+
82+
def flush(self, *args, **kwargs):
83+
return len(self._queue)

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

+4-2
Original file line numberDiff line numberDiff line change
@@ -564,11 +564,13 @@ def _instrument(self, **kwargs):
564564
tracer_provider = kwargs.get("tracer_provider")
565565
_InstrumentedClient._tracer_provider = tracer_provider
566566
_InstrumentedAsyncClient._tracer_provider = tracer_provider
567-
httpx.Client = _InstrumentedClient
567+
# Intentionally using a private attribute here, see:
568+
# https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2538#discussion_r1610603719
569+
httpx.Client = httpx._api.Client = _InstrumentedClient
568570
httpx.AsyncClient = _InstrumentedAsyncClient
569571

570572
def _uninstrument(self, **kwargs):
571-
httpx.Client = self._original_client
573+
httpx.Client = httpx._api.Client = self._original_client
572574
httpx.AsyncClient = self._original_async_client
573575
_InstrumentedClient._tracer_provider = None
574576
_InstrumentedClient._request_hook = None

instrumentation/opentelemetry-instrumentation-httpx/tests/test_httpx_integration.py

+24
Original file line numberDiff line numberDiff line change
@@ -532,12 +532,36 @@ def test_instrument_client(self):
532532
self.assertEqual(result.text, "Hello!")
533533
self.assert_span(num_spans=1)
534534

535+
def test_instrumentation_without_client(self):
536+
537+
HTTPXClientInstrumentor().instrument()
538+
results = [
539+
httpx.get(self.URL),
540+
httpx.request("GET", self.URL),
541+
]
542+
with httpx.stream("GET", self.URL) as stream:
543+
stream.read()
544+
results.append(stream)
545+
546+
spans = self.assert_span(num_spans=len(results))
547+
for idx, res in enumerate(results):
548+
with self.subTest(idx=idx, res=res):
549+
self.assertEqual(res.text, "Hello!")
550+
self.assertEqual(
551+
spans[idx].attributes[SpanAttributes.HTTP_URL],
552+
self.URL,
553+
)
554+
555+
HTTPXClientInstrumentor().uninstrument()
556+
535557
def test_uninstrument(self):
536558
HTTPXClientInstrumentor().instrument()
537559
HTTPXClientInstrumentor().uninstrument()
538560
client = self.create_client()
539561
result = self.perform_request(self.URL, client=client)
562+
result_no_client = httpx.get(self.URL)
540563
self.assertEqual(result.text, "Hello!")
564+
self.assertEqual(result_no_client.text, "Hello!")
541565
self.assert_span(num_spans=0)
542566

543567
def test_uninstrument_client(self):

instrumentation/opentelemetry-instrumentation-redis/src/opentelemetry/instrumentation/redis/util.py

+6-6
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,12 @@ def _extract_conn_attributes(conn_kwargs):
2929
}
3030
db = conn_kwargs.get("db", 0)
3131
attributes[SpanAttributes.DB_REDIS_DATABASE_INDEX] = db
32-
try:
32+
if "path" in conn_kwargs:
33+
attributes[SpanAttributes.NET_PEER_NAME] = conn_kwargs.get("path", "")
34+
attributes[SpanAttributes.NET_TRANSPORT] = (
35+
NetTransportValues.OTHER.value
36+
)
37+
else:
3338
attributes[SpanAttributes.NET_PEER_NAME] = conn_kwargs.get(
3439
"host", "localhost"
3540
)
@@ -39,11 +44,6 @@ def _extract_conn_attributes(conn_kwargs):
3944
attributes[SpanAttributes.NET_TRANSPORT] = (
4045
NetTransportValues.IP_TCP.value
4146
)
42-
except KeyError:
43-
attributes[SpanAttributes.NET_PEER_NAME] = conn_kwargs.get("path", "")
44-
attributes[SpanAttributes.NET_TRANSPORT] = (
45-
NetTransportValues.OTHER.value
46-
)
4747

4848
return attributes
4949

0 commit comments

Comments
 (0)