-
Notifications
You must be signed in to change notification settings - Fork 250
/
Copy pathtrace_context_http_header_format.py
115 lines (95 loc) · 3.74 KB
/
trace_context_http_header_format.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
# Copyright 2017, OpenCensus Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import re
from opencensus.trace.propagation.tracestate_string_format import (
TracestateStringFormatter,
)
from opencensus.trace.span_context import SpanContext
from opencensus.trace.trace_options import TraceOptions
_TRACEPARENT_HEADER_NAME = 'traceparent'
_TRACESTATE_HEADER_NAME = 'tracestate'
_TRACEPARENT_HEADER_FORMAT = \
'^[ \t]*([0-9a-f]{2})-([0-9a-f]{32})-([0-9a-f]{16})-([0-9a-f]{2})' + \
'(-.*)?[ \t]*$'
_TRACEPARENT_HEADER_FORMAT_RE = re.compile(_TRACEPARENT_HEADER_FORMAT)
class TraceContextPropagator(object):
"""Propagator for processing the trace context HTTP header format."""
def from_headers(self, headers):
"""Generate a SpanContext object using the W3C Distributed Tracing headers.
:type headers: dict
:param headers: HTTP request headers.
:rtype: :class:`~opencensus.trace.span_context.SpanContext`
:returns: SpanContext generated from the trace context header.
"""
if headers is None:
return SpanContext()
header = headers.get(_TRACEPARENT_HEADER_NAME)
if header is None:
return SpanContext()
match = re.search(_TRACEPARENT_HEADER_FORMAT_RE, header)
if not match:
return SpanContext()
version = match.group(1)
trace_id = match.group(2)
span_id = match.group(3)
trace_options = match.group(4)
if trace_id == '0' * 32 or span_id == '0' * 16:
return SpanContext()
if version == '00':
if match.group(5):
return SpanContext()
if version == 'ff':
return SpanContext()
span_context = SpanContext(
trace_id=trace_id,
span_id=span_id,
trace_options=TraceOptions(trace_options),
from_header=True)
header = headers.get(_TRACESTATE_HEADER_NAME)
if header is None:
return span_context
try:
tracestate = TracestateStringFormatter().from_string(header)
if tracestate.is_valid():
span_context.tracestate = \
TracestateStringFormatter().from_string(header)
except ValueError:
pass
return span_context
def to_headers(self, span_context):
"""Convert a SpanContext object to W3C Distributed Tracing headers,
using version 0.
:type span_context:
:class:`~opencensus.trace.span_context.SpanContext`
:param span_context: SpanContext object.
:rtype: dict
:returns: W3C Distributed Tracing headers.
"""
trace_id = span_context.trace_id
span_id = span_context.span_id
trace_options = span_context.trace_options.enabled
# Convert the trace options
trace_options = '01' if trace_options else '00'
headers = {
_TRACEPARENT_HEADER_NAME: '00-{}-{}-{}'.format(
trace_id,
span_id,
trace_options
),
}
tracestate = span_context.tracestate
if tracestate:
headers[_TRACESTATE_HEADER_NAME] = \
TracestateStringFormatter().to_string(tracestate)
return headers