Skip to content

Commit 632bf89

Browse files
authored
Send Server-Timing in response headers (#124)
1 parent ab860d2 commit 632bf89

File tree

4 files changed

+205
-60
lines changed

4 files changed

+205
-60
lines changed

instana/http_propagator.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,15 +25,20 @@ class HTTPPropagator():
2525
HEADER_KEY_T = 'X-Instana-T'
2626
HEADER_KEY_S = 'X-Instana-S'
2727
HEADER_KEY_L = 'X-Instana-L'
28+
HEADER_KEY_ST = 'Server-Timing'
2829
LC_HEADER_KEY_T = 'x-instana-t'
2930
LC_HEADER_KEY_S = 'x-instana-s'
3031
LC_HEADER_KEY_L = 'x-instana-l'
32+
LC_HEADER_KEY_ST = 'server-timing'
33+
3134
ALT_HEADER_KEY_T = 'HTTP_X_INSTANA_T'
3235
ALT_HEADER_KEY_S = 'HTTP_X_INSTANA_S'
3336
ALT_HEADER_KEY_L = 'HTTP_X_INSTANA_L'
37+
ATL_HEADER_KEY_ST = 'HTTP_SERVER_TIMING'
3438
ALT_LC_HEADER_KEY_T = 'http_x_instana_t'
3539
ALT_LC_HEADER_KEY_S = 'http_x_instana_s'
3640
ALT_LC_HEADER_KEY_L = 'http_x_instana_l'
41+
ATL_LC_HEADER_KEY_ST = 'http_server_timing'
3742

3843
def inject(self, span_context, carrier):
3944
try:
@@ -44,10 +49,12 @@ def inject(self, span_context, carrier):
4449
carrier[self.HEADER_KEY_T] = trace_id
4550
carrier[self.HEADER_KEY_S] = span_id
4651
carrier[self.HEADER_KEY_L] = "1"
52+
carrier[self.HEADER_KEY_ST] = "intid;desc=%s" % trace_id
4753
elif type(carrier) is list:
4854
carrier.append((self.HEADER_KEY_T, trace_id))
4955
carrier.append((self.HEADER_KEY_S, span_id))
5056
carrier.append((self.HEADER_KEY_L, "1"))
57+
carrier.append((self.HEADER_KEY_ST, "intid;desc=%s" % trace_id))
5158
else:
5259
raise Exception("Unsupported carrier type", type(carrier))
5360

tests/test_django.py

Lines changed: 76 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,6 @@ def test_basic_request(self):
2929

3030
assert response
3131
assert_equals(200, response.status)
32-
assert('X-Instana-T' in response.headers)
33-
assert(int(response.headers['X-Instana-T'], 16))
34-
assert('X-Instana-S' in response.headers)
35-
assert(int(response.headers['X-Instana-S'], 16))
36-
assert('X-Instana-L' in response.headers)
37-
assert_equals('1', response.headers['X-Instana-L'])
3832

3933
spans = self.recorder.queued_spans()
4034
assert_equals(3, len(spans))
@@ -43,6 +37,21 @@ def test_basic_request(self):
4337
urllib3_span = spans[1]
4438
django_span = spans[0]
4539

40+
assert ('X-Instana-T' in response.headers)
41+
assert (int(response.headers['X-Instana-T'], 16))
42+
self.assertEqual(django_span.t, response.headers['X-Instana-T'])
43+
44+
assert ('X-Instana-S' in response.headers)
45+
assert (int(response.headers['X-Instana-S'], 16))
46+
self.assertEqual(django_span.s, response.headers['X-Instana-S'])
47+
48+
assert ('X-Instana-L' in response.headers)
49+
assert_equals('1', response.headers['X-Instana-L'])
50+
51+
server_timing_value = "intid;desc=%s" % django_span.t
52+
assert ('Server-Timing' in response.headers)
53+
self.assertEqual(server_timing_value, response.headers['Server-Timing'])
54+
4655
assert_equals("test", test_span.data.sdk.name)
4756
assert_equals("urllib3", urllib3_span.n)
4857
assert_equals("django", django_span.n)
@@ -68,12 +77,6 @@ def test_request_with_error(self):
6877

6978
assert response
7079
assert_equals(500, response.status)
71-
assert('X-Instana-T' in response.headers)
72-
assert(int(response.headers['X-Instana-T'], 16))
73-
assert('X-Instana-S' in response.headers)
74-
assert(int(response.headers['X-Instana-S'], 16))
75-
assert('X-Instana-L' in response.headers)
76-
assert_equals('1', response.headers['X-Instana-L'])
7780

7881
spans = self.recorder.queued_spans()
7982
assert_equals(3, len(spans))
@@ -82,6 +85,21 @@ def test_request_with_error(self):
8285
urllib3_span = spans[1]
8386
django_span = spans[0]
8487

88+
assert ('X-Instana-T' in response.headers)
89+
assert (int(response.headers['X-Instana-T'], 16))
90+
self.assertEqual(django_span.t, response.headers['X-Instana-T'])
91+
92+
assert ('X-Instana-S' in response.headers)
93+
assert (int(response.headers['X-Instana-S'], 16))
94+
self.assertEqual(django_span.s, response.headers['X-Instana-S'])
95+
96+
assert ('X-Instana-L' in response.headers)
97+
assert_equals('1', response.headers['X-Instana-L'])
98+
99+
server_timing_value = "intid;desc=%s" % django_span.t
100+
assert ('Server-Timing' in response.headers)
101+
self.assertEqual(server_timing_value, response.headers['Server-Timing'])
102+
85103
assert_equals("test", test_span.data.sdk.name)
86104
assert_equals("urllib3", urllib3_span.n)
87105
assert_equals("django", django_span.n)
@@ -108,13 +126,6 @@ def test_complex_request(self):
108126

109127
assert response
110128
assert_equals(200, response.status)
111-
assert('X-Instana-T' in response.headers)
112-
assert(int(response.headers['X-Instana-T'], 16))
113-
assert('X-Instana-S' in response.headers)
114-
assert(int(response.headers['X-Instana-S'], 16))
115-
assert('X-Instana-L' in response.headers)
116-
assert_equals('1', response.headers['X-Instana-L'])
117-
118129
spans = self.recorder.queued_spans()
119130
assert_equals(5, len(spans))
120131

@@ -124,6 +135,21 @@ def test_complex_request(self):
124135
ot_span1 = spans[1]
125136
ot_span2 = spans[0]
126137

138+
assert ('X-Instana-T' in response.headers)
139+
assert (int(response.headers['X-Instana-T'], 16))
140+
self.assertEqual(django_span.t, response.headers['X-Instana-T'])
141+
142+
assert ('X-Instana-S' in response.headers)
143+
assert (int(response.headers['X-Instana-S'], 16))
144+
self.assertEqual(django_span.s, response.headers['X-Instana-S'])
145+
146+
assert ('X-Instana-L' in response.headers)
147+
assert_equals('1', response.headers['X-Instana-L'])
148+
149+
server_timing_value = "intid;desc=%s" % django_span.t
150+
assert ('Server-Timing' in response.headers)
151+
self.assertEqual(server_timing_value, response.headers['Server-Timing'])
152+
127153
assert_equals("test", test_span.data.sdk.name)
128154
assert_equals("urllib3", urllib3_span.n)
129155
assert_equals("django", django_span.n)
@@ -163,12 +189,6 @@ def test_custom_header_capture(self):
163189

164190
assert response
165191
assert_equals(200, response.status)
166-
assert('X-Instana-T' in response.headers)
167-
assert(int(response.headers['X-Instana-T'], 16))
168-
assert('X-Instana-S' in response.headers)
169-
assert(int(response.headers['X-Instana-S'], 16))
170-
assert('X-Instana-L' in response.headers)
171-
assert_equals('1', response.headers['X-Instana-L'])
172192

173193
spans = self.recorder.queued_spans()
174194
assert_equals(3, len(spans))
@@ -210,13 +230,6 @@ def test_with_incoming_context(self):
210230

211231
assert response
212232
assert_equals(200, response.status)
213-
assert('X-Instana-T' in response.headers)
214-
assert(int(response.headers['X-Instana-T'], 16))
215-
self.assertEqual('0000000000000001', response.headers['X-Instana-T'])
216-
assert('X-Instana-S' in response.headers)
217-
assert(int(response.headers['X-Instana-S'], 16))
218-
assert('X-Instana-L' in response.headers)
219-
assert_equals('1', response.headers['X-Instana-L'])
220233

221234
spans = self.recorder.queued_spans()
222235
assert_equals(1, len(spans))
@@ -226,6 +239,21 @@ def test_with_incoming_context(self):
226239
assert_equals(django_span.t, '0000000000000001')
227240
assert_equals(django_span.p, '0000000000000001')
228241

242+
assert ('X-Instana-T' in response.headers)
243+
assert (int(response.headers['X-Instana-T'], 16))
244+
self.assertEqual(django_span.t, response.headers['X-Instana-T'])
245+
246+
assert ('X-Instana-S' in response.headers)
247+
assert (int(response.headers['X-Instana-S'], 16))
248+
self.assertEqual(django_span.s, response.headers['X-Instana-S'])
249+
250+
assert ('X-Instana-L' in response.headers)
251+
assert_equals('1', response.headers['X-Instana-L'])
252+
253+
server_timing_value = "intid;desc=%s" % django_span.t
254+
assert ('Server-Timing' in response.headers)
255+
self.assertEqual(server_timing_value, response.headers['Server-Timing'])
256+
229257
def test_with_incoming_mixed_case_context(self):
230258
request_headers = dict()
231259
request_headers['X-InSTANa-T'] = '0000000000000001'
@@ -235,18 +263,26 @@ def test_with_incoming_mixed_case_context(self):
235263

236264
assert response
237265
assert_equals(200, response.status)
238-
assert('X-Instana-T' in response.headers)
239-
assert(int(response.headers['X-Instana-T'], 16))
240-
self.assertEqual('0000000000000001', response.headers['X-Instana-T'])
241-
assert('X-Instana-S' in response.headers)
242-
assert(int(response.headers['X-Instana-S'], 16))
243-
assert('X-Instana-L' in response.headers)
244-
assert_equals('1', response.headers['X-Instana-L'])
245266

246267
spans = self.recorder.queued_spans()
247268
assert_equals(1, len(spans))
248269

249270
django_span = spans[0]
250271

251272
assert_equals(django_span.t, '0000000000000001')
252-
assert_equals(django_span.p, '0000000000000001')
273+
assert_equals(django_span.p, '0000000000000001')
274+
275+
assert ('X-Instana-T' in response.headers)
276+
assert (int(response.headers['X-Instana-T'], 16))
277+
self.assertEqual(django_span.t, response.headers['X-Instana-T'])
278+
279+
assert ('X-Instana-S' in response.headers)
280+
assert (int(response.headers['X-Instana-S'], 16))
281+
self.assertEqual(django_span.s, response.headers['X-Instana-S'])
282+
283+
assert ('X-Instana-L' in response.headers)
284+
assert_equals('1', response.headers['X-Instana-L'])
285+
286+
server_timing_value = "intid;desc=%s" % django_span.t
287+
assert ('Server-Timing' in response.headers)
288+
self.assertEqual(server_timing_value, response.headers['Server-Timing'])

tests/test_ot_propagators.py

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ def test_basics():
2121
assert callable(extract_func)
2222

2323

24-
def test_inject():
24+
def test_inject_with_dict():
2525
opts = options.Options()
2626
ot.tracer = InstanaTracer(opts)
2727

@@ -35,6 +35,24 @@ def test_inject():
3535
assert_equals(carrier['X-Instana-S'], span.context.span_id)
3636
assert 'X-Instana-L' in carrier
3737
assert_equals(carrier['X-Instana-L'], "1")
38+
assert 'Server-Timing' in carrier
39+
server_timing_value = "intid;desc=%s" % span.context.trace_id
40+
assert_equals(carrier['Server-Timing'], server_timing_value)
41+
42+
43+
def test_inject_with_list():
44+
opts = options.Options()
45+
ot.tracer = InstanaTracer(opts)
46+
47+
carrier = []
48+
span = ot.tracer.start_span("nosetests")
49+
ot.tracer.inject(span.context, ot.Format.HTTP_HEADERS, carrier)
50+
51+
assert ('X-Instana-T', span.context.trace_id) in carrier
52+
assert ('X-Instana-S', span.context.span_id) in carrier
53+
assert ('X-Instana-L', "1") in carrier
54+
server_timing_value = "intid;desc=%s" % span.context.trace_id
55+
assert ('Server-Timing', server_timing_value) in carrier
3856

3957

4058
def test_basic_extract():

0 commit comments

Comments
 (0)