Skip to content

Commit d6f5f36

Browse files
Merge branch 'open-telemetry:main' into google_genai_attribute_improvements
2 parents 3953ea1 + af17965 commit d6f5f36

File tree

11 files changed

+127
-30
lines changed
  • instrumentation
    • opentelemetry-instrumentation-asgi/tests
    • opentelemetry-instrumentation-botocore/src/opentelemetry/instrumentation/botocore
    • opentelemetry-instrumentation-confluent-kafka/src/opentelemetry/instrumentation/confluent_kafka
    • opentelemetry-instrumentation-elasticsearch/src/opentelemetry/instrumentation/elasticsearch
    • opentelemetry-instrumentation-falcon
    • opentelemetry-instrumentation-fastapi/src/opentelemetry/instrumentation/fastapi
    • opentelemetry-instrumentation-flask/src/opentelemetry/instrumentation/flask
    • opentelemetry-instrumentation-logging/src/opentelemetry/instrumentation/logging
  • opentelemetry-instrumentation/src/opentelemetry/instrumentation

11 files changed

+127
-30
lines changed

CHANGELOG.md

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1111
1212
## Unreleased
1313

14+
### Fixed
15+
16+
- `opentelemetry-instrumentation` Fix client address is set to server address in new semconv
17+
([#3354](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3354))
18+
1419
## Version 1.31.0/0.52b0 (2025-03-12)
1520

1621
### Added
@@ -36,7 +41,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
3641
- Loosen `opentelemetry-instrumentation-starlette[instruments]` specifier
3742
([#3304](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3304))
3843

39-
4044
### Fixed
4145

4246
- `opentelemetry-instrumentation-redis` Add missing entry in doc string for `def _instrument`
@@ -112,7 +116,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
112116
### Breaking changes
113117

114118
- `opentelemetry-exporter-prometheus-remote-write` updated protobuf required version from 4.21 to 5.26 and regenerated protobufs
115-
([#3219](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3219))
119+
([#3219](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3219))
116120
- `opentelemetry-instrumentation-sqlalchemy` including sqlcomment in `db.statement` span attribute value is now opt-in
117121
([#3112](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3112))
118122
- `opentelemetry-instrumentation-dbapi` including sqlcomment in `db.statement` span attribute value is now opt-in

instrumentation/opentelemetry-instrumentation-asgi/tests/test_asgi_middleware.py

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,10 @@
5252
from opentelemetry.semconv.attributes.network_attributes import (
5353
NETWORK_PROTOCOL_VERSION,
5454
)
55-
from opentelemetry.semconv.attributes.server_attributes import SERVER_PORT
55+
from opentelemetry.semconv.attributes.server_attributes import (
56+
SERVER_ADDRESS,
57+
SERVER_PORT,
58+
)
5659
from opentelemetry.semconv.attributes.url_attributes import (
5760
URL_PATH,
5861
URL_QUERY,
@@ -401,6 +404,7 @@ def validate_outputs(
401404
"attributes": {
402405
HTTP_REQUEST_METHOD: "GET",
403406
URL_SCHEME: "http",
407+
SERVER_ADDRESS: "127.0.0.1",
404408
SERVER_PORT: 80,
405409
NETWORK_PROTOCOL_VERSION: "1.0",
406410
URL_PATH: "/",
@@ -436,6 +440,7 @@ def validate_outputs(
436440
"attributes": {
437441
HTTP_REQUEST_METHOD: "GET",
438442
URL_SCHEME: "http",
443+
SERVER_ADDRESS: "127.0.0.1",
439444
SERVER_PORT: 80,
440445
NETWORK_PROTOCOL_VERSION: "1.0",
441446
URL_PATH: "/",
@@ -706,7 +711,7 @@ async def test_behavior_with_scope_server_as_none_new_semconv(self):
706711
def update_expected_server(expected):
707712
expected[3]["attributes"].update(
708713
{
709-
CLIENT_ADDRESS: "0.0.0.0",
714+
SERVER_ADDRESS: "0.0.0.0",
710715
SERVER_PORT: 80,
711716
}
712717
)
@@ -733,7 +738,7 @@ def update_expected_server(expected):
733738
SpanAttributes.HTTP_HOST: "0.0.0.0",
734739
SpanAttributes.NET_HOST_PORT: 80,
735740
SpanAttributes.HTTP_URL: "http://0.0.0.0/",
736-
CLIENT_ADDRESS: "0.0.0.0",
741+
SERVER_ADDRESS: "0.0.0.0",
737742
SERVER_PORT: 80,
738743
}
739744
)
@@ -948,7 +953,7 @@ async def test_websocket(self):
948953
SpanAttributes.HTTP_HOST: self.scope["server"][0],
949954
SpanAttributes.HTTP_FLAVOR: self.scope["http_version"],
950955
SpanAttributes.HTTP_TARGET: self.scope["path"],
951-
SpanAttributes.HTTP_URL: f'{self.scope["scheme"]}://{self.scope["server"][0]}{self.scope["path"]}',
956+
SpanAttributes.HTTP_URL: f"{self.scope['scheme']}://{self.scope['server'][0]}{self.scope['path']}",
952957
SpanAttributes.NET_PEER_IP: self.scope["client"][0],
953958
SpanAttributes.NET_PEER_PORT: self.scope["client"][1],
954959
SpanAttributes.HTTP_STATUS_CODE: 200,
@@ -1018,6 +1023,7 @@ async def test_websocket_new_semconv(self):
10181023
"kind": trace_api.SpanKind.SERVER,
10191024
"attributes": {
10201025
URL_SCHEME: self.scope["scheme"],
1026+
SERVER_ADDRESS: self.scope["server"][0],
10211027
SERVER_PORT: self.scope["server"][1],
10221028
NETWORK_PROTOCOL_VERSION: self.scope["http_version"],
10231029
URL_PATH: self.scope["path"],
@@ -1096,12 +1102,13 @@ async def test_websocket_both_semconv(self):
10961102
SpanAttributes.HTTP_HOST: self.scope["server"][0],
10971103
SpanAttributes.HTTP_FLAVOR: self.scope["http_version"],
10981104
SpanAttributes.HTTP_TARGET: self.scope["path"],
1099-
SpanAttributes.HTTP_URL: f'{self.scope["scheme"]}://{self.scope["server"][0]}{self.scope["path"]}',
1105+
SpanAttributes.HTTP_URL: f"{self.scope['scheme']}://{self.scope['server'][0]}{self.scope['path']}",
11001106
SpanAttributes.NET_PEER_IP: self.scope["client"][0],
11011107
SpanAttributes.NET_PEER_PORT: self.scope["client"][1],
11021108
SpanAttributes.HTTP_STATUS_CODE: 200,
11031109
SpanAttributes.HTTP_METHOD: self.scope["method"],
11041110
URL_SCHEME: self.scope["scheme"],
1111+
SERVER_ADDRESS: self.scope["server"][0],
11051112
SERVER_PORT: self.scope["server"][1],
11061113
NETWORK_PROTOCOL_VERSION: self.scope["http_version"],
11071114
URL_PATH: self.scope["path"],
@@ -1661,6 +1668,7 @@ def test_request_attributes_new_semconv(self):
16611668
HTTP_REQUEST_METHOD: "GET",
16621669
URL_PATH: "/",
16631670
URL_QUERY: "foo=bar",
1671+
SERVER_ADDRESS: "127.0.0.1",
16641672
SERVER_PORT: 80,
16651673
URL_SCHEME: "http",
16661674
NETWORK_PROTOCOL_VERSION: "1.0",
@@ -1696,6 +1704,7 @@ def test_request_attributes_both_semconv(self):
16961704
HTTP_REQUEST_METHOD: "GET",
16971705
URL_PATH: "/",
16981706
URL_QUERY: "foo=bar",
1707+
SERVER_ADDRESS: "127.0.0.1",
16991708
SERVER_PORT: 80,
17001709
URL_SCHEME: "http",
17011710
NETWORK_PROTOCOL_VERSION: "1.0",

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

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
.. code:: python
2929
3030
from opentelemetry.instrumentation.botocore import BotocoreInstrumentor
31-
import botocore
31+
import botocore.session
3232
3333
3434
# Instrument Botocore
@@ -39,7 +39,7 @@
3939
session.set_credentials(
4040
access_key="access-key", secret_key="secret-key"
4141
)
42-
ec2 = self.session.create_client("ec2", region_name="us-west-2")
42+
ec2 = session.create_client("ec2", region_name="us-west-2")
4343
ec2.describe_instances()
4444
4545
API
@@ -58,13 +58,15 @@
5858
.. code: python
5959
6060
from opentelemetry.instrumentation.botocore import BotocoreInstrumentor
61-
import botocore
61+
import botocore.session
6262
6363
def request_hook(span, service_name, operation_name, api_params):
6464
# request hook logic
65+
pass
6566
6667
def response_hook(span, service_name, operation_name, result):
6768
# response hook logic
69+
pass
6870
6971
# Instrument Botocore with hooks
7072
BotocoreInstrumentor().instrument(request_hook=request_hook, response_hook=response_hook)
@@ -74,7 +76,7 @@ def response_hook(span, service_name, operation_name, result):
7476
session.set_credentials(
7577
access_key="access-key", secret_key="secret-key"
7678
)
77-
ec2 = self.session.create_client("ec2", region_name="us-west-2")
79+
ec2 = session.create_client("ec2", region_name="us-west-2")
7880
ec2.describe_instances()
7981
8082
Extensions

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

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@
3434
# report a span of type consumer with the default settings
3535
consumer = Consumer(conf2)
3636
37+
def msg_process(msg):
38+
print(msg)
39+
3740
def basic_consume_loop(consumer, topics):
3841
try:
3942
consumer.subscribe(topics)
@@ -44,7 +47,7 @@ def basic_consume_loop(consumer, topics):
4447
if msg.error():
4548
if msg.error().code() == KafkaError._PARTITION_EOF:
4649
# End of partition event
47-
sys.stderr.write(f"{msg.topic() [{msg.partition()}] reached end at offset {msg.offset()}}")
50+
sys.stderr.write(f"{msg.topic()} [{msg.partition()}] reached end at offset {msg.offset()}")
4851
elif msg.error():
4952
raise KafkaException(msg.error())
5053
else:
@@ -53,7 +56,7 @@ def basic_consume_loop(consumer, topics):
5356
# Close down consumer to commit final offsets.
5457
consumer.close()
5558
56-
basic_consume_loop(consumer, "my-topic")
59+
basic_consume_loop(consumer, ["my-topic"])
5760
5861
The _instrument method accepts the following keyword args:
5962
tracer_provider (TracerProvider) - an optional tracer provider
@@ -72,14 +75,16 @@ def instrument_consumer(consumer: Consumer, tracer_provider=None)
7275
.. code:: python
7376
7477
from opentelemetry.instrumentation.confluent_kafka import ConfluentKafkaInstrumentor
78+
from opentelemetry.trace import get_tracer_provider
7579
7680
from confluent_kafka import Producer, Consumer
7781
7882
inst = ConfluentKafkaInstrumentor()
83+
tracer_provider = get_tracer_provider()
7984
80-
p = confluent_kafka.Producer({'bootstrap.servers': 'localhost:29092'})
81-
c = confluent_kafka.Consumer({
82-
'bootstrap.servers': 'localhost:29092',
85+
p = Producer({'bootstrap.servers': 'localhost:9092'})
86+
c = Consumer({
87+
'bootstrap.servers': 'localhost:9092',
8388
'group.id': 'mygroup',
8489
'auto.offset.reset': 'earliest'
8590
})

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

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,15 +32,15 @@
3232
3333
from opentelemetry.instrumentation.elasticsearch import ElasticsearchInstrumentor
3434
import elasticsearch
35-
35+
from datetime import datetime
3636
3737
# instrument elasticsearch
3838
ElasticsearchInstrumentor().instrument()
3939
4040
# Using elasticsearch as normal now will automatically generate spans
4141
es = elasticsearch.Elasticsearch()
42-
es.index(index='my-index', doc_type='my-type', id=1, body={'my': 'data', 'timestamp': datetime.now()})
43-
es.get(index='my-index', doc_type='my-type', id=1)
42+
es.index(index='my-index', doc_type='_doc', id=1, body={'my': 'data', 'timestamp': datetime.now()})
43+
es.get(index='my-index', doc_type='_doc', id=1)
4444
4545
Elasticsearch instrumentation prefixes operation names with the string "Elasticsearch". This
4646
can be changed to a different string by either setting the OTEL_PYTHON_ELASTICSEARCH_NAME_PREFIX
@@ -49,6 +49,8 @@
4949
5050
.. code-block:: python
5151
52+
from opentelemetry.instrumentation.elasticsearch import ElasticsearchInstrumentor
53+
5254
ElasticsearchInstrumentor("my-custom-prefix").instrument()
5355
5456
The instrument() method accepts the following keyword args:
@@ -67,6 +69,7 @@ def response_hook(span: Span, response: dict)
6769
6870
from opentelemetry.instrumentation.elasticsearch import ElasticsearchInstrumentor
6971
import elasticsearch
72+
from datetime import datetime
7073
7174
def request_hook(span, method, url, kwargs):
7275
if span and span.is_recording():
@@ -82,8 +85,8 @@ def response_hook(span, response):
8285
# Using elasticsearch as normal now will automatically generate spans,
8386
# including user custom attributes added from the hooks
8487
es = elasticsearch.Elasticsearch()
85-
es.index(index='my-index', doc_type='my-type', id=1, body={'my': 'data', 'timestamp': datetime.now()})
86-
es.get(index='my-index', doc_type='my-type', id=1)
88+
es.index(index='my-index', doc_type='_doc', id=1, body={'my': 'data', 'timestamp': datetime.now()})
89+
es.get(index='my-index', doc_type='_doc', id=1)
8790
8891
API
8992
---

instrumentation/opentelemetry-instrumentation-falcon/README.rst

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,21 +47,41 @@ will extract path_info and content_type attributes from every traced request and
4747

4848
Falcon Request object reference: https://falcon.readthedocs.io/en/stable/api/request_and_response.html#id1
4949

50+
Usage
51+
-----
52+
53+
.. code-block:: python
54+
55+
import falcon
56+
from opentelemetry.instrumentation.falcon import FalconInstrumentor
57+
58+
FalconInstrumentor().instrument()
59+
60+
app = falcon.App()
61+
62+
class HelloWorldResource(object):
63+
def on_get(self, req, resp):
64+
resp.text = 'Hello World'
65+
66+
app.add_route('/hello', HelloWorldResource())
67+
5068
5169
Request/Response hooks
5270
**********************
5371
The instrumentation supports specifying request and response hooks. These are functions that get called back by the instrumentation right after a Span is created for a request
5472
and right before the span is finished while processing a response. The hooks can be configured as follows:
5573

56-
::
74+
.. code-block:: python
75+
76+
from opentelemetry.instrumentation.falcon import FalconInstrumentor
5777
5878
def request_hook(span, req):
5979
pass
6080
6181
def response_hook(span, req, resp):
6282
pass
6383
64-
FalconInstrumentation().instrument(request_hook=request_hook, response_hook=response_hook)
84+
FalconInstrumentor().instrument(request_hook=request_hook, response_hook=response_hook)
6585
6686
References
6787
----------

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

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -58,16 +58,16 @@
5858
5959
.. code-block:: python
6060
61-
from falcon import API
61+
import falcon
6262
from opentelemetry.instrumentation.falcon import FalconInstrumentor
6363
6464
FalconInstrumentor().instrument()
6565
66-
app = falcon.API()
66+
app = falcon.App()
6767
6868
class HelloWorldResource(object):
6969
def on_get(self, req, resp):
70-
resp.body = 'Hello World'
70+
resp.text = 'Hello World'
7171
7272
app.add_route('/hello', HelloWorldResource())
7373
@@ -78,15 +78,17 @@ def on_get(self, req, resp):
7878
right after a span is created for a request and right before the span is finished for the response.
7979
The hooks can be configured as follows:
8080
81-
::
81+
.. code-block:: python
82+
83+
from opentelemetry.instrumentation.falcon import FalconInstrumentor
8284
8385
def request_hook(span, req):
8486
pass
8587
8688
def response_hook(span, req, resp):
8789
pass
8890
89-
FalconInstrumentation().instrument(request_hook=request_hook, response_hook=response_hook)
91+
FalconInstrumentor().instrument(request_hook=request_hook, response_hook=response_hook)
9092
9193
Capture HTTP request and response headers
9294
*****************************************

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,10 @@ async def foobar():
6464
6565
.. code-block:: python
6666
67+
from opentelemetry.instrumentation.fastapi import FastAPIInstrumentor
68+
from opentelemetry.trace import Span
69+
from typing import Any
70+
6771
def server_request_hook(span: Span, scope: dict[str, Any]):
6872
if span and span.is_recording():
6973
span.set_attribute("custom_user_attribute_from_request_hook", "some-value")
@@ -76,7 +80,7 @@ def client_response_hook(span: Span, scope: dict[str, Any], message: dict[str, A
7680
if span and span.is_recording():
7781
span.set_attribute("custom_user_attribute_from_response_hook", "some-value")
7882
79-
FastAPIInstrumentor().instrument(server_request_hook=server_request_hook, client_request_hook=client_request_hook, client_response_hook=client_response_hook)
83+
FastAPIInstrumentor().instrument(server_request_hook=server_request_hook, client_request_hook=client_request_hook, client_response_hook=client_response_hook)
8084
8185
Capture HTTP request and response headers
8286
*****************************************

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,12 @@ def hello():
133133
134134
.. code-block:: python
135135
136+
from opentelemetry.trace import Span
137+
from wsgiref.types import WSGIEnvironment
138+
from typing import List
139+
140+
from opentelemetry.instrumentation.flask import FlaskInstrumentor
141+
136142
def request_hook(span: Span, environ: WSGIEnvironment):
137143
if span and span.is_recording():
138144
span.set_attribute("custom_user_attribute_from_request_hook", "some-value")

0 commit comments

Comments
 (0)