22
22
23
23
24
24
def get_as_list (
25
- dict_object : typing .Dict [str , str ], key : str
25
+ dict_object : typing .Dict [str , typing . List [ str ] ], key : str
26
26
) -> typing .List [str ]:
27
27
value = dict_object .get (key )
28
- return [ value ] if value is not None else []
28
+ return value if value is not None else []
29
29
30
30
31
31
class TestTraceContextFormat (unittest .TestCase ):
@@ -44,33 +44,6 @@ def test_no_traceparent_header(self):
44
44
span_context = FORMAT .extract (get_as_list , output )
45
45
self .assertTrue (isinstance (span_context , trace .SpanContext ))
46
46
47
- def test_from_headers_tracestate_duplicated_keys (self ):
48
- """If a duplicate tracestate header is present, the most recent entry
49
- is used.
50
-
51
- RFC 3.3.1.4
52
-
53
- Only one entry per key is allowed because the entry represents that last position in the trace.
54
- Hence vendors must overwrite their entry upon reentry to their tracing system.
55
-
56
- For example, if a vendor name is Congo and a trace started in their system and then went through
57
- a system named Rojo and later returned to Congo, the tracestate value would not be:
58
-
59
- congo=congosFirstPosition,rojo=rojosFirstPosition,congo=congosSecondPosition
60
-
61
- Instead, the entry would be rewritten to only include the most recent position:
62
-
63
- congo=congosSecondPosition,rojo=rojosFirstPosition
64
- """
65
- span_context = FORMAT .extract (
66
- get_as_list ,
67
- {
68
- "traceparent" : "00-12345678901234567890123456789012-1234567890123456-00" ,
69
- "tracestate" : "foo=1,bar=2,foo=3" ,
70
- },
71
- )
72
- self .assertEqual (span_context .trace_state , {"foo" : "3" , "bar" : "2" })
73
-
74
47
def test_headers_with_tracestate (self ):
75
48
"""When there is a traceparent and tracestate header, data from
76
49
both should be addded to the SpanContext.
@@ -82,7 +55,10 @@ def test_headers_with_tracestate(self):
82
55
tracestate_value = "foo=1,bar=2,baz=3"
83
56
span_context = FORMAT .extract (
84
57
get_as_list ,
85
- {"traceparent" : traceparent_value , "tracestate" : tracestate_value },
58
+ {
59
+ "traceparent" : [traceparent_value ],
60
+ "tracestate" : [tracestate_value ],
61
+ },
86
62
)
87
63
self .assertEqual (span_context .trace_id , self .TRACE_ID )
88
64
self .assertEqual (span_context .span_id , self .SPAN_ID )
@@ -98,7 +74,8 @@ def test_headers_with_tracestate(self):
98
74
self .assertEqual (output ["tracestate" ].count ("," ), 2 )
99
75
100
76
def test_invalid_trace_id (self ):
101
- """If the trace id is invalid, we must ignore the full traceparent header.
77
+ """If the trace id is invalid, we must ignore the full traceparent header,
78
+ and return a random, valid trace.
102
79
103
80
Also ignore any tracestate.
104
81
@@ -115,11 +92,19 @@ def test_invalid_trace_id(self):
115
92
span_context = FORMAT .extract (
116
93
get_as_list ,
117
94
{
118
- "traceparent" : "00-00000000000000000000000000000000-1234567890123456-00" ,
119
- "tracestate" : "foo=1,bar=2,foo=3" ,
95
+ "traceparent" : [
96
+ "00-00000000000000000000000000000000-1234567890123456-00"
97
+ ],
98
+ "tracestate" : ["foo=1,bar=2,foo=3" ],
120
99
},
121
100
)
122
- self .assertEqual (span_context , trace .INVALID_SPAN_CONTEXT )
101
+ self .assertNotEqual (
102
+ span_context .span_id , trace .INVALID_SPAN_CONTEXT .span_id
103
+ )
104
+ self .assertNotEqual (
105
+ span_context .trace_id , trace .INVALID_SPAN_CONTEXT .trace_id
106
+ )
107
+ self .assertNotEqual (span_context .span_id , "1234567890123456" )
123
108
124
109
def test_invalid_parent_id (self ):
125
110
"""If the parent id is invalid, we must ignore the full traceparent header.
@@ -139,11 +124,14 @@ def test_invalid_parent_id(self):
139
124
span_context = FORMAT .extract (
140
125
get_as_list ,
141
126
{
142
- "traceparent" : "00-00000000000000000000000000000000-0000000000000000-00" ,
143
- "tracestate" : "foo=1,bar=2,foo=3" ,
127
+ "traceparent" : [
128
+ "00-00000000000000000000000000000000-0000000000000000-00"
129
+ ],
130
+ "tracestate" : ["foo=1,bar=2,foo=3" ],
144
131
},
145
132
)
146
- self .assertEqual (span_context , trace .INVALID_SPAN_CONTEXT )
133
+ self .assertNotEqual (span_context , trace .INVALID_SPAN_CONTEXT )
134
+ self .assertEqual (span_context .trace_state , trace .TraceState ())
147
135
148
136
def test_no_send_empty_tracestate (self ):
149
137
"""If the tracestate is empty, do not set the header.
@@ -174,15 +162,46 @@ def test_format_not_supported(self):
174
162
span_context = FORMAT .extract (
175
163
get_as_list ,
176
164
{
177
- "traceparent" : "00-12345678901234567890123456789012-1234567890123456-00-residue" ,
178
- "tracestate" : "foo=1,bar=2,foo=3" ,
165
+ "traceparent" : [
166
+ "00-12345678901234567890123456789012-1234567890123456-00-residue"
167
+ ],
168
+ "tracestate" : ["foo=1,bar=2,foo=3" ],
179
169
},
180
170
)
181
- self .assertEqual (span_context , trace .INVALID_SPAN_CONTEXT )
171
+ self .assertNotEqual (span_context , trace .INVALID_SPAN_CONTEXT )
172
+ self .assertNotEqual (span_context .trace_id , self .TRACE_ID )
182
173
183
174
def test_propagate_invalid_context (self ):
184
175
"""Do not propagate invalid trace context.
185
176
"""
186
177
output = {} # type:typing.Dict[str, str]
187
178
FORMAT .inject (trace .INVALID_SPAN_CONTEXT , dict .__setitem__ , output )
188
179
self .assertFalse ("traceparent" in output )
180
+
181
+ def test_tracestate_empty_header (self ):
182
+ """Do not propagate invalid trace context.
183
+ """
184
+ span_context = FORMAT .extract (
185
+ get_as_list ,
186
+ {
187
+ "traceparent" : [
188
+ "00-12345678901234567890123456789012-1234567890123456-00"
189
+ ],
190
+ "tracestate" : ["foo=1" , "" ],
191
+ },
192
+ )
193
+ self .assertEqual (span_context .trace_state ["foo" ], "1" )
194
+
195
+ def test_tracestate_header_with_trailing_comma (self ):
196
+ """Do not propagate invalid trace context.
197
+ """
198
+ span_context = FORMAT .extract (
199
+ get_as_list ,
200
+ {
201
+ "traceparent" : [
202
+ "00-12345678901234567890123456789012-1234567890123456-00"
203
+ ],
204
+ "tracestate" : ["foo=1," ],
205
+ },
206
+ )
207
+ self .assertEqual (span_context .trace_state ["foo" ], "1" )
0 commit comments