Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/opentelemetry/trace/propagation/tracecontext.py: 31%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

52 statements  

1# Copyright The OpenTelemetry 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# 

15import re 

16import typing 

17 

18from opentelemetry import trace 

19from opentelemetry.context.context import Context 

20from opentelemetry.propagators import textmap 

21from opentelemetry.trace import format_span_id, format_trace_id 

22from opentelemetry.trace.span import TraceState 

23 

24 

25class TraceContextTextMapPropagator(textmap.TextMapPropagator): 

26 """Extracts and injects using w3c TraceContext's headers.""" 

27 

28 _TRACEPARENT_HEADER_NAME = "traceparent" 

29 _TRACESTATE_HEADER_NAME = "tracestate" 

30 _TRACEPARENT_HEADER_FORMAT = ( 

31 "^[ \t]*([0-9a-f]{2})-([0-9a-f]{32})-([0-9a-f]{16})-([0-9a-f]{2})" 

32 + "(-.*)?[ \t]*$" 

33 ) 

34 _TRACEPARENT_HEADER_FORMAT_RE = re.compile(_TRACEPARENT_HEADER_FORMAT) 

35 

36 def extract( 

37 self, 

38 carrier: textmap.CarrierT, 

39 context: typing.Optional[Context] = None, 

40 getter: textmap.Getter[textmap.CarrierT] = textmap.default_getter, 

41 ) -> Context: 

42 """Extracts SpanContext from the carrier. 

43 

44 See `opentelemetry.propagators.textmap.TextMapPropagator.extract` 

45 """ 

46 if context is None: 

47 context = Context() 

48 

49 header = getter.get(carrier, self._TRACEPARENT_HEADER_NAME) 

50 

51 if not header: 

52 return context 

53 

54 match = re.search(self._TRACEPARENT_HEADER_FORMAT_RE, header[0]) 

55 if not match: 

56 return context 

57 

58 version: str = match.group(1) 

59 trace_id: str = match.group(2) 

60 span_id: str = match.group(3) 

61 trace_flags: str = match.group(4) 

62 

63 if trace_id == "0" * 32 or span_id == "0" * 16: 

64 return context 

65 

66 if version == "00": 

67 if match.group(5): # type: ignore 

68 return context 

69 if version == "ff": 

70 return context 

71 

72 tracestate_headers = getter.get(carrier, self._TRACESTATE_HEADER_NAME) 

73 if tracestate_headers is None: 

74 tracestate = None 

75 else: 

76 tracestate = TraceState.from_header(tracestate_headers) 

77 

78 span_context = trace.SpanContext( 

79 trace_id=int(trace_id, 16), 

80 span_id=int(span_id, 16), 

81 is_remote=True, 

82 trace_flags=trace.TraceFlags(int(trace_flags, 16)), 

83 trace_state=tracestate, 

84 ) 

85 return trace.set_span_in_context( 

86 trace.NonRecordingSpan(span_context), context 

87 ) 

88 

89 def inject( 

90 self, 

91 carrier: textmap.CarrierT, 

92 context: typing.Optional[Context] = None, 

93 setter: textmap.Setter[textmap.CarrierT] = textmap.default_setter, 

94 ) -> None: 

95 """Injects SpanContext into the carrier. 

96 

97 See `opentelemetry.propagators.textmap.TextMapPropagator.inject` 

98 """ 

99 span = trace.get_current_span(context) 

100 span_context = span.get_span_context() 

101 if span_context == trace.INVALID_SPAN_CONTEXT: 

102 return 

103 traceparent_string = f"00-{format_trace_id(span_context.trace_id)}-{format_span_id(span_context.span_id)}-{span_context.trace_flags:02x}" 

104 setter.set(carrier, self._TRACEPARENT_HEADER_NAME, traceparent_string) 

105 if span_context.trace_state: 

106 tracestate_string = span_context.trace_state.to_header() 

107 setter.set( 

108 carrier, self._TRACESTATE_HEADER_NAME, tracestate_string 

109 ) 

110 

111 @property 

112 def fields(self) -> typing.Set[str]: 

113 """Returns a set with the fields set in `inject`. 

114 

115 See 

116 `opentelemetry.propagators.textmap.TextMapPropagator.fields` 

117 """ 

118 return {self._TRACEPARENT_HEADER_NAME, self._TRACESTATE_HEADER_NAME}