Skip to content

Commit 26b387c

Browse files
authored
Merge branch 'main' into antonpirker/run-tests-in-python-313
2 parents 7a311a5 + ca0dd50 commit 26b387c

File tree

25 files changed

+919
-141
lines changed

25 files changed

+919
-141
lines changed

.github/workflows/instrumentations_1.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,9 @@ jobs:
3939
- "resource-detector-azure"
4040
- "resource-detector-container"
4141
- "util-http"
42-
- "fastapi-slim"
42+
- "fastapislim"
4343
- "processor-baggage"
44+
- "kafka-pythonng"
4445
os: [ubuntu-20.04]
4546
exclude:
4647
- python-version: pypy3

CHANGELOG.md

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## Unreleased
99

10+
## Added
11+
12+
- `opentelemetry-instrumentation-kafka-python` Instrument temporary fork, kafka-python-ng
13+
inside kafka-python's instrumentation
14+
([#2537](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2537)))
15+
16+
## Breaking changes
17+
1018
## Fixed
1119

1220
- `opentelemetry-instrumentation-aws-lambda` Avoid exception when a handler is not present.
@@ -15,6 +23,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1523
([#2746](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2746))
1624
- `opentelemetry-instrumentation-grpc` Fixes the issue with the gRPC instrumentation not working with the 1.63.0 and higher version of gRPC
1725
([#2483](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2484))
26+
- `opentelemetry-instrumentation-fastapi` Fix fastapi-slim support
27+
([#2756](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2756))
28+
- `opentelemetry-instrumentation-aws-lambda` Fixing w3c baggage support
29+
([#2589](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2589))
30+
- `opentelemetry-instrumentation-celery` propagates baggage
31+
([#2385](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2385))
1832

1933
## Version 1.26.0/0.47b0 (2024-07-23)
2034

@@ -111,6 +125,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
111125
([#2610](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2610))
112126
- `opentelemetry-instrumentation-asgi` Bugfix: Middleware did not set status code attribute on duration metrics for non-recording spans.
113127
([#2627](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2627))
128+
- `opentelemetry-instrumentation-mysql` Add support for `mysql-connector-python` v9
129+
([#2751](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2751))
114130

115131
## Version 1.25.0/0.46b0 (2024-05-31)
116132

@@ -204,6 +220,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
204220
([#2367](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2367))
205221

206222

223+
### Added
224+
- `opentelemetry-instrumentation-fastapi` Add support for configuring header extraction via runtime constructor parameters
225+
([#2241](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2241))
226+
207227
## Version 1.23.0/0.44b0 (2024-02-23)
208228

209229
- Drop support for 3.7
@@ -224,6 +244,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
224244
### Added
225245

226246
- `opentelemetry-instrumentation-psycopg` Initial release for psycopg 3.x
247+
- `opentelemetry-instrumentation-asgi` Add support for configuring ASGI middleware header extraction via runtime constructor parameters
248+
([#2026](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2026))
227249

228250
## Version 1.22.0/0.43b0 (2023-12-14)
229251

@@ -263,8 +285,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
263285
([#1948](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1948))
264286
- Added schema_url (`"https://opentelemetry.io/schemas/1.11.0"`) to all metrics and traces
265287
([#1977](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1977))
266-
- Add support for configuring ASGI middleware header extraction via runtime constructor parameters
267-
([#2026](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2026))
268288

269289
### Fixed
270290

CONTRIBUTING.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,9 @@ The continuous integration overrides that environment variable with as per the c
250250
Below is a checklist of things to be mindful of when implementing a new instrumentation or working on a specific instrumentation. It is one of our goals as a community to keep the implementation specific details of instrumentations as similar across the board as possible for ease of testing and feature parity. It is also good to abstract as much common functionality as possible.
251251

252252
- Follow semantic conventions
253-
- The instrumentation should follow the semantic conventions defined [here](https://github.com/open-telemetry/semantic-conventions/tree/main/docs)
253+
- The instrumentation should follow the semantic conventions defined [here](https://github.com/open-telemetry/semantic-conventions/tree/main/docs).
254+
- To ensure consistency, we encourage contributions that align with [STABLE](https://opentelemetry.io/docs/specs/otel/document-status/#lifecycle-status) semantic conventions if available. This approach helps us avoid potential confusion and reduces the need to support multiple outdated versions of semantic conventions. However, we are still open to considering exceptional cases where changes are well justified.
255+
- Contributions related to outdated HTTP semantic conventions (conventions prior to becoming [stable](https://github.com/open-telemetry/semantic-conventions/tree/v1.23.0)) will likely be discouraged, as they increase complexity and the potential for misconceptions.
254256
- Contains a name that is not already claimed in [Pypi](https://pypi.org/). Contact a maintainer, bring the issue up in the weekly Python SIG or create a ticket in Pypi if a desired name has already been taken.
255257
- Extends from [BaseInstrumentor](https://github.com/open-telemetry/opentelemetry-python-contrib/blob/2518a4ac07cb62ad6587dd8f6cbb5f8663a7e179/opentelemetry-instrumentation/src/opentelemetry/instrumentation/instrumentor.py#L35)
256258
- Supports auto-instrumentation

instrumentation/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,9 @@
2424
| [opentelemetry-instrumentation-grpc](./opentelemetry-instrumentation-grpc) | grpcio ~= 1.27 | No | experimental
2525
| [opentelemetry-instrumentation-httpx](./opentelemetry-instrumentation-httpx) | httpx >= 0.18.0 | No | migration
2626
| [opentelemetry-instrumentation-jinja2](./opentelemetry-instrumentation-jinja2) | jinja2 >= 2.7, < 4.0 | No | experimental
27-
| [opentelemetry-instrumentation-kafka-python](./opentelemetry-instrumentation-kafka-python) | kafka-python >= 2.0 | No | experimental
27+
| [opentelemetry-instrumentation-kafka-python](./opentelemetry-instrumentation-kafka-python) | kafka-python >= 2.0, < 3.0,kafka-python-ng >= 2.0, < 3.0 | No | experimental
2828
| [opentelemetry-instrumentation-logging](./opentelemetry-instrumentation-logging) | logging | No | experimental
29-
| [opentelemetry-instrumentation-mysql](./opentelemetry-instrumentation-mysql) | mysql-connector-python ~= 8.0 | No | experimental
29+
| [opentelemetry-instrumentation-mysql](./opentelemetry-instrumentation-mysql) | mysql-connector-python >= 8.0, < 10.0 | No | experimental
3030
| [opentelemetry-instrumentation-mysqlclient](./opentelemetry-instrumentation-mysqlclient) | mysqlclient < 3 | No | experimental
3131
| [opentelemetry-instrumentation-pika](./opentelemetry-instrumentation-pika) | pika >= 0.12.0 | No | experimental
3232
| [opentelemetry-instrumentation-psycopg](./opentelemetry-instrumentation-psycopg) | psycopg >= 3.1.0 | No | experimental

instrumentation/opentelemetry-instrumentation-aws-lambda/src/opentelemetry/instrumentation/aws_lambda/__init__.py

Lines changed: 66 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ def custom_event_context_extractor(lambda_event):
7676

7777
from wrapt import wrap_function_wrapper
7878

79+
from opentelemetry import context as context_api
7980
from opentelemetry.context.context import Context
8081
from opentelemetry.instrumentation.aws_lambda.package import _instruments
8182
from opentelemetry.instrumentation.aws_lambda.version import __version__
@@ -303,66 +304,75 @@ def _instrumented_lambda_handler_call( # noqa pylint: disable=too-many-branches
303304
schema_url="https://opentelemetry.io/schemas/1.11.0",
304305
)
305306

306-
with tracer.start_as_current_span(
307-
name=orig_handler_name,
308-
context=parent_context,
309-
kind=span_kind,
310-
) as span:
311-
if span.is_recording():
312-
lambda_context = args[1]
313-
# NOTE: The specs mention an exception here, allowing the
314-
# `SpanAttributes.CLOUD_RESOURCE_ID` attribute to be set as a span
315-
# attribute instead of a resource attribute.
316-
#
317-
# See more:
318-
# https://github.com/open-telemetry/semantic-conventions/blob/main/docs/faas/aws-lambda.md#resource-detector
319-
span.set_attribute(
320-
SpanAttributes.CLOUD_RESOURCE_ID,
321-
lambda_context.invoked_function_arn,
322-
)
323-
span.set_attribute(
324-
SpanAttributes.FAAS_INVOCATION_ID,
325-
lambda_context.aws_request_id,
326-
)
327-
328-
# NOTE: `cloud.account.id` can be parsed from the ARN as the fifth item when splitting on `:`
329-
#
330-
# See more:
331-
# https://github.com/open-telemetry/semantic-conventions/blob/main/docs/faas/aws-lambda.md#all-triggers
332-
account_id = lambda_context.invoked_function_arn.split(":")[4]
333-
span.set_attribute(
334-
ResourceAttributes.CLOUD_ACCOUNT_ID,
335-
account_id,
336-
)
307+
token = context_api.attach(parent_context)
308+
try:
309+
with tracer.start_as_current_span(
310+
name=orig_handler_name,
311+
kind=span_kind,
312+
) as span:
313+
if span.is_recording():
314+
lambda_context = args[1]
315+
# NOTE: The specs mention an exception here, allowing the
316+
# `SpanAttributes.CLOUD_RESOURCE_ID` attribute to be set as a span
317+
# attribute instead of a resource attribute.
318+
#
319+
# See more:
320+
# https://github.com/open-telemetry/semantic-conventions/blob/main/docs/faas/aws-lambda.md#resource-detector
321+
span.set_attribute(
322+
SpanAttributes.CLOUD_RESOURCE_ID,
323+
lambda_context.invoked_function_arn,
324+
)
325+
span.set_attribute(
326+
SpanAttributes.FAAS_INVOCATION_ID,
327+
lambda_context.aws_request_id,
328+
)
337329

338-
exception = None
339-
result = None
340-
try:
341-
result = call_wrapped(*args, **kwargs)
342-
except Exception as exc: # pylint: disable=W0703
343-
exception = exc
344-
span.set_status(Status(StatusCode.ERROR))
345-
span.record_exception(exception)
346-
347-
# If the request came from an API Gateway, extract http attributes from the event
348-
# https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/semantic_conventions/instrumentation/aws-lambda.md#api-gateway
349-
# https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/semantic_conventions/http.md#http-server-semantic-conventions
350-
if isinstance(lambda_event, dict) and lambda_event.get(
351-
"requestContext"
352-
):
353-
span.set_attribute(SpanAttributes.FAAS_TRIGGER, "http")
354-
355-
if lambda_event.get("version") == "2.0":
356-
_set_api_gateway_v2_proxy_attributes(lambda_event, span)
357-
else:
358-
_set_api_gateway_v1_proxy_attributes(lambda_event, span)
359-
360-
if isinstance(result, dict) and result.get("statusCode"):
330+
# NOTE: `cloud.account.id` can be parsed from the ARN as the fifth item when splitting on `:`
331+
#
332+
# See more:
333+
# https://github.com/open-telemetry/semantic-conventions/blob/main/docs/faas/aws-lambda.md#all-triggers
334+
account_id = lambda_context.invoked_function_arn.split(
335+
":"
336+
)[4]
361337
span.set_attribute(
362-
SpanAttributes.HTTP_STATUS_CODE,
363-
result.get("statusCode"),
338+
ResourceAttributes.CLOUD_ACCOUNT_ID,
339+
account_id,
364340
)
365341

342+
exception = None
343+
result = None
344+
try:
345+
result = call_wrapped(*args, **kwargs)
346+
except Exception as exc: # pylint: disable=W0703
347+
exception = exc
348+
span.set_status(Status(StatusCode.ERROR))
349+
span.record_exception(exception)
350+
351+
# If the request came from an API Gateway, extract http attributes from the event
352+
# https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/semantic_conventions/instrumentation/aws-lambda.md#api-gateway
353+
# https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/semantic_conventions/http.md#http-server-semantic-conventions
354+
if isinstance(lambda_event, dict) and lambda_event.get(
355+
"requestContext"
356+
):
357+
span.set_attribute(SpanAttributes.FAAS_TRIGGER, "http")
358+
359+
if lambda_event.get("version") == "2.0":
360+
_set_api_gateway_v2_proxy_attributes(
361+
lambda_event, span
362+
)
363+
else:
364+
_set_api_gateway_v1_proxy_attributes(
365+
lambda_event, span
366+
)
367+
368+
if isinstance(result, dict) and result.get("statusCode"):
369+
span.set_attribute(
370+
SpanAttributes.HTTP_STATUS_CODE,
371+
result.get("statusCode"),
372+
)
373+
finally:
374+
context_api.detach(token)
375+
366376
now = time.time()
367377
_tracer_provider = tracer_provider or get_tracer_provider()
368378
if hasattr(_tracer_provider, "force_flush"):

instrumentation/opentelemetry-instrumentation-aws-lambda/tests/mocks/lambda_function.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,14 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15+
import json
16+
17+
from opentelemetry import baggage as baggage_api
18+
1519

1620
def handler(event, context):
17-
return "200 ok"
21+
baggage_content = dict(baggage_api.get_all().items())
22+
return json.dumps({"baggage_content": baggage_content})
1823

1924

2025
def rest_api_handler(event, context):

instrumentation/opentelemetry-instrumentation-aws-lambda/tests/test_aws_lambda_instrumentation_manual.py

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,15 @@
1111
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
14-
14+
import json
1515
import os
1616
from dataclasses import dataclass
1717
from importlib import import_module, reload
1818
from typing import Any, Callable, Dict
1919
from unittest import mock
2020

2121
from opentelemetry import propagate
22+
from opentelemetry.baggage.propagation import W3CBaggagePropagator
2223
from opentelemetry.environment_variables import OTEL_PROPAGATORS
2324
from opentelemetry.instrumentation.aws_lambda import (
2425
_HANDLER,
@@ -79,6 +80,9 @@ def __init__(self, aws_request_id, invoked_function_arn):
7980
MOCK_W3C_TRACE_STATE_KEY = "vendor_specific_key"
8081
MOCK_W3C_TRACE_STATE_VALUE = "test_value"
8182

83+
MOCK_W3C_BAGGAGE_KEY = "baggage_key"
84+
MOCK_W3C_BAGGAGE_VALUE = "baggage_value"
85+
8286

8387
def mock_execute_lambda(event=None):
8488
"""Mocks the AWS Lambda execution.
@@ -97,7 +101,7 @@ def mock_execute_lambda(event=None):
97101

98102
module_name, handler_name = os.environ[_HANDLER].rsplit(".", 1)
99103
handler_module = import_module(module_name.replace("/", "."))
100-
getattr(handler_module, handler_name)(event, MOCK_LAMBDA_CONTEXT)
104+
return getattr(handler_module, handler_name)(event, MOCK_LAMBDA_CONTEXT)
101105

102106

103107
class TestAwsLambdaInstrumentor(TestBase):
@@ -181,6 +185,9 @@ class TestCase:
181185
expected_state_value: str = None
182186
expected_trace_state_len: int = 0
183187
propagators: str = "tracecontext"
188+
expected_baggage: str = None
189+
disable_aws_context_propagation: bool = False
190+
disable_aws_context_propagation_envvar: str = ""
184191

185192
def custom_event_context_extractor(lambda_event):
186193
return get_global_textmap().extract(lambda_event["foo"]["headers"])
@@ -266,6 +273,24 @@ def custom_event_context_extractor(lambda_event):
266273
expected_state_value=MOCK_W3C_TRACE_STATE_VALUE,
267274
xray_traceid=MOCK_XRAY_TRACE_CONTEXT_SAMPLED,
268275
),
276+
TestCase(
277+
name="baggage_propagation",
278+
custom_extractor=None,
279+
context={
280+
"headers": {
281+
TraceContextTextMapPropagator._TRACEPARENT_HEADER_NAME: MOCK_W3C_TRACE_CONTEXT_SAMPLED,
282+
TraceContextTextMapPropagator._TRACESTATE_HEADER_NAME: f"{MOCK_W3C_TRACE_STATE_KEY}={MOCK_W3C_TRACE_STATE_VALUE},foo=1,bar=2",
283+
W3CBaggagePropagator._BAGGAGE_HEADER_NAME: f"{MOCK_W3C_BAGGAGE_KEY}={MOCK_W3C_BAGGAGE_VALUE}",
284+
}
285+
},
286+
expected_traceid=MOCK_W3C_TRACE_ID,
287+
expected_parentid=MOCK_W3C_PARENT_SPAN_ID,
288+
expected_trace_state_len=3,
289+
expected_state_value=MOCK_W3C_TRACE_STATE_VALUE,
290+
xray_traceid=MOCK_XRAY_TRACE_CONTEXT_NOT_SAMPLED,
291+
expected_baggage=MOCK_W3C_BAGGAGE_VALUE,
292+
propagators="tracecontext,baggage",
293+
),
269294
]
270295
for test in tests:
271296

@@ -284,7 +309,9 @@ def custom_event_context_extractor(lambda_event):
284309
AwsLambdaInstrumentor().instrument(
285310
event_context_extractor=test.custom_extractor,
286311
)
287-
mock_execute_lambda(test.context)
312+
result = mock_execute_lambda(test.context)
313+
result = json.loads(result)
314+
288315
spans = self.memory_exporter.get_finished_spans()
289316
assert spans
290317
self.assertEqual(len(spans), 1)
@@ -305,6 +332,10 @@ def custom_event_context_extractor(lambda_event):
305332
parent_context.trace_state.get(MOCK_W3C_TRACE_STATE_KEY),
306333
test.expected_state_value,
307334
)
335+
self.assertEqual(
336+
result["baggage_content"].get(MOCK_W3C_BAGGAGE_KEY),
337+
test.expected_baggage,
338+
)
308339
self.assertTrue(parent_context.is_remote)
309340
self.memory_exporter.clear()
310341
AwsLambdaInstrumentor().uninstrument()

0 commit comments

Comments
 (0)