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

Commit 2ac053e

Browse files
wkiserliyanhui1228
authored andcommitted
Refactor exporters to accept SpanData objects instead of Spans (#144)
1 parent aba6a32 commit 2ac053e

21 files changed

+463
-195
lines changed

opencensus/trace/exporters/base.py

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,24 @@ class Exporter(object):
2020
2121
Subclasses of :class:`Exporter` must override :meth:`export`.
2222
"""
23-
def emit(self, trace):
24-
"""Emit the trace."""
23+
24+
def emit(self, span_datas):
25+
"""
26+
:type span_datas: list of :class:
27+
`~opencensus.trace.span_data.SpanData`
28+
:param list of opencensus.trace.span_data.SpanData span_datas:
29+
SpanData tuples to emit
30+
"""
2531
raise NotImplementedError
2632

27-
def export(self, trace):
33+
def export(self, span_datas):
2834
"""Export the trace. Send trace to transport, and transport will call
2935
exporter.emit() to actually send the trace to the specified tracing
3036
backend.
37+
38+
:type span_datas: list of :class:
39+
`~opencensus.trace.span_data.SpanData`
40+
:param list of opencensus.trace.span_data.SpanData span_datas:
41+
SpanData tuples to export
3142
"""
3243
raise NotImplementedError

opencensus/trace/exporters/file_exporter.py

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
import json
1818

19+
from opencensus.trace import span_data
1920
from opencensus.trace.exporters import base
2021
from opencensus.trace.exporters.transports import sync
2122

@@ -47,14 +48,25 @@ def __init__(self, file_name=DEFAULT_FILENAME,
4748
self.transport = transport(self)
4849
self.file_mode = file_mode
4950

50-
def emit(self, trace):
51+
def emit(self, span_datas):
5152
"""
52-
:type trace: dict
53-
:param trace: Trace collected.
53+
:type span_datas: list of :class:
54+
`~opencensus.trace.span_data.SpanData`
55+
:param list of opencensus.trace.span_data.SpanData span_datas:
56+
SpanData tuples to emit
5457
"""
5558
with open(self.file_name, self.file_mode) as file:
56-
trace_str = json.dumps(trace)
59+
# convert to the legacy trace json for easier refactoring
60+
# TODO: refactor this to use the span data directly
61+
legacy_trace_json = span_data.format_legacy_trace_json(span_datas)
62+
trace_str = json.dumps(legacy_trace_json)
5763
file.write(trace_str)
5864

59-
def export(self, trace):
60-
self.transport.export(trace)
65+
def export(self, span_datas):
66+
"""
67+
:type span_datas: list of :class:
68+
`~opencensus.trace.span_data.SpanData`
69+
:param list of opencensus.trace.span_data.SpanData span_datas:
70+
SpanData tuples to export
71+
"""
72+
self.transport.export(span_datas)

opencensus/trace/exporters/logging_exporter.py

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
import logging
1818

19+
from opencensus.trace import span_data
1920
from opencensus.trace.exporters import base
2021
from opencensus.trace.exporters.transports import sync
2122

@@ -63,12 +64,23 @@ def __init__(self, handler=None, transport=sync.SyncTransport):
6364
self.logger.setLevel(logging.INFO)
6465
self.transport = transport(self)
6566

66-
def emit(self, trace):
67+
def emit(self, span_datas):
6768
"""
68-
:type traces: dict
69-
:param traces: Trace collected.
69+
:type span_datas: list of :class:
70+
`~opencensus.trace.span_data.SpanData`
71+
:param list of opencensus.trace.span_data.SpanData span_datas:
72+
SpanData tuples to emit
7073
"""
71-
self.logger.info(trace)
74+
# convert to the legacy trace json for easier refactoring
75+
# TODO: refactor this to use the span data directly
76+
legacy_trace_json = span_data.format_legacy_trace_json(span_datas)
77+
self.logger.info(legacy_trace_json)
7278

73-
def export(self, trace):
74-
self.transport.export(trace)
79+
def export(self, span_datas):
80+
"""
81+
:type span_datas: list of :class:
82+
`~opencensus.trace.span_data.SpanData`
83+
:param list of opencensus.trace.span_data.SpanData span_datas:
84+
SpanData tuples to export
85+
"""
86+
self.transport.export(span_datas)

opencensus/trace/exporters/print_exporter.py

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -28,20 +28,24 @@ class PrintExporter(base.Exporter):
2828
:class:`.SyncTransport`. The other option is
2929
:class:`.BackgroundThreadTransport`.
3030
"""
31+
3132
def __init__(self, transport=sync.SyncTransport):
3233
self.transport = transport(self)
3334

34-
def emit(self, trace):
35-
"""export the traces by printing it out.
36-
37-
:type trace: dict
38-
:param trace: Trace collected.
39-
40-
:rtype: dict
41-
:returns: Trace printed.
35+
def emit(self, span_datas):
4236
"""
43-
print(trace)
44-
return trace
37+
:type span_datas: list of :class:
38+
`~opencensus.trace.span_data.SpanData`
39+
:param list of opencensus.trace.span_data.SpanData span_datas:
40+
SpanData tuples to emit
41+
"""
42+
print(span_datas)
4543

46-
def export(self, trace):
47-
self.transport.export(trace)
44+
def export(self, span_datas):
45+
"""
46+
:type span_datas: list of :class:
47+
`~opencensus.trace.span_data.SpanData`
48+
:param list of opencensus.trace.span_data.SpanData span_datas:
49+
SpanData tuples to export
50+
"""
51+
self.transport.export(span_datas)

opencensus/trace/exporters/stackdriver_exporter.py

Lines changed: 29 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,14 @@
1414

1515
import os
1616

17-
from opencensus.trace.attributes import Attributes
17+
from google.cloud.trace.client import Client
18+
1819
from opencensus.trace import attributes_helper
20+
from opencensus.trace import span_data
21+
from opencensus.trace.attributes import Attributes
1922
from opencensus.trace.exporters import base
2023
from opencensus.trace.exporters.transports import sync
2124

22-
from google.cloud.trace.client import Client
23-
24-
2525
# OpenCensus Version
2626
VERSION = '0.1.3'
2727

@@ -132,33 +132,46 @@ def __init__(self, client=None, project_id=None,
132132
self.project_id = client.project
133133
self.transport = transport(self)
134134

135-
def emit(self, spans):
135+
def emit(self, span_datas):
136136
"""
137-
:type spans: dict
138-
:param spans: Spans collected.
137+
:type span_datas: list of :class:
138+
`~opencensus.trace.span_data.SpanData`
139+
:param list of opencensus.trace.span_data.SpanData span_datas:
140+
SpanData tuples to emit
139141
"""
140142
name = 'projects/{}'.format(self.project_id)
141-
stackdriver_spans = self.translate_to_stackdriver(spans)
143+
144+
# convert to the legacy trace json for easier refactoring
145+
# TODO: refactor this to use the span data directly
146+
trace = span_data.format_legacy_trace_json(span_datas)
147+
148+
stackdriver_spans = self.translate_to_stackdriver(trace)
142149
self.client.batch_write_spans(name, stackdriver_spans)
143150

144-
def export(self, trace):
145-
self.transport.export(trace)
151+
def export(self, span_datas):
152+
"""
153+
:type span_datas: list of :class:
154+
`~opencensus.trace.span_data.SpanData`
155+
:param list of opencensus.trace.span_data.SpanData span_datas:
156+
SpanData tuples to export
157+
"""
158+
self.transport.export(span_datas)
146159

147-
def translate_to_stackdriver(self, spans):
160+
def translate_to_stackdriver(self, trace):
148161
"""Translate the spans json to Stackdriver format.
149162
150163
See: https://cloud.google.com/trace/docs/reference/v2/rest/v2/
151164
projects.traces/batchWrite
152165
153-
:type spans: dict
154-
:param spans: Spans collected.
166+
:type trace: dict
167+
:param trace: Trace dictionary
155168
156169
:rtype: dict
157170
:returns: Spans in Google Cloud StackDriver Trace format.
158171
"""
159-
set_attributes(spans)
160-
spans_json = spans.get('spans')
161-
trace_id = spans.get('traceId')
172+
set_attributes(trace)
173+
spans_json = trace.get('spans')
174+
trace_id = trace.get('traceId')
162175
spans_list = []
163176

164177
for span in spans_json:

opencensus/trace/exporters/transports/background_thread.py

Lines changed: 11 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -81,34 +81,27 @@ def _get_items(self):
8181
def _thread_main(self):
8282
"""The entry point for the worker thread.
8383
84-
Pulls pending spans off the queue and writes them in batches to
85-
the specified tracing backend using the exporter.
84+
Pulls pending SpanData tuples off the queue and writes them in
85+
batches to the specified tracing backend using the exporter.
8686
"""
8787
print('Background thread started.')
8888

8989
quit_ = False
9090

9191
while True:
9292
items = self._get_items()
93-
trace_id = None
94-
spans = []
93+
span_datas = []
9594

9695
for item in items:
9796
if item is _WORKER_TERMINATOR:
9897
quit_ = True
9998
# Continue processing items, don't break, try to process
10099
# all items we got back before quitting.
101100
else:
102-
trace_id = item.get('traceId')
103-
spans.extend(item.get('spans'))
101+
span_datas.extend(item)
104102

105-
if spans and trace_id:
106-
spans_json = {
107-
'traceId': trace_id,
108-
'spans': spans,
109-
}
110-
111-
self.exporter.emit(spans_json)
103+
if span_datas:
104+
self.exporter.emit(span_datas)
112105

113106
for _ in range(len(items)):
114107
self._queue.task_done()
@@ -181,9 +174,9 @@ def _export_pending_spans(self):
181174
else:
182175
print('Failed to send pending spans.')
183176

184-
def enqueue(self, trace):
185-
"""Queues a trace to be written by the background thread."""
186-
self._queue.put_nowait(trace)
177+
def enqueue(self, span_datas):
178+
"""Queues span_datas to be written by the background thread."""
179+
self._queue.put_nowait(span_datas)
187180

188181
def flush(self):
189182
"""Submit any pending spans."""
@@ -214,9 +207,9 @@ def __init__(self, exporter, grace_period=_DEFAULT_GRACE_PERIOD,
214207
self.worker = _Worker(exporter, grace_period, max_batch_size)
215208
self.worker.start()
216209

217-
def export(self, trace):
210+
def export(self, span_datas):
218211
"""Put the trace to be exported into queue."""
219-
self.worker.enqueue(trace)
212+
self.worker.enqueue(span_datas)
220213

221214
def flush(self):
222215
"""Submit any pending traces."""

opencensus/trace/exporters/transports/base.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ class Transport(object):
2020
2121
Subclasses of :class:`Transport` must override :meth:`export`.
2222
"""
23-
def export(self, trace):
24-
"""Export the trace by calling exporter.emit()."""
23+
def export(self, span_datas):
24+
"""Export the SpanData tuples by calling exporter.emit()."""
2525
raise NotImplementedError
2626

2727
def flush(self):

opencensus/trace/exporters/transports/sync.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,5 +19,5 @@ class SyncTransport(base.Transport):
1919
def __init__(self, exporter):
2020
self.exporter = exporter
2121

22-
def export(self, trace):
23-
self.exporter.emit(trace)
22+
def export(self, span_datas):
23+
self.exporter.emit(span_datas)

opencensus/trace/exporters/zipkin_exporter.py

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,14 @@
1414

1515
"""Export the spans data to Zipkin Collector."""
1616

17+
import calendar
1718
import datetime
1819
import json
1920
import logging
21+
2022
import requests
21-
import calendar
2223

24+
from opencensus.trace import span_data
2325
from opencensus.trace.exporters import base
2426
from opencensus.trace.exporters.transports import sync
2527

@@ -90,12 +92,18 @@ def get_url(self):
9092
self.port,
9193
self.endpoint)
9294

