Skip to content

Commit ffc043b

Browse files
authored
Merge branch 'main' into feature/asyncio-instrumentation
2 parents b4ffc63 + 4bf3577 commit ffc043b

File tree

84 files changed

+1383
-478
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

84 files changed

+1383
-478
lines changed

.github/workflows/test.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ on:
66
- 'release/*'
77
pull_request:
88
env:
9-
CORE_REPO_SHA: 9831afaff5b4d371fd9a14266ab47884546bd971
9+
CORE_REPO_SHA: 35a021194787359324c46f5ca99d31802e4c92bd
1010

1111
jobs:
1212
build:

.pylintrc

+3-10
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
# A comma-separated list of package or module names from where C extensions may
44
# be loaded. Extensions are loading into the active Python interpreter and may
55
# run arbitrary code.
6-
extension-pkg-whitelist=
6+
extension-pkg-whitelist=cassandra
77

88
# Add list of files or directories to be excluded. They should be base names, not
99
# paths.
@@ -29,7 +29,7 @@ limit-inference-results=100
2929

3030
# List of plugins (as comma separated values of python modules names) to load,
3131
# usually to register additional checkers.
32-
load-plugins=
32+
load-plugins=pylint.extensions.no_self_use
3333

3434
# Pickle collected data for later comparisons.
3535
persistent=yes
@@ -69,7 +69,6 @@ disable=missing-docstring,
6969
duplicate-code,
7070
ungrouped-imports, # Leave this up to isort
7171
wrong-import-order, # Leave this up to isort
72-
bad-continuation, # Leave this up to black
7372
line-too-long, # Leave this up to black
7473
exec-used,
7574
super-with-arguments, # temp-pylint-upgrade
@@ -81,6 +80,7 @@ disable=missing-docstring,
8180
invalid-overridden-method, # temp-pylint-upgrade
8281
missing-module-docstring, # temp-pylint-upgrade
8382
import-error, # needed as a workaround as reported here: https://github.com/open-telemetry/opentelemetry-python-contrib/issues/290
83+
cyclic-import,
8484

8585
# Enable the message, report, category or checker with the given id(s). You can
8686
# either give multiple identifier separated by comma (,) or put this option
@@ -268,13 +268,6 @@ max-line-length=79
268268
# Maximum number of lines in a module.
269269
max-module-lines=1000
270270

271-
# List of optional constructs for which whitespace checking is disabled. `dict-
272-
# separator` is used to allow tabulation in dicts, etc.: {1 : 1,\n222: 2}.
273-
# `trailing-comma` allows a space between comma and closing bracket: (a, ).
274-
# `empty-line` allows space-only lines.
275-
no-space-check=trailing-comma,
276-
dict-separator
277-
278271
# Allow the body of a class to be on the same line as the declaration if body
279272
# contains single statement.
280273
single-line-class-stmt=no

CHANGELOG.md

