1# Copyright 2017, OpenCensus Authors
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7#     http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14
15from opencensus.trace.span_context import SpanContext
16from opencensus.trace.trace_options import TraceOptions
17
18_OPENCENSUS_TRACE_PREFIX = 'opencensus-trace'
19_TRACE_ID_KEY = '{}-traceid'.format(_OPENCENSUS_TRACE_PREFIX)
20_SPAN_ID_KEY = '{}-spanid'.format(_OPENCENSUS_TRACE_PREFIX)
21_TRACE_OPTIONS_KEY = '{}-traceoptions'.format(_OPENCENSUS_TRACE_PREFIX)
22
23DEFAULT_TRACE_OPTIONS = '1'
24
25
26class TextFormatPropagator(object):
27    """This class provides the basic utilities for extracting the trace
28    information from a carrier which is a dict to form a SpanContext. And
29    generating a dict using the provided SpanContext.
30    """
31    def from_carrier(self, carrier):
32        """Generate a SpanContext object using the information in the carrier.
33
34        :type carrier: dict
35        :param carrier: The carrier which has the trace_id, span_id, options
36                        information for creating a SpanContext.
37
38        :rtype: :class:`~opencensus.trace.span_context.SpanContext`
39        :returns: SpanContext generated from the carrier.
40        """
41        trace_id = None
42        span_id = None
43        trace_options = None
44
45        for key in carrier:
46            key = key.lower()
47            if key == _TRACE_ID_KEY:
48                trace_id = carrier[key]
49            if key == _SPAN_ID_KEY:
50                span_id = carrier[key]
51            if key == _TRACE_OPTIONS_KEY:
52                trace_options = bool(carrier[key])
53
54        if trace_options is None:
55            trace_options = DEFAULT_TRACE_OPTIONS
56
57        return SpanContext(
58            trace_id=trace_id,
59            span_id=span_id,
60            trace_options=TraceOptions(trace_options),
61            from_header=True)
62
63    def to_carrier(self, span_context, carrier):
64        """Inject the SpanContext fields to carrier dict.
65
66        :type span_context:
67            :class:`~opencensus.trace.span_context.SpanContext`
68        :param span_context: SpanContext object.
69
70        :type carrier: dict
71        :param carrier: The carrier which holds the trace_id, span_id, options
72                        information from a SpanContext.
73
74        :rtype: dict
75        :returns: The carrier which holds the span context information.
76        """
77        carrier[_TRACE_ID_KEY] = str(span_context.trace_id)
78
79        if span_context.span_id is not None:
80            carrier[_SPAN_ID_KEY] = str(span_context.span_id)
81
82        carrier[_TRACE_OPTIONS_KEY] = str(
83            span_context.trace_options.trace_options_byte)
84
85        return carrier
86