Skip to content

Commit 36007ae

Browse files
authored
Merge branch 'main' into sha-automation
2 parents f9f40d4 + 00329e0 commit 36007ae

File tree

27 files changed

+836
-420
lines changed

27 files changed

+836
-420
lines changed

CHANGELOG.md

+9
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## Unreleased
99

10+
- Fix intermittent `Connection aborted` error when using otlp/http exporters
11+
([#4477](https://github.com/open-telemetry/opentelemetry-python/pull/4477))
12+
- opentelemetry-sdk: use stable code attributes: `code.function` -> `code.function.name`, `code.lineno` -> `code.line.number`, `code.filepath` -> `code.file.path`
13+
([#4508](https://github.com/open-telemetry/opentelemetry-python/pull/4508))
14+
- Fix serialization of extended attributes for logs signal
15+
([#4342](https://github.com/open-telemetry/opentelemetry-python/pull/4342))
16+
- docs: updated and added to the metrics and log examples
17+
([#4559](https://github.com/open-telemetry/opentelemetry-python/pull/4559))
18+
1019
## Version 1.32.0/0.53b0 (2025-04-10)
1120

1221
- Fix user agent in OTLP HTTP metrics exporter

docs/conf.py

+4
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,10 @@
154154
"py:class",
155155
"_contextvars.Token",
156156
),
157+
(
158+
"py:class",
159+
"AnyValue",
160+
),
157161
]
158162

159163
# Add any paths that contain templates here, relative to this directory.

docs/examples/logs/README.rst

+67-34
Original file line numberDiff line numberDiff line change
@@ -52,37 +52,70 @@ The resulting logs will appear in the output from the collector and look similar
5252

5353
.. code-block:: sh
5454
55-
Resource SchemaURL:
56-
Resource labels:
57-
-> telemetry.sdk.language: STRING(python)
58-
-> telemetry.sdk.name: STRING(opentelemetry)
59-
-> telemetry.sdk.version: STRING(1.8.0)
60-
-> service.name: STRING(shoppingcart)
61-
-> service.instance.id: STRING(instance-12)
62-
InstrumentationLibraryLogs #0
63-
InstrumentationLibraryMetrics SchemaURL:
64-
InstrumentationLibrary __main__ 0.1
65-
LogRecord #0
66-
Timestamp: 2022-01-13 20:37:03.998733056 +0000 UTC
67-
Severity: WARNING
68-
ShortName:
69-
Body: Jail zesty vixen who grabbed pay from quack.
70-
Trace ID:
71-
Span ID:
72-
Flags: 0
73-
LogRecord #1
74-
Timestamp: 2022-01-13 20:37:04.082757888 +0000 UTC
75-
Severity: ERROR
76-
ShortName:
77-
Body: The five boxing wizards jump quickly.
78-
Trace ID:
79-
Span ID:
80-
Flags: 0
81-
LogRecord #2
82-
Timestamp: 2022-01-13 20:37:04.082979072 +0000 UTC
83-
Severity: ERROR
84-
ShortName:
85-
Body: Hyderabad, we have a major problem.
86-
Trace ID: 63491217958f126f727622e41d4460f3
87-
Span ID: d90c57d6e1ca4f6c
88-
Flags: 1
55+
ResourceLog #0
56+
Resource SchemaURL:
57+
Resource attributes:
58+
-> telemetry.sdk.language: Str(python)
59+
-> telemetry.sdk.name: Str(opentelemetry)
60+
-> telemetry.sdk.version: Str(1.33.0.dev0)
61+
-> service.name: Str(shoppingcart)
62+
-> service.instance.id: Str(instance-12)
63+
ScopeLogs #0
64+
ScopeLogs SchemaURL:
65+
InstrumentationScope myapp.area2
66+
LogRecord #0
67+
ObservedTimestamp: 2025-04-22 12:16:57.315179 +0000 UTC
68+
Timestamp: 2025-04-22 12:16:57.315152896 +0000 UTC
69+
SeverityText: WARN
70+
SeverityNumber: Warn(13)
71+
Body: Str(Jail zesty vixen who grabbed pay from quack.)
72+
Attributes:
73+
-> code.filepath: Str(/Users/jayclifford/Repos/opentelemetry-python/docs/examples/logs/example.py)
74+
-> code.function: Str(<module>)
75+
-> code.lineno: Int(47)
76+
Trace ID:
77+
Span ID:
78+
Flags: 0
79+
LogRecord #1
80+
ObservedTimestamp: 2025-04-22 12:16:57.31522 +0000 UTC
81+
Timestamp: 2025-04-22 12:16:57.315213056 +0000 UTC
82+
SeverityText: ERROR
83+
SeverityNumber: Error(17)
84+
Body: Str(The five boxing wizards jump quickly.)
85+
Attributes:
86+
-> code.filepath: Str(/Users/jayclifford/Repos/opentelemetry-python/docs/examples/logs/example.py)
87+
-> code.function: Str(<module>)
88+
-> code.lineno: Int(48)
89+
Trace ID:
90+
Span ID:
91+
Flags: 0
92+
LogRecord #2
93+
ObservedTimestamp: 2025-04-22 12:16:57.315445 +0000 UTC
94+
Timestamp: 2025-04-22 12:16:57.31543808 +0000 UTC
95+
SeverityText: ERROR
96+
SeverityNumber: Error(17)
97+
Body: Str(Hyderabad, we have a major problem.)
98+
Attributes:
99+
-> code.filepath: Str(/Users/jayclifford/Repos/opentelemetry-python/docs/examples/logs/example.py)
100+
-> code.function: Str(<module>)
101+
-> code.lineno: Int(61)
102+
Trace ID: 8a6739fffce895e694700944e2faf23e
103+
Span ID: a45337020100cb63
104+
Flags: 1
105+
ScopeLogs #1
106+
ScopeLogs SchemaURL:
107+
InstrumentationScope myapp.area1
108+
LogRecord #0
109+
ObservedTimestamp: 2025-04-22 12:16:57.315242 +0000 UTC
110+
Timestamp: 2025-04-22 12:16:57.315234048 +0000 UTC
111+
SeverityText: ERROR
112+
SeverityNumber: Error(17)
113+
Body: Str(I have custom attributes.)
114+
Attributes:
115+
-> user_id: Str(user-123)
116+
-> code.filepath: Str(/Users/jayclifford/Repos/opentelemetry-python/docs/examples/logs/example.py)
117+
-> code.function: Str(<module>)
118+
-> code.lineno: Int(53)
119+
Trace ID:
120+
Span ID:
121+
Flags: 0

docs/examples/logs/example.py

+4
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,10 @@
4747
logger2.warning("Jail zesty vixen who grabbed pay from quack.")
4848
logger2.error("The five boxing wizards jump quickly.")
4949

50+
# Log custom attributes
51+
# Custom attributes are added on a per event basis
52+
user_id = "user-123"
53+
logger1.error("I have custom attributes.", extra={"user_id": user_id})
5054

5155
# Trace context correlation
5256
tracer = trace.get_tracer(__name__)

docs/examples/logs/otel-collector-config.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ receivers:
66

77
exporters:
88
debug:
9-
verbosity: debug
9+
verbosity: detailed
1010

1111
processors:
1212
batch:

docs/examples/metrics/reader/README.rst

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ These examples show how to customize the metrics that are output by the SDK usin
66
* preferred_aggregation.py: Shows how to configure the preferred aggregation for metric instrument types.
77
* preferred_temporality.py: Shows how to configure the preferred temporality for metric instrument types.
88
* preferred_exemplarfilter.py: Shows how to configure the exemplar filter.
9+
* synchronous_gauge_read.py: Shows how to use `PeriodicExportingMetricReader` in a synchronous manner to explicitly control the collection of metrics.
910

1011
The source files of these examples are available :scm_web:`here <docs/examples/metrics/reader/>`.
1112

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
# Copyright The OpenTelemetry Authors
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
import math
16+
from typing import Iterable
17+
18+
from opentelemetry.metrics import (
19+
CallbackOptions,
20+
Observation,
21+
get_meter_provider,
22+
set_meter_provider,
23+
)
24+
from opentelemetry.sdk.metrics import MeterProvider
25+
from opentelemetry.sdk.metrics.export import (
26+
ConsoleMetricExporter,
27+
PeriodicExportingMetricReader,
28+
)
29+
30+
temperature = 0.0
31+
humidity = 0.0
32+
33+
34+
# Function called by the gauge to read the temperature
35+
def read_temperature(options: CallbackOptions) -> Iterable[Observation]:
36+
global temperature
37+
yield Observation(value=temperature, attributes={"room": "living-room"})
38+
39+
40+
# Function called by the gauge to read the humidity
41+
def read_humidity(options: CallbackOptions) -> Iterable[Observation]:
42+
global humidity
43+
yield Observation(value=humidity, attributes={"room": "living-room"})
44+
45+
46+
# Use console exporter for the example
47+
exporter = ConsoleMetricExporter()
48+
49+
# The PeriodicExportingMetricReader If the time interval is set to math.inf
50+
# the reader will not invoke periodic collection
51+
reader = PeriodicExportingMetricReader(
52+
exporter,
53+
export_interval_millis=math.inf,
54+
)
55+
56+
provider = MeterProvider(metric_readers=[reader])
57+
set_meter_provider(provider)
58+
59+
meter = get_meter_provider().get_meter("synchronous_read", "0.1.2")
60+
61+
gauge = meter.create_observable_gauge(
62+
name="synchronous_gauge_temperature",
63+
description="Gauge value captured synchronously",
64+
callbacks=[read_temperature],
65+
)
66+
67+
# Simulate synchronous reading of temperature
68+
print("--- Simulating synchronous reading of temperature ---", flush=True)
69+
temperature = 25.0
70+
reader.collect()
71+
# Note: The reader will only collect the last value before `collect` is called
72+
print("--- Last value only ---", flush=True)
73+
temperature = 30.0
74+
temperature = 35.0
75+
reader.collect()
76+
# Invoking `collect` will read all measurements assigned to the reader
77+
gauge2 = meter.create_observable_gauge(
78+
name="synchronous_gauge_humidity",
79+
description="Gauge value captured synchronously",
80+
callbacks=[read_humidity],
81+
)
82+
print("--- Multiple Measurements ---", flush=True)
83+
temperature = 20.0
84+
humidity = 50.0
85+
reader.collect()
86+
# Invoking `force_flush` will read all measurements assigned to the reader
87+
print("--- Invoking force_flush ---", flush=True)
88+
provider.force_flush()

exporter/opentelemetry-exporter-otlp-proto-common/src/opentelemetry/exporter/otlp/proto/common/_internal/__init__.py

+6-3
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@
4545
)
4646
from opentelemetry.sdk.trace import Resource
4747
from opentelemetry.sdk.util.instrumentation import InstrumentationScope
48-
from opentelemetry.util.types import Attributes
48+
from opentelemetry.util.types import _ExtendedAttributes
4949

5050
_logger = logging.getLogger(__name__)
5151

@@ -136,14 +136,17 @@ def _encode_trace_id(trace_id: int) -> bytes:
136136

137137

138138
def _encode_attributes(
139-
attributes: Attributes,
139+
attributes: _ExtendedAttributes,
140+
allow_null: bool = False,
140141
) -> Optional[List[PB2KeyValue]]:
141142
if attributes:
142143
pb2_attributes = []
143144
for key, value in attributes.items():
144145
# pylint: disable=broad-exception-caught
145146
try:
146-
pb2_attributes.append(_encode_key_value(key, value))
147+
pb2_attributes.append(
148+
_encode_key_value(key, value, allow_null=allow_null)
149+
)
147150
except Exception as error:
148151
_logger.exception("Failed to encode key %s: %s", key, error)
149152
else:

exporter/opentelemetry-exporter-otlp-proto-common/src/opentelemetry/exporter/otlp/proto/common/_internal/_log_encoder/__init__.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,9 @@ def _encode_log(log_data: LogData) -> PB2LogRecord:
5757
flags=int(log_data.log_record.trace_flags),
5858
body=_encode_value(body, allow_null=True),
5959
severity_text=log_data.log_record.severity_text,
60-
attributes=_encode_attributes(log_data.log_record.attributes),
60+
attributes=_encode_attributes(
61+
log_data.log_record.attributes, allow_null=True
62+
),
6163
dropped_attributes_count=log_data.log_record.dropped_attributes,
6264
severity_number=log_data.log_record.severity_number.value,
6365
)

0 commit comments

Comments
 (0)