+13
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1212
([#1919](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1943))
1313
- `opentelemetry-instrumentation` Added Otel semantic convention opt-in mechanism
1414
([#1987](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1987))
15+
- `opentelemetry-instrumentation-httpx` Fix mixing async and non async hooks
16+
([#1920](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1920))
17+
- `opentelemetry-instrumentation-requests` Implement new semantic convention opt-in with stable http semantic conventions
18+
([#2002](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2002))
19+
- `opentelemetry-instrument-grpc` Fix arity of context.abort for AIO RPCs
20+
([#2066](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2066))
1521

22+
### Fixed
23+
24+
- `opentelemetry-instrumentation-urllib`/`opentelemetry-instrumentation-urllib3` Fix metric descriptions to match semantic conventions
25+
([#1959](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1959))
26+
1627
## Version 1.21.0/0.42b0 (2023-11-01)
1728

1829
### Added
@@ -28,6 +39,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
2839

2940
### Fixed
3041

42+
- `opentelemetry-instrumentation-aio-pika` and `opentelemetry-instrumentation-pika` Fix missing trace context propagation when trace not recording.
43+
([#1969](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1969))
3144
- Fix version of Flask dependency `werkzeug`
3245
([#1980](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1980))
3346
- `opentelemetry-resource-detector-azure` Using new Cloud Resource ID attribute.

CONTRIBUTING.md

+5-1
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,13 @@ An easier way to do so is:
5252
2. Run `.tox/lint/bin/isort .`
5353

5454
See
55-
[`tox.ini`](https://github.com/open-telemetry/opentelemetry-python/blob/main/tox.ini)
55+
[`tox.ini`](https://github.com/open-telemetry/opentelemetry-python-contrib/blob/main/tox.ini)
5656
for more detail on available tox commands.
5757

58+
### Troubleshooting
59+
60+
- Some packages may require additional system wide dependencies to be installed. For example, you may need to install `libpq-dev` to run the postgresql client libraries instrumentation tests. or `libsnappy-dev` to run the prometheus exporter tests. If you encounter a build error, please check the installation instructions for the package you are trying to run tests for.
61+
5862
### Benchmarks
5963

6064
Performance progression of benchmarks for packages distributed by OpenTelemetry Python can be viewed as a [graph of throughput vs commit history](https://opentelemetry-python-contrib.readthedocs.io/en/latest/performance/benchmarks.html). From the linked page, you can download a JSON file with the performance results.

dev-requirements.txt

+13-14
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,19 @@
1-
pylint==2.12.2
2-
flake8~=3.7
3-
isort~=5.6
4-
black>=22.1.0
5-
httpretty~=1.0
6-
mypy==0.790
7-
sphinx
8-
sphinx-rtd-theme~=0.4
9-
sphinx-autodoc-typehints
10-
pytest!=5.2.3
11-
pytest-cov>=2.8
12-
readme-renderer~=24.0
1+
pylint==3.0.2
2+
flake8==6.1.0
3+
isort==5.12.0
4+
black==22.3.0
5+
httpretty==1.1.4
6+
mypy==0.931
7+
sphinx==7.1.2
8+
sphinx-rtd-theme==2.0.0rc4
9+
sphinx-autodoc-typehints==1.25.2
10+
pytest==7.1.3
11+
pytest-cov==4.1.0
12+
readme-renderer==42.0
1313
bleach==4.1.0 # transient dependency for readme-renderer
14-
grpcio-tools==1.29.0
15-
mypy-protobuf>=1.23
1614
protobuf~=3.13
1715
markupsafe>=2.0.1
1816
codespell==2.1.0
1917
requests==2.31.0
2018
ruamel.yaml==0.17.21
19+
flaky==3.7.0

docs-requirements.txt

+3-6
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
sphinx==4.5.0
2-
sphinx-rtd-theme~=0.4
3-
sphinx-autodoc-typehints
1+
sphinx==7.1.2
2+
sphinx-rtd-theme==2.0.0rc4
3+
sphinx-autodoc-typehints==1.25.2
44

55
# Need to install the api/sdk in the venv for autodoc. Modifying sys.path
66
# doesn't work for pkg_resources.
@@ -45,11 +45,8 @@ remoulade>=0.50
4545
sqlalchemy>=1.0
4646
tornado>=5.1.1
4747
tortoise-orm>=0.17.0
48-
ddtrace>=0.34.0
4948
httpx>=0.18.0
5049

5150
# indirect dependency pins
5251
markupsafe==2.0.1
5352
itsdangerous==2.0.1
54-
55-
docutils==0.16

eachdist.ini

+1
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ packages=
5454
[lintroots]
5555
extraroots=examples/*,scripts/
5656
subglob=*.py,tests/,test/,src/*,examples/*
57+
ignore=sklearn
5758

5859
[testroots]
5960
extraroots=examples/*,tests/

exporter/opentelemetry-exporter-prometheus-remote-write/tests/conftest.py

+2
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
import pytest
44

55
import opentelemetry.test.metrictestutil as metric_util
6+
7+
# pylint: disable=no-name-in-module
68
from opentelemetry.exporter.prometheus_remote_write import (
79
PrometheusRemoteWriteMetricsExporter,
810
)

exporter/opentelemetry-exporter-prometheus-remote-write/tests/test_prometheus_remote_write_exporter.py

+1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
import pytest
1919

20+
# pylint: disable=no-name-in-module
2021
from opentelemetry.exporter.prometheus_remote_write import (
2122
PrometheusRemoteWriteMetricsExporter,
2223
)

instrumentation/opentelemetry-instrumentation-aio-pika/src/opentelemetry/instrumentation/aio_pika/publish_decorator.py

+1-2
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,7 @@ async def decorated_publish(
4545
if not span:
4646
return await publish(message, routing_key, **kwargs)
4747
with trace.use_span(span, end_on_exit=True):
48-
if span.is_recording():
49-
propagate.inject(message.properties.headers)
48+
propagate.inject(message.properties.headers)
5049
return_value = await publish(message, routing_key, **kwargs)
5150
return return_value
5251

instrumentation/opentelemetry-instrumentation-aio-pika/tests/test_publish_decorator.py

+61
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import asyncio
1515
from typing import Type
1616
from unittest import TestCase, mock, skipIf
17+
from unittest.mock import MagicMock
1718

1819
from aio_pika import Exchange, RobustExchange
1920

@@ -92,6 +93,36 @@ def test_publish(self):
9293
def test_robust_publish(self):
9394
self._test_publish(RobustExchange)
9495

96+
def _test_publish_works_with_not_recording_span(self, exchange_type):
97+
exchange = exchange_type(CONNECTION_7, CHANNEL_7, EXCHANGE_NAME)
98+
with mock.patch.object(
99+
PublishDecorator, "_get_publish_span"
100+
) as mock_get_publish_span:
101+
mocked_not_recording_span = MagicMock()
102+
mocked_not_recording_span.is_recording.return_value = False
103+
mock_get_publish_span.return_value = mocked_not_recording_span
104+
with mock.patch.object(
105+
Exchange, "publish", return_value=asyncio.sleep(0)
106+
) as mock_publish:
107+
with mock.patch(
108+
"opentelemetry.instrumentation.aio_pika.publish_decorator.propagate.inject"
109+
) as mock_inject:
110+
decorated_publish = PublishDecorator(
111+
self.tracer, exchange
112+
).decorate(mock_publish)
113+
self.loop.run_until_complete(
114+
decorated_publish(MESSAGE, ROUTING_KEY)
115+
)
116+
mock_publish.assert_called_once()
117+
mock_get_publish_span.assert_called_once()
118+
mock_inject.assert_called_once()
119+
120+
def test_publish_works_with_not_recording_span(self):
121+
self._test_publish_works_with_not_recording_span(Exchange)
122+
123+
def test_publish_works_with_not_recording_span_robust(self):
124+
self._test_publish_works_with_not_recording_span(RobustExchange)
125+
95126

96127
@skipIf(AIOPIKA_VERSION_INFO <= (8, 0), "Only for aio_pika 8")
97128
class TestInstrumentedExchangeAioRmq8(TestCase):
@@ -144,3 +175,33 @@ def test_publish(self):
144175

145176
def test_robust_publish(self):
146177
self._test_publish(RobustExchange)
178+
179+
def _test_publish_works_with_not_recording_span(self, exchange_type):
180+
exchange = exchange_type(CONNECTION_7, CHANNEL_7, EXCHANGE_NAME)
181+
with mock.patch.object(
182+
PublishDecorator, "_get_publish_span"
183+
) as mock_get_publish_span:
184+
mocked_not_recording_span = MagicMock()
185+
mocked_not_recording_span.is_recording.return_value = False
186+
mock_get_publish_span.return_value = mocked_not_recording_span
187+
with mock.patch.object(
188+
Exchange, "publish", return_value=asyncio.sleep(0)
189+
) as mock_publish:
190+
with mock.patch(
191+
"opentelemetry.instrumentation.aio_pika.publish_decorator.propagate.inject"
192+
) as mock_inject:
193+
decorated_publish = PublishDecorator(
194+
self.tracer, exchange
195+
).decorate(mock_publish)
196+
self.loop.run_until_complete(
197+
decorated_publish(MESSAGE, ROUTING_KEY)
198+
)
199+
mock_publish.assert_called_once()
200+
mock_get_publish_span.assert_called_once()
201+
mock_inject.assert_called_once()
202+
203+
def test_publish_works_with_not_recording_span(self):
204+
self._test_publish_works_with_not_recording_span(Exchange)
205+
206+
def test_publish_works_with_not_recording_span_robust(self):
207+
self._test_publish_works_with_not_recording_span(RobustExchange)

instrumentation/opentelemetry-instrumentation-aiohttp-client/tests/test_aiohttp_client_integration.py

+9-3
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
import asyncio
1616
import contextlib
17+
import sys
1718
import typing
1819
import unittest
1920
import urllib.parse
@@ -116,14 +117,19 @@ def test_status_codes(self):
116117
status_code=status_code,
117118
)
118119

120+
url = f"http://{host}:{port}/test-path?query=param#foobar"
121+
# if python version is < 3.8, then the url will be
122+
if sys.version_info[1] < 8:
123+
url = f"http://{host}:{port}/test-path#foobar"
124+
119125
self.assert_spans(
120126
[
121127
(
122128
"GET",
123129
(span_status, None),
124130
{
125131
SpanAttributes.HTTP_METHOD: "GET",
126-
SpanAttributes.HTTP_URL: f"http://{host}:{port}/test-path#foobar",
132+
SpanAttributes.HTTP_URL: url,
127133
SpanAttributes.HTTP_STATUS_CODE: int(
128134
status_code
129135
),
@@ -136,7 +142,7 @@ def test_status_codes(self):
136142

137143
def test_schema_url(self):
138144
with self.subTest(status_code=200):
139-
host, port = self._http_request(
145+
self._http_request(
140146
trace_config=aiohttp_client.create_trace_config(),
141147
url="/test-path?query=param#foobar",
142148
status_code=200,
@@ -156,7 +162,7 @@ def test_not_recording(self):
156162
mock_tracer.start_span.return_value = mock_span
157163
with mock.patch("opentelemetry.trace.get_tracer"):
158164
# pylint: disable=W0612
159-
host, port = self._http_request(
165+
self._http_request(
160166
trace_config=aiohttp_client.create_trace_config(),
161167
url="/test-path?query=param#foobar",
162168
)

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

+8-8
Original file line numberDiff line numberDiff line change
@@ -13,24 +13,24 @@
1313
# limitations under the License.
1414

1515
import urllib
16+
from timeit import default_timer
17+
from typing import Dict, List, Tuple, Union
18+
1619
from aiohttp import web
1720
from multidict import CIMultiDictProxy
18-
from timeit import default_timer
19-
from typing import Tuple, Dict, List, Union
2021

21-
from opentelemetry import context, trace, metrics
22+
from opentelemetry import context, metrics, trace
2223
from opentelemetry.context import _SUPPRESS_HTTP_INSTRUMENTATION_KEY
2324
from opentelemetry.instrumentation.aiohttp_server.package import _instruments
2425
from opentelemetry.instrumentation.aiohttp_server.version import __version__
2526
from opentelemetry.instrumentation.instrumentor import BaseInstrumentor
2627
from opentelemetry.instrumentation.utils import http_status_to_status_code
27-
from opentelemetry.propagators.textmap import Getter
2828
from opentelemetry.propagate import extract
29-
from opentelemetry.semconv.trace import SpanAttributes
29+
from opentelemetry.propagators.textmap import Getter
3030
from opentelemetry.semconv.metrics import MetricInstruments
31+
from opentelemetry.semconv.trace import SpanAttributes
3132
from opentelemetry.trace.status import Status, StatusCode
32-
from opentelemetry.util.http import get_excluded_urls
33-
from opentelemetry.util.http import remove_url_credentials
33+
from opentelemetry.util.http import get_excluded_urls, remove_url_credentials
3434

3535
_duration_attrs = [
3636
SpanAttributes.HTTP_METHOD,
@@ -127,7 +127,7 @@ def collect_request_attributes(request: web.Request) -> Dict:
127127
result[SpanAttributes.HTTP_METHOD] = http_method
128128

129129
http_host_value_list = (
130-
[request.host] if type(request.host) != list else request.host
130+
[request.host] if not isinstance(request.host, list) else request.host
131131
)
132132
if http_host_value_list:
133133
result[SpanAttributes.HTTP_SERVER_NAME] = ",".join(

0 commit comments

Comments
 (0)