Skip to content

Commit 7dee36c

Browse files
committed
Use an exception to catch inability to parse
1 parent d9a2c8c commit 7dee36c

File tree

5 files changed

+49
-81
lines changed

5 files changed

+49
-81
lines changed

sdk-extension/opentelemetry-sdk-extension-aws/src/opentelemetry/sdk/extension/aws/trace/aws_xray_ids_generator.py

+7-4
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15-
import datetime
1615
import random
16+
import time
1717

1818
from opentelemetry import trace
1919

@@ -28,10 +28,13 @@ class AwsXRayIdsGenerator(trace.IdsGenerator):
2828
See: https://docs.aws.amazon.com/xray/latest/devguide/xray-api-sendingdata.html#xray-api-traceids
2929
"""
3030

31+
random_ids_generator = trace.RandomIdsGenerator()
32+
3133
def generate_span_id(self) -> int:
32-
return trace.RandomIdsGenerator().generate_span_id()
34+
return self.random_ids_generator.generate_span_id()
3335

34-
def generate_trace_id(self) -> int:
35-
trace_time = int(datetime.datetime.utcnow().timestamp())
36+
@staticmethod
37+
def generate_trace_id() -> int:
38+
trace_time = int(time.time())
3639
trace_identifier = random.getrandbits(96)
3740
return (trace_time << 96) + trace_identifier

sdk-extension/opentelemetry-sdk-extension-aws/src/opentelemetry/sdk/extension/aws/trace/propagation/aws_xray_format.py

+39-47
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,12 @@
2727
_logger = logging.getLogger(__name__)
2828

2929

30+
class AwsParseTraceHeaderError(Exception):
31+
def __init__(self, message):
32+
super().__init__()
33+
self.message = message
34+
35+
3036
class AwsXRayFormat(TextMapPropagator):
3137
"""Propagator for the AWS X-Ray Trace Header propagation protocol.
3238
@@ -75,11 +81,12 @@ def extract(
7581
trace.INVALID_SPAN, context=context
7682
)
7783

78-
trace_id, span_id, sampled, err = self.extract_span_properties(
79-
trace_header
80-
)
81-
82-
if err is not None:
84+
try:
85+
trace_id, span_id, sampled = self._extract_span_properties(
86+
trace_header
87+
)
88+
except AwsParseTraceHeaderError as err:
89+
_logger.debug(err.message)
8390
return trace.set_span_in_context(
8491
trace.INVALID_SPAN, context=context
8592
)
@@ -97,7 +104,7 @@ def extract(
97104
)
98105

