Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 1112792

Browse files
Add proper length zero padding to hex strings of traceId, spanId, parentId sent on the wire (open-telemetry#908)
1 parent 8c4fca5 commit 1112792

File tree

3 files changed

+74
-5
lines changed

3 files changed

+74
-5
lines changed

exporter/opentelemetry-exporter-zipkin/CHANGELOG.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
- Change package name to opentelemetry-exporter-zipkin
66
([#953](https://github.com/open-telemetry/opentelemetry-python/pull/953))
7+
- Add proper length zero padding to hex strings of traceId, spanId, parentId sent on the wire, for compatibility with jaeger-collector
8+
([#908](https://github.com/open-telemetry/opentelemetry-python/pull/908))
79

810
## 0.8b0
911

@@ -23,4 +25,4 @@ Released 2020-05-12
2325

2426
Released 2020-02-21
2527

26-
- Initial release
28+
- Initial release

exporter/opentelemetry-exporter-zipkin/src/opentelemetry/exporter/zipkin/__init__.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -168,8 +168,9 @@ def _translate_to_zipkin(self, spans: Sequence[Span]):
168168
duration_mus = _nsec_to_usec_round(span.end_time - span.start_time)
169169

170170
zipkin_span = {
171-
"traceId": format(trace_id, "x"),
172-
"id": format(span_id, "x"),
171+
# Ensure left-zero-padding of traceId, spanId, parentId
172+
"traceId": format(trace_id, "032x"),
173+
"id": format(span_id, "016x"),
173174
"name": span.name,
174175
"timestamp": start_timestamp_mus,
175176
"duration": duration_mus,
@@ -184,10 +185,10 @@ def _translate_to_zipkin(self, spans: Sequence[Span]):
184185

185186
if isinstance(span.parent, Span):
186187
zipkin_span["parentId"] = format(
187-
span.parent.get_context().span_id, "x"
188+
span.parent.get_context().span_id, "016x"
188189
)
189190
elif isinstance(span.parent, SpanContext):
190-
zipkin_span["parentId"] = format(span.parent.span_id, "x")
191+
zipkin_span["parentId"] = format(span.parent.span_id, "016x")
191192

192193
zipkin_spans.append(zipkin_span)
193194
return zipkin_spans

exporter/opentelemetry-exporter-zipkin/tests/test_zipkin_exporter.py

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,72 @@ def test_export(self):
264264
headers={"Content-Type": "application/json"},
265265
)
266266

267+
# pylint: disable=too-many-locals
268+
def test_zero_padding(self):
269+
"""test that hex ids starting with 0
270+
are properly padded to 16 or 32 hex chars
271+
when exported
272+
"""
273+
274+
span_names = "testZeroes"
275+
trace_id = 0x0E0C63257DE34C926F9EFCD03927272E
276+
span_id = 0x04BF92DEEFC58C92
277+
parent_id = 0x0AAAAAAAAAAAAAAA
278+
279+
start_time = 683647322 * 10 ** 9 # in ns
280+
duration = 50 * 10 ** 6
281+
end_time = start_time + duration
282+
283+
span_context = trace_api.SpanContext(
284+
trace_id,
285+
span_id,
286+
is_remote=False,
287+
trace_flags=TraceFlags(TraceFlags.SAMPLED),
288+
)
289+
parent_context = trace_api.SpanContext(
290+
trace_id, parent_id, is_remote=False
291+
)
292+
293+
otel_span = trace.Span(
294+
name=span_names[0], context=span_context, parent=parent_context,
295+
)
296+
297+
otel_span.start(start_time=start_time)
298+
otel_span.end(end_time=end_time)
299+
300+
service_name = "test-service"
301+
local_endpoint = {"serviceName": service_name, "port": 9411}
302+
303+
exporter = ZipkinSpanExporter(service_name)
304+
# Check traceId are properly lowercase 16 or 32 hex
305+
expected = [
306+
{
307+
"traceId": "0e0c63257de34c926f9efcd03927272e",
308+
"id": "04bf92deefc58c92",
309+
"name": span_names[0],
310+
"timestamp": start_time // 10 ** 3,
311+
"duration": duration // 10 ** 3,
312+
"localEndpoint": local_endpoint,
313+
"kind": None,
314+
"tags": {},
315+
"annotations": None,
316+
"debug": True,
317+
"parentId": "0aaaaaaaaaaaaaaa",
318+
}
319+
]
320+
321+
mock_post = MagicMock()
322+
with patch("requests.post", mock_post):
323+
mock_post.return_value = MockResponse(200)
324+
status = exporter.export([otel_span])
325+
self.assertEqual(SpanExportResult.SUCCESS, status)
326+
327+
mock_post.assert_called_with(
328+
url="http://localhost:9411/api/v2/spans",
329+
data=json.dumps(expected),
330+
headers={"Content-Type": "application/json"},
331+
)
332+
267333
@patch("requests.post")
268334
def test_invalid_response(self, mock_post):
269335
mock_post.return_value = MockResponse(404)

0 commit comments

Comments
 (0)