Skip to content

Commit cf65afa

Browse files
committed
add type checking for opentelemetry-exporter-otlp-json-common
1 parent 0b9e0d4 commit cf65afa

File tree

8 files changed

+81
-116
lines changed

8 files changed

+81
-116
lines changed

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

Lines changed: 11 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,13 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15-
1615
from __future__ import annotations
1716

1817
import logging
1918
from collections.abc import Collection, Mapping, Sequence
2019
from typing import (
2120
Any,
22-
Callable,
23-
Optional,
24-
TypeVar,
21+
cast,
2522
)
2623

2724
from opentelemetry.proto_json.common.v1.common import AnyValue as JSONAnyValue
@@ -40,16 +37,13 @@
4037
)
4138
from opentelemetry.sdk.resources import Resource
4239
from opentelemetry.sdk.util.instrumentation import InstrumentationScope
43-
from opentelemetry.util.types import _ExtendedAttributes
40+
from opentelemetry.util.types import Attributes
4441

4542
_logger = logging.getLogger(__name__)
4643

47-
_TypingResourceT = TypeVar("_TypingResourceT")
48-
_ResourceDataT = TypeVar("_ResourceDataT")
49-
5044

5145
def _encode_instrumentation_scope(
52-
instrumentation_scope: InstrumentationScope,
46+
instrumentation_scope: InstrumentationScope | None,
5347
) -> JSONInstrumentationScope:
5448
return (
5549
JSONInstrumentationScope(
@@ -67,9 +61,7 @@ def _encode_resource(resource: Resource) -> JSONResource:
6761

6862

6963
# pylint: disable-next=too-many-return-statements
70-
def _encode_value(
71-
value: Any, allow_null: bool = False
72-
) -> Optional[JSONAnyValue]:
64+
def _encode_value(value: Any, allow_null: bool = False) -> JSONAnyValue | None:
7365
if allow_null is True and value is None:
7466
return None
7567
if isinstance(value, bool):
@@ -85,7 +77,10 @@ def _encode_value(
8577
if isinstance(value, Sequence):
8678
return JSONAnyValue(
8779
array_value=JSONArrayValue(
88-
values=_encode_array(value, allow_null=allow_null)
80+
values=cast(
81+
list[JSONAnyValue],
82+
_encode_array(value, allow_null=allow_null),
83+
)
8984
)
9085
)
9186
if isinstance(value, Mapping):
@@ -134,11 +129,11 @@ def _encode_trace_id(trace_id: int) -> bytes:
134129

135130

136131
def _encode_attributes(
137-
attributes: _ExtendedAttributes,
132+
attributes: Attributes | None,
138133
allow_null: bool = False,
139-
) -> Optional[list[JSONKeyValue]]:
134+
) -> list[JSONKeyValue]:
140135
if not attributes:
141-
return None
136+
return []
142137
json_attributes = []
143138
for key, value in attributes.items():
144139
# pylint: disable=broad-exception-caught
@@ -149,28 +144,3 @@ def _encode_attributes(
149144
except Exception as error:
150145
_logger.exception("Failed to encode key %s: %s", key, error)
151146
return json_attributes
152-
153-
154-
def _get_resource_data(
155-
sdk_resource_scope_data: dict[Resource, _ResourceDataT],
156-
resource_class: Callable[..., _TypingResourceT],
157-
name: str,
158-
) -> list[_TypingResourceT]:
159-
resource_data = []
160-
161-
for (
162-
sdk_resource,
163-
scope_data,
164-
) in sdk_resource_scope_data.items():
165-
json_resource = JSONResource(
166-
attributes=_encode_attributes(sdk_resource.attributes)
167-
)
168-
resource_data.append(
169-
resource_class(
170-
**{
171-
"resource": json_resource,
172-
f"scope_{name}": scope_data.values(),
173-
}
174-
)
175-
)
176-
return resource_data

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

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,11 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15+
from __future__ import annotations
16+
1517
from collections import defaultdict
1618
from collections.abc import Collection
19+
from typing import cast
1720

1821
from opentelemetry.exporter.otlp.json.common._internal import (
1922
_encode_attributes,
@@ -34,6 +37,7 @@
3437
ScopeLogs as JSONScopeLogs,
3538
)
3639
from opentelemetry.sdk._logs import ReadableLogRecord
40+
from opentelemetry.util.types import Attributes
3741

3842

3943
def encode_logs(
@@ -45,27 +49,23 @@ def encode_logs(
4549

4650

4751
def _encode_log(readable_log_record: ReadableLogRecord) -> JSONLogRecord:
48-
span_id = (
49-
None
50-
if readable_log_record.log_record.span_id == 0
51-
else _encode_span_id(readable_log_record.log_record.span_id)
52-
)
53-
trace_id = (
54-
None
55-
if readable_log_record.log_record.trace_id == 0
56-
else _encode_trace_id(readable_log_record.log_record.trace_id)
57-
)
58-
body = readable_log_record.log_record.body
5952
return JSONLogRecord(
6053
time_unix_nano=readable_log_record.log_record.timestamp,
6154
observed_time_unix_nano=readable_log_record.log_record.observed_timestamp,
62-
span_id=span_id,
63-
trace_id=trace_id,
55+
span_id=_encode_span_id(readable_log_record.log_record.span_id)
56+
if readable_log_record.log_record.span_id
57+
else None,
58+
trace_id=_encode_trace_id(readable_log_record.log_record.trace_id)
59+
if readable_log_record.log_record.trace_id
60+
else None,
6461
flags=int(readable_log_record.log_record.trace_flags),
65-
body=_encode_value(body, allow_null=True),
62+
body=_encode_value(
63+
readable_log_record.log_record.body, allow_null=True
64+
),
6665
severity_text=readable_log_record.log_record.severity_text,
6766
attributes=_encode_attributes(
68-
readable_log_record.log_record.attributes, allow_null=True
67+
cast(Attributes, readable_log_record.log_record.attributes),
68+
allow_null=True,
6969
),
7070
dropped_attributes_count=readable_log_record.dropped_attributes,
7171
severity_number=getattr(

exporter/opentelemetry-exporter-otlp-json-common/src/opentelemetry/exporter/otlp/json/common/_internal/metrics_encoder/__init__.py

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
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+
1415
from __future__ import annotations
1516

1617
import logging
@@ -67,16 +68,12 @@
6768
ScopeMetrics,
6869
)
6970
from opentelemetry.sdk.metrics.export import (
70-
ExponentialHistogram as ExponentialHistogramType,
71-
)
72-
from opentelemetry.sdk.metrics.export import (
71+
ExponentialHistogram,
7372
Gauge,
73+
Histogram,
7474
MetricsData,
7575
Sum,
7676
)
77-
from opentelemetry.sdk.metrics.export import (
78-
Histogram as HistogramType,
79-
)
8077

8178
_logger = logging.getLogger(__name__)
8279

@@ -123,7 +120,7 @@ def _encode_metric(metric: Metric) -> JSONMetric:
123120
_encode_gauge_data_point(pt) for pt in metric.data.data_points
124121
]
125122
)
126-
elif isinstance(metric.data, HistogramType):
123+
elif isinstance(metric.data, Histogram):
127124
json_metric.histogram = JSONHistogram(
128125
data_points=[
129126
_encode_histogram_data_point(pt)
@@ -139,7 +136,7 @@ def _encode_metric(metric: Metric) -> JSONMetric:
139136
aggregation_temporality=metric.data.aggregation_temporality,
140137
is_monotonic=metric.data.is_monotonic,
141138
)
142-
elif isinstance(metric.data, ExponentialHistogramType):
139+
elif isinstance(metric.data, ExponentialHistogram):
143140
json_metric.exponential_histogram = JSONExponentialHistogram(
144141
data_points=[
145142
_encode_exponential_histogram_data_point(pt)
@@ -196,8 +193,8 @@ def _encode_histogram_data_point(
196193
exemplars=_encode_exemplars(data_point.exemplars),
197194
count=data_point.count,
198195
sum=data_point.sum,
199-
bucket_counts=data_point.bucket_counts,
200-
explicit_bounds=data_point.explicit_bounds,
196+
bucket_counts=list(data_point.bucket_counts),
197+
explicit_bounds=list(data_point.explicit_bounds),
201198
max=data_point.max,
202199
min=data_point.min,
203200
)
@@ -218,15 +215,15 @@ def _encode_exponential_histogram_data_point(
218215
positive=(
219216
JSONExponentialHistogramDataPoint.Buckets(
220217
offset=data_point.positive.offset,
221-
bucket_counts=data_point.positive.bucket_counts,
218+
bucket_counts=list(data_point.positive.bucket_counts),
222219
)
223220
if data_point.positive.bucket_counts
224221
else None
225222
),
226223
negative=(
227224
JSONExponentialHistogramDataPoint.Buckets(
228225
offset=data_point.negative.offset,
229-
bucket_counts=data_point.negative.bucket_counts,
226+
bucket_counts=list(data_point.negative.bucket_counts),
230227
)
231228
if data_point.negative.bucket_counts
232229
else None

exporter/opentelemetry-exporter-otlp-json-common/src/opentelemetry/exporter/otlp/json/common/_internal/trace_encoder/__init__.py

Lines changed: 34 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,11 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15+
from __future__ import annotations
16+
1517
import logging
1618
from collections import defaultdict
1719
from collections.abc import Collection
18-
from typing import Optional
1920

2021
from opentelemetry.exporter.otlp.json.common._internal import (
2122
_encode_attributes,
@@ -98,7 +99,7 @@ def _encode_resource_spans(
9899
return json_resource_spans
99100

100101

101-
def _span_flags(parent_span_context: Optional[SpanContext]) -> int:
102+
def _span_flags(parent_span_context: SpanContext | None) -> int:
102103
flags = JSONSpanFlags.SPAN_FLAGS_CONTEXT_HAS_IS_REMOTE_MASK
103104
if parent_span_context and parent_span_context.is_remote:
104105
flags |= JSONSpanFlags.SPAN_FLAGS_CONTEXT_IS_REMOTE_MASK
@@ -108,10 +109,14 @@ def _span_flags(parent_span_context: Optional[SpanContext]) -> int:
108109
def _encode_span(sdk_span: ReadableSpan) -> JSONSpan:
109110
span_context = sdk_span.get_span_context()
110111
return JSONSpan(
111-
trace_id=_encode_trace_id(span_context.trace_id),
112-
span_id=_encode_span_id(span_context.span_id),
113-
trace_state=_encode_trace_state(span_context.trace_state),
114-
parent_span_id=_encode_parent_id(sdk_span.parent),
112+
trace_id=_encode_trace_id(
113+
span_context.trace_id if span_context else 0
114+
),
115+
span_id=_encode_span_id(span_context.span_id if span_context else 0),
116+
trace_state=_encode_trace_state(
117+
span_context.trace_state if span_context else None
118+
),
119+
parent_span_id=_encode_context_span_id(sdk_span.parent),
115120
name=sdk_span.name,
116121
kind=_SPAN_KIND_MAP[sdk_span.kind],
117122
start_time_unix_nano=sdk_span.start_time,
@@ -129,40 +134,32 @@ def _encode_span(sdk_span: ReadableSpan) -> JSONSpan:
129134

130135
def _encode_events(
131136
events: Collection[Event],
132-
) -> Optional[list[JSONSpan.Event]]:
133-
return (
134-
[
135-
JSONSpan.Event(
136-
name=event.name,
137-
time_unix_nano=event.timestamp,
138-
attributes=_encode_attributes(event.attributes),
139-
dropped_attributes_count=event.dropped_attributes,
140-
)
141-
for event in events
142-
]
143-
if events
144-
else None
145-
)
137+
) -> list[JSONSpan.Event]:
138+
return [
139+
JSONSpan.Event(
140+
name=event.name,
141+
time_unix_nano=event.timestamp,
142+
attributes=_encode_attributes(event.attributes),
143+
dropped_attributes_count=event.dropped_attributes,
144+
)
145+
for event in events
146+
]
146147

147148

148149
def _encode_links(links: Collection[Link]) -> list[JSONSpan.Link]:
149-
return (
150-
[
151-
JSONSpan.Link(
152-
trace_id=_encode_trace_id(link.context.trace_id),
153-
span_id=_encode_span_id(link.context.span_id),
154-
attributes=_encode_attributes(link.attributes),
155-
dropped_attributes_count=link.dropped_attributes,
156-
flags=_span_flags(link.context),
157-
)
158-
for link in links
159-
]
160-
if links
161-
else None
162-
)
150+
return [
151+
JSONSpan.Link(
152+
trace_id=_encode_trace_id(link.context.trace_id),
153+
span_id=_encode_span_id(link.context.span_id),
154+
attributes=_encode_attributes(link.attributes),
155+
dropped_attributes_count=link.dropped_attributes,
156+
flags=_span_flags(link.context),
157+
)
158+
for link in links
159+
]
163160

164161

165-
def _encode_status(status: Status) -> Optional[JSONStatus]:
162+
def _encode_status(status: Status | None) -> JSONStatus | None:
166163
return (
167164
JSONStatus(
168165
code=JSONStatus.StatusCode(status.status_code.value),
@@ -173,13 +170,13 @@ def _encode_status(status: Status) -> Optional[JSONStatus]:
173170
)
174171

175172

176-
def _encode_trace_state(trace_state: Optional[TraceState]) -> Optional[str]:
173+
def _encode_trace_state(trace_state: TraceState | None) -> str | None:
177174
return (
178175
",".join([f"{key}={value}" for key, value in (trace_state.items())])
179176
if trace_state is not None
180177
else None
181178
)
182179

183180

184-
def _encode_parent_id(context: Optional[SpanContext]) -> Optional[bytes]:
181+
def _encode_context_span_id(context: SpanContext | None) -> bytes | None:
185182
return _encode_span_id(context.span_id) if context else None

exporter/opentelemetry-exporter-otlp-json-common/tests/test_common_encoder.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -238,8 +238,8 @@ def test_encode_attributes_all_types(self):
238238
)
239239

240240
def test_encode_attributes_empty(self):
241-
self.assertIsNone(_encode_attributes({}))
242-
self.assertIsNone(_encode_attributes(None))
241+
self.assertEqual(_encode_attributes({}), [])
242+
self.assertEqual(_encode_attributes(None), [])
243243

244244
def test_encode_attributes_error_skips_bad_key(self):
245245
with self.assertLogs(level=ERROR) as error:
@@ -310,7 +310,7 @@ def test_encode_resource(self):
310310
def test_encode_resource_empty(self):
311311
resource = Resource({})
312312
result = _encode_resource(resource)
313-
self.assertEqual(result, JSONResource(attributes=None))
313+
self.assertEqual(result, JSONResource())
314314
self.assertEqual(result.to_dict(), {})
315315

316316
def test_encode_instrumentation_scope(self):

exporter/opentelemetry-exporter-otlp-json-common/tests/test_log_encoder.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,7 @@ def test_encode_log_empty_record(self):
196196
self.assertIsNone(lr.severity_text)
197197
self.assertIsNone(lr.severity_number)
198198
self.assertIsNone(lr.body)
199-
self.assertIsNone(lr.attributes)
199+
self.assertEqual(lr.attributes, [])
200200

201201
def test_encode_log_event_name(self):
202202
log = make_log(body="event happened", event_name="my.event")

0 commit comments

Comments
 (0)