Skip to content

Commit b430915

Browse files
authored
Merge branch 'main' into xray-sampler-pr1
2 parents 8b463f4 + 1923343 commit b430915

File tree

7 files changed

+234
-119
lines changed

7 files changed

+234
-119
lines changed

CHANGELOG.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
2828

2929
### Fixed
3030

31-
- `opentelemetry-instrumentation-botocore`: Handle dict input in _decode_tool_use for Bedrock streaming
31+
- `opentelemetry-instrumentation-botocore`: bedrock: only decode JSON input buffer in Anthropic Claude streaming
3232
([#3875](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3875))
3333
- `opentelemetry-instrumentation-aiohttp-client`, `opentelemetry-instrumentation-aiohttp-server`: Fix readme links and text
3434
([#3902](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3902))
3535
- `opentelemetry-instrumentation-aws-lambda`: Fix ImportError with slash-delimited handler paths
3636
([#3894](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3894))
3737
- `opentelemetry-exporter-richconsole`: Prevent deadlock when parent span is not part of the batch
3838
([#3900](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3900))
39+
- `opentelemetry-instrumentation-psycopg2`, `opentelemetry-instrumentation-psycopg`: improve readthedocs for sqlcommenter configuration.
40+
([#3882](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3882))
41+
- `opentelemetry-instrumentation-aiohttp-server`: delay initialization of tracer, meter and excluded urls to instrumentation for testability
42+
([#3836](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3836))
3943

4044
## Version 1.38.0/0.59b0 (2025-10-16)
4145

instrumentation/opentelemetry-instrumentation-aiohttp-server/src/opentelemetry/instrumentation/aiohttp_server/__init__.py

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,25 @@ async def hello(request):
3535
app.add_routes([web.get('/', hello)])
3636
3737
web.run_app(app)
38+
39+
40+
Configuration
41+
-------------
42+
43+
Exclude lists
44+
*************
45+
To exclude certain URLs from tracking, set the environment variable ``OTEL_PYTHON_AIOHTTP_SERVER_EXCLUDED_URLS``
46+
(or ``OTEL_PYTHON_EXCLUDED_URLS`` to cover all instrumentations) to a string of comma delimited regexes that match the
47+
URLs.
48+
49+
For example,
50+
51+
::
52+
53+
export OTEL_PYTHON_AIOHTTP_SERVER_EXCLUDED_URLS="client/.*/info,healthcheck"
54+
55+
will exclude requests such as ``https://site/client/123/info`` and ``https://site/xyz/healthcheck``.
56+
3857
"""
3958

4059
import urllib
@@ -94,9 +113,9 @@ async def hello(request):
94113
HTTP_SERVER_NAME,
95114
]
96115

97-
tracer = trace.get_tracer(__name__)
98-
meter = metrics.get_meter(__name__, __version__)
99-
_excluded_urls = get_excluded_urls("AIOHTTP_SERVER")
116+
tracer = None
117+
meter = None
118+
_excluded_urls = None
100119

101120

102121
def _parse_duration_attrs(req_attrs):
@@ -296,6 +315,16 @@ class AioHttpServerInstrumentor(BaseInstrumentor):
296315
"""
297316

298317
def _instrument(self, **kwargs):
318+
# update global values at instrument time so we can test them
319+
global _excluded_urls # pylint: disable=global-statement
320+
_excluded_urls = get_excluded_urls("AIOHTTP_SERVER")
321+
322+
global tracer # pylint: disable=global-statement
323+
tracer = trace.get_tracer(__name__)
324+
325+
global meter # pylint: disable=global-statement
326+
meter = metrics.get_meter(__name__, __version__)
327+
299328
self._original_app = web.Application
300329
setattr(web, "Application", _InstrumentedApplication)
301330

instrumentation/opentelemetry-instrumentation-aiohttp-server/tests/test_aiohttp_server_integration.py

Lines changed: 78 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import pytest
2020
import pytest_asyncio
2121

22+
from opentelemetry import metrics as metrics_api
2223
from opentelemetry import trace as trace_api
2324
from opentelemetry.instrumentation.aiohttp_server import (
2425
AioHttpServerInstrumentor,
@@ -29,7 +30,10 @@
2930
HTTP_STATUS_CODE,
3031
HTTP_URL,
3132
)
32-
from opentelemetry.test.globals_test import reset_trace_globals
33+
from opentelemetry.test.globals_test import (
34+
reset_metrics_globals,
35+
reset_trace_globals,
36+
)
3337
from opentelemetry.test.test_base import TestBase
3438
from opentelemetry.util._importlib_metadata import entry_points
3539

@@ -65,6 +69,20 @@ def fixture_tracer():
6569
reset_trace_globals()
6670

6771

72+
@pytest.fixture(name="meter", scope="function")
73+
def fixture_meter():
74+
test_base = TestBase()
75+
76+
meter_provider, memory_reader = test_base.create_meter_provider()
77+
78+
reset_metrics_globals()
79+
metrics_api.set_meter_provider(meter_provider)
80+
81+
yield meter_provider, memory_reader
82+
83+
reset_metrics_globals()
84+
85+
6886
async def default_handler(request, status=200):
6987
return aiohttp.web.Response(status=status)
7088

@@ -113,21 +131,27 @@ def test_checking_instrumentor_pkg_installed():
113131
)
114132
async def test_status_code_instrumentation(
115133
tracer,
134+
meter,
116135
server_fixture,
117136
aiohttp_client,
118137
url,
119138
expected_method,
120139
expected_status_code,
121140
):
122141
_, memory_exporter = tracer
142+
_, metrics_reader = meter
123143
server, _ = server_fixture
124144

125145
assert len(memory_exporter.get_finished_spans()) == 0
146+
metrics = _get_sorted_metrics(metrics_reader.get_metrics_data())
147+
assert len(metrics) == 0
126148

127149
client = await aiohttp_client(server)
128150
await client.get(url)
129151

130152
assert len(memory_exporter.get_finished_spans()) == 1
153+
metrics = _get_sorted_metrics(metrics_reader.get_metrics_data())
154+
assert len(metrics) == 2
131155

132156
[span] = memory_exporter.get_finished_spans()
133157

@@ -195,3 +219,56 @@ async def handler(request):
195219
# Clean up
196220
AioHttpServerInstrumentor().uninstrument()
197221
memory_exporter.clear()
222+
223+
224+
def _get_sorted_metrics(metrics_data):
225+
resource_metrics = metrics_data.resource_metrics if metrics_data else []
226+
227+
all_metrics = []
228+
for metrics in resource_metrics:
229+
for scope_metrics in metrics.scope_metrics:
230+
all_metrics.extend(scope_metrics.metrics)
231+
232+
return sorted(
233+
all_metrics,
234+
key=lambda m: m.name,
235+
)
236+
237+
238+
@pytest.mark.asyncio
239+
@pytest.mark.parametrize(
240+
"env_var",
241+
["OTEL_PYTHON_AIOHTTP_SERVER_EXCLUDED_URLS", "OTEL_PYTHON_EXCLUDED_URLS"],
242+
)
243+
async def test_excluded_urls(
244+
tracer, meter, aiohttp_server, monkeypatch, env_var
245+
):
246+
"""Test that excluded env vars are taken into account."""
247+
_, memory_exporter = tracer
248+
_, metrics_reader = meter
249+
250+
monkeypatch.setenv(env_var, "/status/200")
251+
AioHttpServerInstrumentor().instrument()
252+
253+
app = aiohttp.web.Application()
254+
255+
async def handler(request):
256+
return aiohttp.web.Response(text="hello")
257+
258+
app.router.add_get("/status/200", handler)
259+
260+
server = await aiohttp_server(app)
261+
262+
url = f"http://{server.host}:{server.port}/status/200"
263+
async with aiohttp.ClientSession() as session:
264+
async with session.get(url) as response:
265+
assert response.status == 200
266+
assert await response.text() == "hello"
267+
268+
spans = memory_exporter.get_finished_spans()
269+
assert len(spans) == 0
270+
271+
metrics = _get_sorted_metrics(metrics_reader.get_metrics_data())
272+
assert len(metrics) == 0
273+
274+
AioHttpServerInstrumentor().uninstrument()

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

Lines changed: 58 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,10 @@
1313
# limitations under the License.
1414

1515
"""
16-
The integration with PostgreSQL supports the `Psycopg`_ library, it can be enabled by
16+
The integration with PostgreSQL supports the `Psycopg`_ library. It can be enabled by
1717
using ``PsycopgInstrumentor``.
1818
19-
.. _Psycopg: http://initd.org/psycopg/
19+
.. _Psycopg: https://www.psycopg.org/psycopg3/docs/
2020
2121
Usage
2222
-----
@@ -55,84 +55,87 @@
5555
Configuration
5656
-------------
5757
58-
SQLCOMMENTER
59-
*****************************************
58+
SQLCommenter
59+
************
6060
You can optionally configure Psycopg instrumentation to enable sqlcommenter which enriches
61-
the query with contextual information.
61+
the query with contextual information. Queries made after setting up trace integration with
62+
sqlcommenter enabled will have configurable key-value pairs appended to them, e.g.
63+
``"select * from auth_users; /*traceparent=00-01234567-abcd-01*/"``. This supports context
64+
propagation between database client and server when database log records are enabled.
65+
For more information, see:
66+
67+
* `Semantic Conventions - Database Spans <https://github.com/open-telemetry/semantic-conventions/blob/main/docs/database/database-spans.md#sql-commenter>`_
68+
* `sqlcommenter <https://google.github.io/sqlcommenter/>`_
6269
6370
.. code:: python
6471
6572
from opentelemetry.instrumentation.psycopg import PsycopgInstrumentor
6673
67-
PsycopgInstrumentor().instrument(enable_commenter=True, commenter_options={})
68-
69-
70-
For example,
71-
::
72-
73-
Invoking cursor.execute("select * from auth_users") will lead to sql query "select * from auth_users" but when SQLCommenter is enabled
74-
the query will get appended with some configurable tags like "select * from auth_users /*tag=value*/;"
75-
76-
77-
SQLCommenter Configurations
78-
***************************
79-
We can configure the tags to be appended to the sqlquery log by adding configuration inside commenter_options(default:{}) keyword
80-
81-
db_driver = True(Default) or False
82-
83-
For example,
84-
::
85-
Enabling this flag will add psycopg and it's version which is /*psycopg%%3A2.9.3*/
86-
87-
dbapi_threadsafety = True(Default) or False
88-
89-
For example,
90-
::
91-
Enabling this flag will add threadsafety /*dbapi_threadsafety=2*/
74+
PsycopgInstrumentor().instrument(enable_commenter=True)
9275
93-
dbapi_level = True(Default) or False
9476
95-
For example,
96-
::
97-
Enabling this flag will add dbapi_level /*dbapi_level='2.0'*/
77+
SQLCommenter with commenter_options
78+
***********************************
79+
The key-value pairs appended to the query can be configured using
80+
``commenter_options``. When sqlcommenter is enabled, all available KVs/tags
81+
are calculated by default. ``commenter_options`` supports *opting out*
82+
of specific KVs.
9883
99-
libpq_version = True(Default) or False
100-
101-
For example,
102-
::
103-
Enabling this flag will add libpq_version /*libpq_version=140001*/
104-
105-
driver_paramstyle = True(Default) or False
84+
.. code:: python
10685
107-
For example,
108-
::
109-
Enabling this flag will add driver_paramstyle /*driver_paramstyle='pyformat'*/
86+
from opentelemetry.instrumentation.psycopg import PsycopgInstrumentor
11087
111-
opentelemetry_values = True(Default) or False
88+
# Opts into sqlcomment for Psycopg trace integration.
89+
# Opts out of tags for libpq_version, db_driver.
90+
PsycopgInstrumentor().instrument(
91+
enable_commenter=True,
92+
commenter_options={
93+
"libpq_version": False,
94+
"db_driver": False,
95+
}
96+
)
11297
113-
For example,
114-
::
115-
Enabling this flag will add traceparent values /*traceparent='00-03afa25236b8cd948fa853d67038ac79-405ff022e8247c46-01'*/
98+
Available commenter_options
99+
###########################
100+
101+
The following sqlcomment key-values can be opted out of through ``commenter_options``:
102+
103+
+---------------------------+-----------------------------------------------------------+---------------------------------------------------------------------------+
104+
| Commenter Option | Description | Example |
105+
+===========================+===========================================================+===========================================================================+
106+
| ``db_driver`` | Database driver name with version. | ``psycopg='3.1.9'`` |
107+
+---------------------------+-----------------------------------------------------------+---------------------------------------------------------------------------+
108+
| ``dbapi_threadsafety`` | DB-API threadsafety value: 0-3 or unknown. | ``dbapi_threadsafety=2`` |
109+
+---------------------------+-----------------------------------------------------------+---------------------------------------------------------------------------+
110+
| ``dbapi_level`` | DB-API API level: 1.0, 2.0, or unknown. | ``dbapi_level='2.0'`` |
111+
+---------------------------+-----------------------------------------------------------+---------------------------------------------------------------------------+
112+
| ``driver_paramstyle`` | DB-API paramstyle for SQL statement parameter. | ``driver_paramstyle='pyformat'`` |
113+
+---------------------------+-----------------------------------------------------------+---------------------------------------------------------------------------+
114+
| ``libpq_version`` | PostgreSQL libpq version | ``libpq_version=140001`` |
115+
+---------------------------+-----------------------------------------------------------+---------------------------------------------------------------------------+
116+
| ``opentelemetry_values`` | OpenTelemetry context as traceparent at time of query. | ``traceparent='00-03afa25236b8cd948fa853d67038ac79-405ff022e8247c46-01'`` |
117+
+---------------------------+-----------------------------------------------------------+---------------------------------------------------------------------------+
116118
117119
SQLComment in span attribute
118120
****************************
119-
If sqlcommenter is enabled, you can optionally configure psycopg instrumentation to append sqlcomment to query span attribute for convenience of your platform.
121+
If sqlcommenter is enabled, you can opt into the inclusion of sqlcomment in
122+
the query span ``db.statement`` attribute for your needs. If ``commenter_options``
123+
have been set, the span attribute comment will also be configured by this
124+
setting.
120125
121126
.. code:: python
122127
123128
from opentelemetry.instrumentation.psycopg import PsycopgInstrumentor
124129
130+
# Opts into sqlcomment for Psycopg trace integration.
131+
# Opts into sqlcomment for `db.statement` span attribute.
125132
PsycopgInstrumentor().instrument(
126133
enable_commenter=True,
127134
enable_attribute_commenter=True,
128135
)
129136
130-
For example,
131-
::
132-
133-
Invoking cursor.execute("select * from auth_users") will lead to postgresql query "select * from auth_users" but when SQLCommenter and attribute_commenter are enabled
134-
the query will get appended with some configurable tags like "select * from auth_users /*tag=value*/;" for both server query and `db.statement` span attribute.
135-
137+
Warning:
138+
Capture of sqlcomment in ``db.statement`` may have high cardinality without platform normalization. See `Semantic Conventions for database spans <https://opentelemetry.io/docs/specs/semconv/database/database-spans/#generating-a-summary-of-the-query-text>`_ for more information.
136139
137140
API
138141
---

instrumentation/opentelemetry-instrumentation-psycopg2/README.rst

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
OpenTelemetry Psycopg Instrumentation
2-
=====================================
1+
OpenTelemetry Psycopg2 Instrumentation
2+
======================================
33

44
|pypi|
55

@@ -16,6 +16,6 @@ Installation
1616

1717
References
1818
----------
19-
* `OpenTelemetry Psycopg Instrumentation <https://opentelemetry-python-contrib.readthedocs.io/en/latest/instrumentation/psycopg2/psycopg2.html>`_
19+
* `OpenTelemetry Psycopg2 Instrumentation <https://opentelemetry-python-contrib.readthedocs.io/en/latest/instrumentation/psycopg2/psycopg2.html>`_
2020
* `OpenTelemetry Project <https://opentelemetry.io/>`_
2121
* `OpenTelemetry Python Examples <https://github.com/open-telemetry/opentelemetry-python/tree/main/docs/examples>`_

0 commit comments

Comments
 (0)