Skip to content
This repository was archived by the owner on Sep 17, 2025. It is now read-only.

Commit df9baf2

Browse files
sonmezonurBogdan Drutu
authored andcommitted
Use SpanData objects to emit spans on Zipkin Exporter (#217)
1 parent f544c4a commit df9baf2

2 files changed

Lines changed: 35 additions & 59 deletions

File tree

opencensus/trace/exporters/zipkin_exporter.py

Lines changed: 29 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,9 @@
2121

2222
import requests
2323

24-
from opencensus.trace import span_data
2524
from opencensus.trace.exporters import base
2625
from opencensus.trace.exporters.transports import sync
26+
from opencensus.trace.utils import check_str_length
2727

2828
DEFAULT_ENDPOINT = '/api/v2/spans'
2929
DEFAULT_HOST_NAME = 'localhost'
@@ -100,15 +100,9 @@ def emit(self, span_datas):
100100
:param list of opencensus.trace.span_data.SpanData span_datas:
101101
SpanData tuples to emit
102102
"""
103-
# convert to the legacy trace json for easier refactoring
104-
# TODO: refactor this to use the span data directly
105-
trace = span_data.format_legacy_trace_json(span_datas)
106-
107-
trace_id = trace.get('traceId')
108-
spans = trace.get('spans')
109103

110104
try:
111-
zipkin_spans = self.translate_to_zipkin(trace_id, spans)
105+
zipkin_spans = self.translate_to_zipkin(span_datas)
112106
result = requests.post(
113107
url=self.url,
114108
data=json.dumps(zipkin_spans),
@@ -124,18 +118,22 @@ def emit(self, span_datas):
124118
def export(self, span_datas):
125119
self.transport.export(span_datas)
126120

127-
def translate_to_zipkin(self, trace_id, spans):
121+
def translate_to_zipkin(self, span_datas):
128122
"""Translate the opencensus spans to zipkin spans.
129123
130-
:type trace_id: str
131-
:param trace_id: Trace ID.
132-
133-
:type spans: list
134-
:param spans: List of spans to be exported.
124+
:type span_datas: list of :class:
125+
`~opencensus.trace.span_data.SpanData`
126+
:param span_datas:
127+
SpanData tuples to emit
135128
136129
:rtype: list
137130
:returns: List of zipkin format spans.
138131
"""
132+
133+
top_span = span_datas[0]
134+
trace_id = top_span.context.trace_id if top_span.context is not None \
135+
else None
136+
139137
local_endpoint = {
140138
'serviceName': self.service_name,
141139
'port': self.port,
@@ -149,17 +147,17 @@ def translate_to_zipkin(self, trace_id, spans):
149147

150148
zipkin_spans = []
151149

152-
for span in spans:
150+
for span in span_datas:
153151
# Timestamp in zipkin spans is int of microseconds.
154152
start_datetime = datetime.datetime.strptime(
155-
span.get('startTime'),
153+
span.start_time,
156154
ISO_DATETIME_REGEX)
157155
start_timestamp_ms = calendar.timegm(
158156
start_datetime.timetuple()) * 1000 * 1000 \
159157
+ start_datetime.microsecond
160158

161159
end_datetime = datetime.datetime.strptime(
162-
span.get('endTime'),
160+
span.end_time,
163161
ISO_DATETIME_REGEX)
164162
end_timestamp_ms = calendar.timegm(
165163
end_datetime.timetuple()) * 1000 * 1000 \
@@ -169,16 +167,16 @@ def translate_to_zipkin(self, trace_id, spans):
169167

170168
zipkin_span = {
171169
'traceId': trace_id,
172-
'id': str(span.get('spanId')),
173-
'name': span.get('displayName', {}).get('value'),
170+
'id': str(span.span_id),
171+
'name': span.name,
174172
'timestamp': int(round(start_timestamp_ms)),
175173
'duration': int(round(duration_ms)),
176174
'localEndpoint': local_endpoint,
177-
'tags': _extract_tags_from_span(span),
175+
'tags': _extract_tags_from_span(span.attributes),
178176
}
179177

180-
span_kind = span.get('kind')
181-
parent_span_id = span.get('parentSpanId')
178+
span_kind = span.span_kind
179+
parent_span_id = span.parent_span_id
182180

183181
if span_kind is not None:
184182
kind = SPAN_KIND_MAP.get(span_kind)
@@ -195,18 +193,16 @@ def translate_to_zipkin(self, trace_id, spans):
195193
return zipkin_spans
196194

197195

198-
def _extract_tags_from_span(span):
196+
def _extract_tags_from_span(attr):
197+
if attr is None:
198+
return {}
199199
tags = {}
200-
for attribute_key, attribute_value in span.get(
201-
'attributes', {}).get('attributeMap', {}).items():
202-
if not isinstance(attribute_value, dict):
203-
continue
204-
if attribute_value.get('string_value') is not None:
205-
value = attribute_value.get('string_value').get('value')
206-
elif attribute_value.get('int_value') is not None:
207-
value = str(attribute_value.get('int_value'))
208-
elif attribute_value.get('bool_value') is not None:
209-
value = str(attribute_value.get('bool_value'))
200+
for attribute_key, attribute_value in attr.items():
201+
if isinstance(attribute_value, (int, bool)):
202+
value = str(attribute_value)
203+
elif isinstance(attribute_value, str):
204+
res, _ = check_str_length(str_to_check=attribute_value)
205+
value = res
210206
else:
211207
logging.warn('Could not serialize tag {}'.format(attribute_key))
212208
continue

tests/unit/trace/exporters/test_zipkin_exporter.py

Lines changed: 6 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -208,45 +208,25 @@ def test_translate_to_zipkin_span_kind_none(self):
208208
# Test ipv4 local endpoint
209209
exporter_ipv4 = zipkin_exporter.ZipkinExporter(
210210
service_name='my_service', ipv4=ipv4)
211-
ipv4_trace = span_data_module.format_legacy_trace_json(spans_ipv4)
212211
zipkin_spans_ipv4 = exporter_ipv4.translate_to_zipkin(
213-
trace_id=trace_id,
214-
spans=ipv4_trace.get('spans'))
212+
span_datas=spans_ipv4)
215213

216214
self.assertEqual(zipkin_spans_ipv4, expected_zipkin_spans_ipv4)
217215

218216
# Test ipv6 local endpoint
219217
exporter_ipv6 = zipkin_exporter.ZipkinExporter(
220218
service_name='my_service', ipv6=ipv6)
221-
ipv6_trace = span_data_module.format_legacy_trace_json(spans_ipv6)
222219
zipkin_spans_ipv6 = exporter_ipv6.translate_to_zipkin(
223-
trace_id=trace_id,
224-
spans=ipv6_trace.get('spans')
225-
)
220+
span_datas=spans_ipv6)
226221

227222
self.assertEqual(zipkin_spans_ipv6, expected_zipkin_spans_ipv6)
228223

229224
def test_ignore_incorrect_spans(self):
230-
span1 = {
231-
'attributes': {
232-
'attributeMap': {
233-
'float_value': {
234-
'value': 0.1
235-
}
236-
}
237-
}
238-
}
239-
self.assertEqual(zipkin_exporter._extract_tags_from_span(span1), {})
240-
241-
span2 = {
242-
'attributes': {
243-
'attributeMap': {
244-
'bool_value': False
245-
}
225+
attributes = {'float_value': 0.1}
226+
self.assertEqual(zipkin_exporter._extract_tags_from_span(attributes), {})
246227

247-
}
248-
}
249-
self.assertEqual(zipkin_exporter._extract_tags_from_span(span2), {})
228+
attributes = None
229+
self.assertEqual(zipkin_exporter._extract_tags_from_span(attributes), {})
250230

251231

252232
class MockTransport(object):

0 commit comments

Comments
 (0)