Skip to content

Commit 35cb914

Browse files
authored
Span.set_tag: validate tag name and value types (#245)
* Span.set_tag: validate tag name and value types * Test set_tag bad data types * Add list to the valid types * Move tests to the opentracing area
1 parent 6d6be25 commit 35cb914

File tree

3 files changed

+69
-1
lines changed

3 files changed

+69
-1
lines changed

instana/span.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,18 @@
1+
import sys
12
from .log import logger
23
from .util import DictionaryOfStan
34
from basictracer.span import BasicSpan
45
import opentracing.ext.tags as ot_tags
56

67

8+
PY3 = sys.version_info[0] == 3
9+
10+
if PY3:
11+
string_type = str
12+
else:
13+
string_type = basestring
14+
15+
716
class SpanContext():
817
def __init__(
918
self,
@@ -39,6 +48,23 @@ class InstanaSpan(BasicSpan):
3948
def finish(self, finish_time=None):
4049
super(InstanaSpan, self).finish(finish_time)
4150

51+
def set_tag(self, key, value):
52+
if not isinstance(key, string_type):
53+
logger.debug("(non-fatal) span.set_tag: tag names must be strings. tag discarded for %s", type(key))
54+
return self
55+
56+
final_value = value
57+
value_type = type(value)
58+
if value_type not in [bool, float, int, list, str]:
59+
try:
60+
final_value = str(value)
61+
except:
62+
final_value = "(non-fatal) span.set_tag: values must be one of these types: bool, float, int, list or str. tag discarded"
63+
logger.debug(final_value, exc_info=True)
64+
65+
return super(InstanaSpan, self).set_tag(key, final_value)
66+
67+
4268
def mark_as_errored(self, tags = None):
4369
"""
4470
Mark this span as errored.
File renamed without changes.

tests/opentracing/test_ot_span.py

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import time
2-
32
import unittest
43
import opentracing
4+
from uuid import UUID
5+
from instana.util import to_json
56
from instana.singletons import tracer
67

78

@@ -144,3 +145,44 @@ def test_span_kind(self):
144145

145146
span = spans[4]
146147
self.assertEqual(3, span.k)
148+
149+
def test_bad_tag_values(self):
150+
with tracer.start_active_span('test') as scope:
151+
# Set a UUID class as a tag
152+
# If unchecked, this causes a json.dumps error: "ValueError: Circular reference detected"
153+
scope.span.set_tag('uuid', UUID(bytes=b'\x12\x34\x56\x78'*4))
154+
# Arbitrarily setting an instance of some class
155+
scope.span.set_tag('tracer', tracer)
156+
scope.span.set_tag('none', None)
157+
scope.span.set_tag('mylist', [1, 2, 3])
158+
159+
160+
spans = tracer.recorder.queued_spans()
161+
assert len(spans) == 1
162+
163+
test_span = spans[0]
164+
assert(test_span)
165+
assert(len(test_span.data['sdk']['custom']['tags']) == 4)
166+
assert(test_span.data['sdk']['custom']['tags']['uuid'] == '12345678-1234-5678-1234-567812345678')
167+
assert(test_span.data['sdk']['custom']['tags']['tracer'])
168+
assert(test_span.data['sdk']['custom']['tags']['none'] == 'None')
169+
assert(test_span.data['sdk']['custom']['tags']['mylist'] == [1, 2, 3])
170+
171+
json_data = to_json(test_span)
172+
assert(json_data)
173+
174+
def test_bad_tag_names(self):
175+
with tracer.start_active_span('test') as scope:
176+
# Tag names (keys) must be strings
177+
scope.span.set_tag(1234567890, 'This should not get set')
178+
179+
spans = tracer.recorder.queued_spans()
180+
assert len(spans) == 1
181+
182+
test_span = spans[0]
183+
assert(test_span)
184+
assert(len(test_span.data['sdk']['custom']['tags']) == 0)
185+
186+
json_data = to_json(test_span)
187+
assert(json_data)
188+

0 commit comments

Comments
 (0)