Skip to content

Commit d01bc87

Browse files
author
Peter Giacomo Lombardo
authored
Tag Validation: Run validations on Span record (#262)
1 parent b149928 commit d01bc87

File tree

1 file changed

+65
-81
lines changed

1 file changed

+65
-81
lines changed

instana/span.py

Lines changed: 65 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -23,81 +23,6 @@ class InstanaSpan(BasicSpan):
2323
stack = None
2424
synthetic = False
2525

26-
def __init__(self, tracer, operation_name=None, context=None, parent_id=None, tags=None, start_time=None):
27-
# Tag validation
28-
filtered_tags = {}
29-
if tags is not None:
30-
for key in tags.keys():
31-
validated_key, validated_value = self._validate_tag(key, tags[key])
32-
if validated_key is not None:
33-
filtered_tags[validated_key] = validated_value
34-
35-
super(InstanaSpan, self).__init__(tracer, operation_name, context, parent_id, filtered_tags, start_time)
36-
37-
def _validate_tag(self, key, value):
38-
"""
39-
This method will assure that <key> and <value> are valid to set as a tag.
40-
If <value> fails the check, an attempt will be made to convert it into
41-
something useful.
42-
43-
On check failure, this method will return None values indicating that the tag is
44-
not valid and could not be converted into something useful
45-
46-
:param key: The tag key
47-
:param value: The tag value
48-
:return: Tuple (key, value)
49-
"""
50-
validated_key = None
51-
validated_value = None
52-
53-
try:
54-
# Tag keys must be some type of text or string type
55-
if isinstance(key, (six.text_type, six.string_types)):
56-
validated_key = key[0:1024] # Max key length of 1024 characters
57-
58-
if isinstance(value, (bool, float, int, list, dict, six.text_type, six.string_types)):
59-
validated_value = value
60-
else:
61-
validated_value = self._convert_tag_value(value)
62-
else:
63-
logger.debug("(non-fatal) tag names must be strings. tag discarded for %s", type(key))
64-
except Exception:
65-
logger.debug("instana.span._validate_tag: ", exc_info=True)
66-
67-
return (validated_key, validated_value)
68-
69-
def _convert_tag_value(self, value):
70-
final_value = None
71-
72-
try:
73-
final_value = repr(value)
74-
except Exception:
75-
final_value = "(non-fatal) span.set_tag: values must be one of these types: bool, float, int, list, " \
76-
"set, str or alternatively support 'repr'. tag discarded"
77-
logger.debug(final_value, exc_info=True)
78-
return None
79-
return final_value
80-
81-
def set_tag(self, key, value):
82-
validated_key, validated_value = self._validate_tag(key, value)
83-
84-
if validated_key is not None and validated_value is not None:
85-
return super(InstanaSpan, self).set_tag(validated_key, validated_value)
86-
87-
return self
88-
89-
def log_kv(self, key_values, timestamp=None):
90-
validated_key = None
91-
validated_value = None
92-
93-
for key in key_values.keys():
94-
validated_key, validated_value = self._validate_tag(key, key_values[key])
95-
96-
if validated_key is not None and validated_value is not None:
97-
return super(InstanaSpan, self).log_kv({validated_key: validated_value}, timestamp)
98-
99-
return self
100-
10126
def mark_as_errored(self, tags = None):
10227
"""
10328
Mark this span as errored.
@@ -160,7 +85,6 @@ def log_exception(self, exc):
16085
logger.debug("span.log_exception", exc_info=True)
16186
raise
16287

163-
16488
class BaseSpan(object):
16589
sy = None
16690

@@ -188,6 +112,64 @@ def __init__(self, span, source, service_name, **kwargs):
188112
self.stack = span.stack
189113

190114
self.__dict__.update(kwargs)
115+
116+
def _validate_tags(self, tags):
117+
"""
118+
This method will loop through a set of tags to validate each key and value.
119+
120+
:param tags: dict of tags
121+
:return: dict - a filtered set of tags
122+
"""
123+
filtered_tags = {}
124+
for key in tags.keys():
125+
validated_key, validated_value = self._validate_tag(key, tags[key])
126+
if validated_key is not None and validated_value is not None:
127+
filtered_tags[validated_key] = validated_value
128+
return filtered_tags
129+
130+
def _validate_tag(self, key, value):
131+
"""
132+
This method will assure that <key> and <value> are valid to set as a tag.
133+
If <value> fails the check, an attempt will be made to convert it into
134+
something useful.
135+
136+
On check failure, this method will return None values indicating that the tag is
137+
not valid and could not be converted into something useful
138+
139+
:param key: The tag key
140+
:param value: The tag value
141+
:return: Tuple (key, value)
142+
"""
143+
validated_key = None
144+
validated_value = None
145+
146+
try:
147+
# Tag keys must be some type of text or string type
148+
if isinstance(key, (six.text_type, six.string_types)):
149+
validated_key = key[0:1024] # Max key length of 1024 characters
150+
151+
if isinstance(value, (bool, float, int, list, dict, six.text_type, six.string_types)):
152+
validated_value = value
153+
else:
154+
validated_value = self._convert_tag_value(value)
155+
else:
156+
logger.debug("(non-fatal) tag names must be strings. tag discarded for %s", type(key))
157+
except Exception:
158+
logger.debug("instana.span._validate_tag: ", exc_info=True)
159+
160+
return (validated_key, validated_value)
161+
162+
def _convert_tag_value(self, value):
163+
final_value = None
164+
165+
try:
166+
final_value = repr(value)
167+
except Exception:
168+
final_value = "(non-fatal) span.set_tag: values must be one of these types: bool, float, int, list, " \
169+
"set, str or alternatively support 'repr'. tag discarded"
170+
logger.debug(final_value, exc_info=True)
171+
return None
172+
return final_value
191173

192174

193175
class SDKSpan(BaseSpan):
@@ -208,12 +190,14 @@ def __init__(self, span, source, service_name, **kwargs):
208190

209191
self.data["sdk"]["name"] = span.operation_name
210192
self.data["sdk"]["type"] = span_kind[0]
211-
self.data["sdk"]["custom"]["tags"] = span.tags
193+
self.data["sdk"]["custom"]["tags"] = self._validate_tags(span.tags)
212194

213195
if span.logs is not None and len(span.logs) > 0:
214196
logs = DictionaryOfStan()
215197
for log in span.logs:
216-
logs[repr(log.timestamp)] = log.key_values
198+
filtered_key_values = self._validate_tags(log.key_values)
199+
if len(filtered_key_values.keys()) > 0:
200+
logs[repr(log.timestamp)] = filtered_key_values
217201
self.data["sdk"]["custom"]["logs"] = logs
218202

219203
if "arguments" in span.tags:
@@ -227,8 +211,8 @@ def __init__(self, span, source, service_name, **kwargs):
227211

228212
def get_span_kind(self, span):
229213
"""
230-
Will retrieve the `span.kind` tag and return a tuple containing the appropriate string and integer
231-
values for the Instana backend
214+
Will retrieve the `span.kind` tag and return a tuple containing the appropriate string and integer
215+
values for the Instana backend
232216
233217
:param span: The span to search for the `span.kind` tag
234218
:return: Tuple (String, Int)
@@ -277,7 +261,7 @@ def __init__(self, span, source, service_name, **kwargs):
277261

278262
# Store any leftover tags in the custom section
279263
if len(span.tags) > 0:
280-
self.data["custom"]["tags"] = span.tags
264+
self.data["custom"]["tags"] = self._validate_tags(span.tags)
281265

282266
def _populate_entry_span_data(self, span):
283267
if span.operation_name in self.HTTP_SPANS:

0 commit comments

Comments
 (0)