Skip to content

Commit 86a2d7c

Browse files
authored
Merge pull request #141 from swiftstack/adding-annotations
Add a zipkin_span.add_annotation() method
2 parents 18dd27c + 9b333a7 commit 86a2d7c

File tree

3 files changed

+89
-4
lines changed

3 files changed

+89
-4
lines changed

py_zipkin/logging_helper.py

+4-4
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ def __init__(
3737
max_span_batch_size=None,
3838
firehose_handler=None,
3939
encoding=None,
40+
annotations=None,
4041
):
4142
self.zipkin_attrs = zipkin_attrs
4243
self.endpoint = endpoint
@@ -51,6 +52,7 @@ def __init__(
5152
self.client_context = client_context
5253
self.max_span_batch_size = max_span_batch_size
5354
self.firehose_handler = firehose_handler
55+
self.annotations = annotations or {}
5456

5557
self.remote_endpoint = None
5658
self.encoder = get_encoder(encoding)
@@ -108,10 +110,8 @@ def _emit_spans_with_span_sender(self, span_sender):
108110

109111
span_sender.add_span(span)
110112

111-
annotations = {}
112-
113113
if self.add_logging_annotation:
114-
annotations[LOGGING_END_KEY] = time.time()
114+
self.annotations[LOGGING_END_KEY] = time.time()
115115

116116
span_sender.add_span(Span(
117117
trace_id=self.zipkin_attrs.trace_id,
@@ -124,7 +124,7 @@ def _emit_spans_with_span_sender(self, span_sender):
124124
local_endpoint=self.endpoint,
125125
remote_endpoint=self.remote_endpoint,
126126
shared=not self.report_root_timestamp,
127-
annotations=annotations,
127+
annotations=self.annotations,
128128
tags=self.tags,
129129
))
130130

py_zipkin/zipkin.py

+21
Original file line numberDiff line numberDiff line change
@@ -457,6 +457,7 @@ def start(self):
457457
max_span_batch_size=self.max_span_batch_size,
458458
firehose_handler=self.firehose_handler,
459459
encoding=self.encoding,
460+
annotations=self.annotations,
460461
)
461462
self.logging_context.start()
462463
self.get_tracer().set_transport_configured(configured=True)
@@ -542,6 +543,26 @@ def update_binary_annotations(self, extra_annotations):
542543
# the binary annotations for the logging context directly.
543544
self.logging_context.tags.update(extra_annotations)
544545

546+
def add_annotation(self, value, timestamp=None):
547+
"""Add an annotation for the current span
548+
549+
The timestamp defaults to "now", but may be specified.
550+
551+
:param value: The annotation string
552+
:type value: str
553+
:param timestamp: Timestamp for the annotation
554+
:type timestamp: float
555+
"""
556+
timestamp = timestamp or time.time()
557+
if not self.logging_context:
558+
# This is not the root span, so annotations will be added
559+
# to the log handler when this span context exits.
560+
self.annotations[value] = timestamp
561+
else:
562+
# Otherwise, we're in the context of the root span, so just update
563+
# the annotations for the logging context directly.
564+
self.logging_context.annotations[value] = timestamp
565+
545566
def add_sa_binary_annotation(
546567
self,
547568
port=0,

tests/zipkin_test.py

+64
Original file line numberDiff line numberDiff line change
@@ -470,6 +470,7 @@ def test_start_root_span(self, mock_time, mock_log_ctx):
470470
max_span_batch_size=50,
471471
firehose_handler=firehose,
472472
encoding=Encoding.V2_JSON,
473+
annotations={},
473474
)
474475
assert mock_log_ctx.return_value.start.call_count == 1
475476
assert tracer.is_transport_configured() is True
@@ -729,6 +730,69 @@ def test_update_binary_annotations_non_root_not_traced(self):
729730
'status': '200',
730731
}
731732

733+
def test_add_annotation_root(self):
734+
with zipkin.zipkin_span(
735+
service_name='test_service',
736+
span_name='test_span',
737+
transport_handler=MockTransportHandler(),
738+
sample_rate=100.0,
739+
annotations={'abc': 123},
740+
add_logging_annotation=True,
741+
) as span:
742+
span.add_annotation('def', 345)
743+
span.add_annotation('ghi', timestamp=678)
744+
with mock.patch('py_zipkin.zipkin.time.time') as mock_time:
745+
mock_time.return_value = 91011
746+
span.add_annotation('jkl')
747+
748+
assert span.logging_context.annotations == {
749+
'abc': 123,
750+
'def': 345,
751+
'ghi': 678,
752+
'jkl': 91011,
753+
}
754+
755+
def test_add_annotation_non_root(self):
756+
context = zipkin.zipkin_span(
757+
service_name='test_service',
758+
span_name='test_span',
759+
annotations={'abc': 123},
760+
)
761+
context.get_tracer()._context_stack.push(zipkin.create_attrs_for_span())
762+
with context as span:
763+
span.add_annotation('def', 345)
764+
span.add_annotation('ghi', timestamp=678)
765+
with mock.patch('py_zipkin.zipkin.time.time') as mock_time:
766+
mock_time.return_value = 91011
767+
span.add_annotation('jkl')
768+
769+
assert span.annotations == {
770+
'abc': 123,
771+
'def': 345,
772+
'ghi': 678,
773+
'jkl': 91011,
774+
}
775+
776+
def test_add_annotation_non_root_not_traced(self):
777+
# nothing happens if the request is not traced
778+
with zipkin.zipkin_span(
779+
service_name='test_service',
780+
span_name='test_span',
781+
annotations={'abc': 123},
782+
) as span:
783+
span.add_annotation('def', 345)
784+
span.add_annotation('ghi', timestamp=678)
785+
with mock.patch('py_zipkin.zipkin.time.time') as mock_time:
786+
mock_time.return_value = 91011
787+
span.add_annotation('jkl')
788+
789+
assert span.annotations == {
790+
'abc': 123,
791+
'def': 345,
792+
'ghi': 678,
793+
'jkl': 91011,
794+
}
795+
732796
def test_add_sa_binary_annotation_non_client(self):
733797
# Nothing happens if this is not a client span
734798
context = zipkin.zipkin_span('test_service', 'test_span')

0 commit comments

Comments
 (0)