99106
if not span_context.is_valid:
100-
_logger.error(
107+
_logger.debug(
101108
"Invalid Span Extracted. Insertting INVALID span into provided context."
102109
)
103110
return trace.set_span_in_context(
@@ -108,94 +115,79 @@ def extract(
108115
trace.DefaultSpan(span_context), context=context
109116
)
110117

111-
def extract_span_properties(self, trace_header):
118+
def _extract_span_properties(self, trace_header):
112119
trace_id = trace.INVALID_TRACE_ID
113120
span_id = trace.INVALID_SPAN_ID
114121
sampled = False
115122

116-
extract_err = None
117-
118123
for kv_pair_str in trace_header.split(self.KV_PAIR_DELIMITER):
119-
if extract_err:
120-
break
121-
122124
try:
123125
key_str, value_str = kv_pair_str.split(
124126
self.KEY_AND_VALUE_DELIMITER
125127
)
126128
key, value = key_str.strip(), value_str.strip()
127-
except ValueError:
128-
_logger.error(
129+
except ValueError as ex:
130+
raise AwsParseTraceHeaderError(
129131
(
130132
"Error parsing X-Ray trace header. Invalid key value pair: %s. Returning INVALID span context.",
131133
kv_pair_str,
132134
)
133-
)
134-
return trace_id, span_id, sampled, extract_err
135-
135+
) from ex
136136
if key == self.TRACE_ID_KEY:
137-
if not self.validate_trace_id(value):
138-
_logger.error(
137+
if not self._validate_trace_id(value):
138+
raise AwsParseTraceHeaderError(
139139
(
140140
"Invalid TraceId in X-Ray trace header: '%s' with value '%s'. Returning INVALID span context.",
141141
self.TRACE_HEADER_KEY,
142142
trace_header,
143143
)
144144
)
145-
extract_err = True
146-
break
147145

148146
try:
149-
trace_id = self.parse_trace_id(value)
150-
except ValueError:
151-
_logger.error(
147+
trace_id = self._parse_trace_id(value)
148+
except ValueError as ex:
149+
raise AwsParseTraceHeaderError(
152150
(
153151
"Invalid TraceId in X-Ray trace header: '%s' with value '%s'. Returning INVALID span context.",
154152
self.TRACE_HEADER_KEY,
155153
trace_header,
156154
)
157-
)
158-
extract_err = True
155+
) from ex
159156
elif key == self.PARENT_ID_KEY:
160-
if not self.validate_span_id(value):
161-
_logger.error(
157+
if not self._validate_span_id(value):
158+
raise AwsParseTraceHeaderError(
162159
(
163160
"Invalid ParentId in X-Ray trace header: '%s' with value '%s'. Returning INVALID span context.",
164161
self.TRACE_HEADER_KEY,
165162
trace_header,
166163
)
167164
)
168-
extract_err = True
169-
break
170165

171166
try:
172-
span_id = AwsXRayFormat.parse_span_id(value)
173-
except ValueError:
174-
_logger.error(
167+
span_id = AwsXRayFormat._parse_span_id(value)
168+
except ValueError as ex:
169+
raise AwsParseTraceHeaderError(
175170
(
176171
"Invalid TraceId in X-Ray trace header: '%s' with value '%s'. Returning INVALID span context.",
177172
self.TRACE_HEADER_KEY,
178173
trace_header,
179174
)
180-
)
181-
extract_err = True
175+
) from ex
182176
elif key == self.SAMPLED_FLAG_KEY:
183-
if not self.validate_sampled_flag(value):
184-
_logger.error(
177+
if not self._validate_sampled_flag(value):
178+
raise AwsParseTraceHeaderError(
185179
(
186180
"Invalid Sampling flag in X-Ray trace header: '%s' with value '%s'. Returning INVALID span context.",
187181
self.TRACE_HEADER_KEY,
188182
trace_header,
189183
)
190184
)
191-
extract_err = True
192-
break
193185

194-
sampled = self.parse_sampled_flag(value)
186+
sampled = self._parse_sampled_flag(value)
195187

196-
return trace_id, span_id, sampled, extract_err
188+
return trace_id, span_id, sampled
197189

198-
def validate_trace_id(self, trace_id_str):
190+
def _validate_trace_id(self, trace_id_str):
199191
return (
200192
len(trace_id_str) == self.TRACE_ID_LENGTH
201193
and trace_id_str.startswith(self.TRACE_ID_VERSION)
@@ -205,7 +197,7 @@ def validate_trace_id(self, trace_id_str):
205197
== self.TRACE_ID_DELIMITER
206198
)
207199

208-
def parse_trace_id(self, trace_id_str):
200+
def _parse_trace_id(self, trace_id_str):
209201
timestamp_subset = trace_id_str[
210202
self.TRACE_ID_DELIMITER_INDEX_1
211203
+ 1 : self.TRACE_ID_DELIMITER_INDEX_2
@@ -215,22 +207,22 @@ def parse_trace_id(self, trace_id_str):
215207
]
216208
return int(timestamp_subset + unique_id_subset, 16)
217209

218-
def validate_span_id(self, span_id_str):
210+
def _validate_span_id(self, span_id_str):
219211
return len(span_id_str) == self.PARENT_ID_LENGTH
220212

221213
@staticmethod
222-
def parse_span_id(span_id_str):
214+
def _parse_span_id(span_id_str):
223215
return int(span_id_str, 16)
224216

225-
def validate_sampled_flag(self, sampled_flag_str):
217+
def _validate_sampled_flag(self, sampled_flag_str):
226218
return len(
227219
sampled_flag_str
228220
) == self.SAMPLED_FLAG_LENGTH and sampled_flag_str in (
229221
self.IS_SAMPLED,
230222
self.NOT_SAMPLED,
231223
)
232224

233-
def parse_sampled_flag(self, sampled_flag_str):
225+
def _parse_sampled_flag(self, sampled_flag_str):
234226
return sampled_flag_str[0] == self.IS_SAMPLED
235227

236228
def inject(
Original file line numberDiff line numberDiff line change
@@ -1,13 +0,0 @@
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.
Original file line numberDiff line numberDiff line change
@@ -1,13 +0,0 @@
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.

sdk-extension/opentelemetry-sdk-extension-aws/tests/trace/test_aws_xray_ids_generator.py

+3-4
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
# limitations under the License.
1414

1515
import datetime
16+
import time
1617
import unittest
1718

1819
from opentelemetry.sdk.extension.aws.trace import AwsXRayIdsGenerator
@@ -33,11 +34,9 @@ def test_id_timestamps_are_acceptable_for_xray(self):
3334
for _ in range(1000):
3435
trace_id = ids_generator.generate_trace_id()
3536
trace_id_time = trace_id >> 96
36-
current_time = int(datetime.datetime.utcnow().timestamp())
37+
current_time = int(time.time())
3738
self.assertLessEqual(trace_id_time, current_time)
3839
one_month_ago_time = int(
39-
(
40-
datetime.datetime.utcnow() - datetime.timedelta(30)
41-
).timestamp()
40+
(datetime.datetime.now() - datetime.timedelta(30)).timestamp()
4241
)
4342
self.assertGreater(trace_id_time, one_month_ago_time)

0 commit comments

Comments
 (0)