Skip to content

Commit 8a1cf98

Browse files
committed
2 parents ac9ec26 + 2138a8f commit 8a1cf98

File tree

73 files changed

+1514
-664
lines changed

Some content is hidden

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

73 files changed

+1514
-664
lines changed

CHANGELOG.md

+45-2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,37 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

88
## Unreleased
9+
- `opentelemetry-instrumentation-asgi` Add `http.server.request.size` metric
10+
([#1867](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1867))
11+
12+
### Fixed
13+
14+
- Fix elastic-search instrumentation sanitization to support bulk queries
15+
([#1870](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1870))
16+
- Update falcon instrumentation to follow semantic conventions
17+
([#1824](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1824))
18+
- Fix sqlalchemy instrumentation wrap methods to accept sqlcommenter options([#1873](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1873))
19+
20+
### Added
21+
22+
- Fix async redis clients not being traced correctly ([#1830](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1830))
23+
- Make Flask request span attributes available for `start_span`.
24+
([#1784](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1784))
25+
- Fix falcon instrumentation's usage of Span Status to only set the description if the status code is ERROR.
26+
([#1840](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1840))
27+
- Instrument all httpx versions >= 0.18. ([#1748](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1748))
28+
- Fix `Invalid type NoneType for attribute X (opentelemetry-instrumentation-aws-lambda)` error when some attributes do not exist
29+
([#1780](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1780))
30+
- Add metric instrumentation for celery
31+
([#1679](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1679))
32+
- `opentelemetry-instrumentation-asgi` Add `http.server.response.size` metric
33+
([#1789](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1789))
34+
- `opentelemetry-instrumentation-grpc` Allow gRPC connections via Unix socket
35+
([#1833](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1833))
36+
- Fix elasticsearch `Transport.perform_request` instrument wrap for elasticsearch >= 8
37+
([#1810](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1810))
38+
- `opentelemetry-instrumentation-urllib3` Add support for urllib3 version 2
39+
([#1879](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1879))
940

1041
### Added
1142
- `opentelemetry-instrumentation-kafka-python` Add instrumentation to `consume` method
@@ -16,18 +47,22 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1647
- `opentelemetry-instrumentation-system-metrics` Add `process.` prefix to `runtime.memory`, `runtime.cpu.time`, and `runtime.gc_count`. Change `runtime.memory` from count to UpDownCounter. ([#1735](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1735))
1748
- Add request and response hooks for GRPC instrumentation (client only)
1849
([#1706](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1706))
50+
- Fix memory leak in SQLAlchemy instrumentation where disposed `Engine` does not get garbage collected
51+
([#1771](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1771)
1952
- `opentelemetry-instrumentation-pymemcache` Update instrumentation to support pymemcache >4
2053
([#1764](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1764))
54+
- `opentelemetry-instrumentation-confluent-kafka` Add support for higher versions of confluent_kafka
55+
([#1815](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1815))
2156

2257
### Added
2358

2459
- Expand sqlalchemy pool.name to follow the semantic conventions
2560
([#1778](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1778))
2661
- Add `excluded_urls` functionality to `urllib` and `urllib3` instrumentations
2762
([#1733](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1733))
28-
- Make Django request span attributes available for `start_span`.
63+
- Make Django request span attributes available for `start_span`.
2964
([#1730](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1730))
30-
- Make ASGI request span attributes available for `start_span`.
65+
- Make ASGI request span attributes available for `start_span`.
3166
([#1762](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1762))
3267
- `opentelemetry-instrumentation-celery` Add support for anonymous tasks.
3368
([#1407](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1407))
@@ -42,12 +77,20 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
4277

4378
### Fixed
4479

80+
- Fix redis db.statements to be sanitized by default
81+
([#1778](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1778))
4582
- Fix elasticsearch db.statement attribute to be sanitized by default
4683
([#1758](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1758))
4784
- Fix `AttributeError` when AWS Lambda handler receives a list event
4885
([#1738](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1738))
4986
- Fix `None does not implement middleware` error when there are no middlewares registered
5087
([#1766](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1766))
88+
- Fix Flask instrumentation to only close the span if it was created by the same request context.
89+
([#1692](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1692))
90+
91+
### Changed
92+
- Update HTTP server/client instrumentation span names to comply with spec
93+
([#1759](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1759)
5194

5295
## Version 1.17.0/0.38b0 (2023-03-22)
5396

README.md

+3-1
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ depend on `opentelemetry-sdk` or another package that implements the API.
4949
**Please note** that these libraries are currently in _beta_, and shouldn't
5050
generally be used in production environments.
5151

52+
Unless explicitly stated otherwise, any instrumentation here for a particular library is not developed or maintained by the authors of such library.
53+
5254
The
5355
[`instrumentation/`](https://github.com/open-telemetry/opentelemetry-python-contrib/tree/main/instrumentation)
5456
directory includes OpenTelemetry instrumentation packages, which can be installed
@@ -97,7 +99,6 @@ Approvers ([@open-telemetry/python-approvers](https://github.com/orgs/open-telem
9799
- [Aaron Abbott](https://github.com/aabmass), Google
98100
- [Jeremy Voss](https://github.com/jeremydvoss), Microsoft
99101
- [Sanket Mehta](https://github.com/sanketmehta28), Cisco
100-
- [Shalev Roda](https://github.com/shalevr), Cisco
101102

102103
Emeritus Approvers:
103104

@@ -112,6 +113,7 @@ Maintainers ([@open-telemetry/python-maintainers](https://github.com/orgs/open-t
112113

113114
- [Diego Hurtado](https://github.com/ocelotl), Lightstep
114115
- [Leighton Chen](https://github.com/lzchen), Microsoft
116+
- [Shalev Roda](https://github.com/shalevr), Cisco
115117

116118
Emeritus Maintainers:
117119

dev-requirements.txt

+2-2
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ bleach==4.1.0 # transient dependency for readme-renderer
1414
grpcio-tools==1.29.0
1515
mypy-protobuf>=1.23
1616
protobuf~=3.13
17-
markupsafe==2.0.1
17+
markupsafe>=2.0.1
1818
codespell==2.1.0
19-
requests==2.28.1
19+
requests==2.31.0
2020
ruamel.yaml==0.17.21

docs-requirements.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ boto~=2.0
2626
botocore~=1.0
2727
boto3~=1.0
2828
celery>=4.0
29-
confluent-kafka>= 1.8.2,< 2.0.0
29+
confluent-kafka>= 1.8.2,<= 2.2.0
3030
elasticsearch>=2.0,<9.0
3131
flask~=2.0
3232
falcon~=2.0

instrumentation/README.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
| [opentelemetry-instrumentation-boto3sqs](./opentelemetry-instrumentation-boto3sqs) | boto3 ~= 1.0 | No
1212
| [opentelemetry-instrumentation-botocore](./opentelemetry-instrumentation-botocore) | botocore ~= 1.0 | No
1313
| [opentelemetry-instrumentation-celery](./opentelemetry-instrumentation-celery) | celery >= 4.0, < 6.0 | No
14-
| [opentelemetry-instrumentation-confluent-kafka](./opentelemetry-instrumentation-confluent-kafka) | confluent-kafka >= 1.8.2, < 2.0.0 | No
14+
| [opentelemetry-instrumentation-confluent-kafka](./opentelemetry-instrumentation-confluent-kafka) | confluent-kafka >= 1.8.2, <= 2.2.0 | No
1515
| [opentelemetry-instrumentation-dbapi](./opentelemetry-instrumentation-dbapi) | dbapi | No
1616
| [opentelemetry-instrumentation-django](./opentelemetry-instrumentation-django) | django >= 1.10 | Yes
1717
| [opentelemetry-instrumentation-elasticsearch](./opentelemetry-instrumentation-elasticsearch) | elasticsearch >= 2.0 | No
@@ -41,5 +41,5 @@
4141
| [opentelemetry-instrumentation-tornado](./opentelemetry-instrumentation-tornado) | tornado >= 5.1.1 | Yes
4242
| [opentelemetry-instrumentation-tortoiseorm](./opentelemetry-instrumentation-tortoiseorm) | tortoise-orm >= 0.17.0 | No
4343
| [opentelemetry-instrumentation-urllib](./opentelemetry-instrumentation-urllib) | urllib | Yes
44-
| [opentelemetry-instrumentation-urllib3](./opentelemetry-instrumentation-urllib3) | urllib3 >= 1.0.0, < 2.0.0 | Yes
44+
| [opentelemetry-instrumentation-urllib3](./opentelemetry-instrumentation-urllib3) | urllib3 >= 1.0.0, < 3.0.0 | Yes
4545
| [opentelemetry-instrumentation-wsgi](./opentelemetry-instrumentation-wsgi) | wsgi | Yes

instrumentation/opentelemetry-instrumentation-aiohttp-client/pyproject.toml

+1
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ instruments = [
3838
]
3939
test = [
4040
"opentelemetry-instrumentation-aiohttp-client[instruments]",
41+
"http-server-mock"
4142
]
4243

4344
[project.entry-points.opentelemetry_instrumentor]

instrumentation/opentelemetry-instrumentation-aiohttp-client/src/opentelemetry/instrumentation/aiohttp_client/__init__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,7 @@ async def on_request_start(
179179
return
180180

181181
http_method = params.method.upper()
182-
request_span_name = f"HTTP {http_method}"
182+
request_span_name = f"{http_method}"
183183
request_url = (
184184
remove_url_credentials(trace_config_ctx.url_filter(params.url))
185185
if callable(trace_config_ctx.url_filter)

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

+29-17
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import aiohttp
2424
import aiohttp.test_utils
2525
import yarl
26+
from http_server_mock import HttpServerMock
2627
from pkg_resources import iter_entry_points
2728

2829
from opentelemetry import context
@@ -118,7 +119,7 @@ def test_status_codes(self):
118119
self.assert_spans(
119120
[
120121
(
121-
"HTTP GET",
122+
"GET",
122123
(span_status, None),
123124
{
124125
SpanAttributes.HTTP_METHOD: "GET",
@@ -212,7 +213,7 @@ def strip_query_params(url: yarl.URL) -> str:
212213
self.assert_spans(
213214
[
214215
(
215-
"HTTP GET",
216+
"GET",
216217
(StatusCode.UNSET, None),
217218
{
218219
SpanAttributes.HTTP_METHOD: "GET",
@@ -246,7 +247,7 @@ async def do_request(url):
246247
self.assert_spans(
247248
[
248249
(
249-
"HTTP GET",
250+
"GET",
250251
(expected_status, None),
251252
{
252253
SpanAttributes.HTTP_METHOD: "GET",
@@ -273,7 +274,7 @@ async def request_handler(request):
273274
self.assert_spans(
274275
[
275276
(
276-
"HTTP GET",
277+
"GET",
277278
(StatusCode.ERROR, None),
278279
{
279280
SpanAttributes.HTTP_METHOD: "GET",
@@ -300,7 +301,7 @@ async def request_handler(request):
300301
self.assert_spans(
301302
[
302303
(
303-
"HTTP GET",
304+
"GET",
304305
(StatusCode.ERROR, None),
305306
{
306307
SpanAttributes.HTTP_METHOD: "GET",
@@ -313,27 +314,37 @@ async def request_handler(request):
313314
def test_credential_removal(self):
314315
trace_configs = [aiohttp_client.create_trace_config()]
315316

316-
url = "http://username:[email protected]/status/200"
317-
with self.subTest(url=url):
317+
app = HttpServerMock("test_credential_removal")
318318

319-
async def do_request(url):
320-
async with aiohttp.ClientSession(
321-
trace_configs=trace_configs,
322-
) as session:
323-
async with session.get(url):
324-
pass
319+
@app.route("/status/200")
320+
def index():
321+
return "hello"
325322

326-
loop = asyncio.get_event_loop()
327-
loop.run_until_complete(do_request(url))
323+
url = "http://username:password@localhost:5000/status/200"
324+
325+
with app.run("localhost", 5000):
326+
with self.subTest(url=url):
327+
328+
async def do_request(url):
329+
async with aiohttp.ClientSession(
330+
trace_configs=trace_configs,
331+
) as session:
332+
async with session.get(url):
333+
pass
334+
335+
loop = asyncio.get_event_loop()
336+
loop.run_until_complete(do_request(url))
328337

329338
self.assert_spans(
330339
[
331340
(
332-
"HTTP GET",
341+
"GET",
333342
(StatusCode.UNSET, None),
334343
{
335344
SpanAttributes.HTTP_METHOD: "GET",
336-
SpanAttributes.HTTP_URL: "http://httpbin.org/status/200",
345+
SpanAttributes.HTTP_URL: (
346+
"http://localhost:5000/status/200"
347+
),
337348
SpanAttributes.HTTP_STATUS_CODE: int(HTTPStatus.OK),
338349
},
339350
)
@@ -380,6 +391,7 @@ def test_instrument(self):
380391
self.get_default_request(), self.URL, self.default_handler
381392
)
382393
span = self.assert_spans(1)
394+
self.assertEqual("GET", span.name)
383395
self.assertEqual("GET", span.attributes[SpanAttributes.HTTP_METHOD])
384396
self.assertEqual(
385397
f"http://{host}:{port}/test-path",

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

+44-7
Original file line numberDiff line numberDiff line change
@@ -415,18 +415,23 @@ def set_status_code(span, status_code):
415415

416416

417417
def get_default_span_details(scope: dict) -> Tuple[str, dict]:
418-
"""Default implementation for get_default_span_details
418+
"""
419+
Default span name is the HTTP method and URL path, or just the method.
420+
https://github.com/open-telemetry/opentelemetry-specification/pull/3165
421+
https://opentelemetry.io/docs/reference/specification/trace/semantic_conventions/http/#name
422+
419423
Args:
420424
scope: the ASGI scope dictionary
421425
Returns:
422426
a tuple of the span name, and any attributes to attach to the span.
423427
"""
424-
span_name = (
425-
scope.get("path", "").strip()
426-
or f"HTTP {scope.get('method', '').strip()}"
427-
)
428-
429-
return span_name, {}
428+
path = scope.get("path", "").strip()
429+
method = scope.get("method", "").strip()
430+
if method and path: # http
431+
return f"{method} {path}", {}
432+
if path: # websocket
433+
return path, {}
434+
return method, {} # http with no path
430435

431436

432437
def _collect_target_attribute(
@@ -501,6 +506,16 @@ def __init__(
501506
unit="ms",
502507
description="measures the duration of the inbound HTTP request",
503508
)
509+
self.server_response_size_histogram = self.meter.create_histogram(
510+
name=MetricInstruments.HTTP_SERVER_RESPONSE_SIZE,
511+
unit="By",
512+
description="measures the size of HTTP response messages (compressed).",
513+
)
514+
self.server_request_size_histogram = self.meter.create_histogram(
515+
name=MetricInstruments.HTTP_SERVER_REQUEST_SIZE,
516+
unit="By",
517+
description="Measures the size of HTTP request messages (compressed).",
518+
)
504519
self.active_requests_counter = self.meter.create_up_down_counter(
505520
name=MetricInstruments.HTTP_SERVER_ACTIVE_REQUESTS,
506521
unit="requests",
@@ -513,6 +528,7 @@ def __init__(
513528
self.server_request_hook = server_request_hook
514529
self.client_request_hook = client_request_hook
515530
self.client_response_hook = client_response_hook
531+
self.content_length_header = None
516532

517533
async def __call__(self, scope, receive, send):
518534
"""The ASGI application
@@ -588,6 +604,20 @@ async def __call__(self, scope, receive, send):
588604
self.active_requests_counter.add(
589605
-1, active_requests_count_attrs
590606
)
607+
if self.content_length_header:
608+
self.server_response_size_histogram.record(
609+
self.content_length_header, duration_attrs
610+
)
611+
request_size = asgi_getter.get(scope, "content-length")
612+
if request_size:
613+
try:
614+
request_size_amount = int(request_size[0])
615+
except ValueError:
616+
pass
617+
else:
618+
self.server_request_size_histogram.record(
619+
request_size_amount, duration_attrs
620+
)
591621
if token:
592622
context.detach(token)
593623

@@ -655,6 +685,13 @@ async def otel_send(message):
655685
setter=asgi_setter,
656686
)
657687

688+
content_length = asgi_getter.get(message, "content-length")
689+
if content_length:
690+
try:
691+
self.content_length_header = int(content_length[0])
692+
except ValueError:
693+
pass
694+
658695
await send(message)
659696

660697
return otel_send

0 commit comments

Comments
 (0)