93-
def emit(self, trace):
94-
"""Send trace to Zipkin server, default using the v2 API.
95+
def emit(self, span_datas):
96+
"""Send SpanData tuples to Zipkin server, default using the v2 API.
9597
96-
:type trace: dict
97-
:param trace: Trace data in dictionary format.
98+
:type span_datas: list of :class:
99+
`~opencensus.trace.span_data.SpanData`
100+
:param list of opencensus.trace.span_data.SpanData span_datas:
101+
SpanData tuples to emit
98102
"""
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+
99107
trace_id = trace.get('traceId')
100108
spans = trace.get('spans')
101109

@@ -113,8 +121,8 @@ def emit(self, trace):
113121
except Exception as e: # pragma: NO COVER
114122
logging.error(getattr(e, 'message', e))
115123

116-
def export(self, trace):
117-
self.transport.export(trace)
124+
def export(self, span_datas):
125+
self.transport.export(span_datas)
118126

119127
def translate_to_zipkin(self, trace_id, spans):
120128
"""Translate the opencensus spans to zipkin spans.

opencensus/trace/span.py

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,12 @@
2525
from opencensus.trace.utils import _get_truncatable_str
2626

2727

28+
class SpanKind(object):
29+
UNSPECIFIED = 0
30+
SERVER = 1
31+
CLIENT = 2
32+
33+
2834
class Span(object):
2935
"""A span is an individual timed event which forms a node of the trace
3036
tree. Each span has its name, span id and parent id. The parent id
@@ -85,6 +91,11 @@ class Span(object):
8591
method in the tracer class to finish a span. If no
8692
tracer is passed in, then just finish the span using
8793
the finish method in the Span class.
94+
95+
:type span_kind: int
96+
:param span_kind: (Optional) Highly recommended flag that denotes the type
97+
of span (valid values defined by :class:
98+
`opencensus.trace.span.SpanKind`)
8899
"""
89100

90101
def __init__(
@@ -100,7 +111,8 @@ def __init__(
100111
links=None,
101112
status=None,
102113
same_process_as_parent_span=None,
103-
context_tracer=None):
114+
context_tracer=None,
115+
span_kind=SpanKind.UNSPECIFIED):
104116
self.name = name
105117
self.parent_span = parent_span
106118
self.start_time = start_time
@@ -132,6 +144,7 @@ def __init__(
132144
self.same_process_as_parent_span = same_process_as_parent_span
133145
self._child_spans = []
134146
self.context_tracer = context_tracer
147+
self.span_kind = span_kind
135148

136149
@property
137150
def children(self):

0 commit comments

Comments
 (0)