11#pragma once
22
3- #include < array>
4- #include < iostream>
5- #include < map>
6- #include < string>
73#include " detail/context.h"
8- #include " opentelemetry/common/key_value_iterable.h"
9- #include " opentelemetry/context/context.h"
10- #include " opentelemetry/nostd/shared_ptr.h"
11- #include " opentelemetry/nostd/span.h"
12- #include " opentelemetry/nostd/string_view.h"
13- #include " opentelemetry/nostd/variant.h"
4+ #include " detail/hex.h"
5+ #include " detail/string.h"
146#include " opentelemetry/trace/default_span.h"
157#include " opentelemetry/trace/propagation/text_map_propagator.h"
16- # include " opentelemetry/trace/span.h "
17- #include " opentelemetry/trace/span_context.h "
8+
9+ #include < array >
1810
1911OPENTELEMETRY_BEGIN_NAMESPACE
2012namespace trace
@@ -38,9 +30,8 @@ static const nostd::string_view kB3SampledHeader = "X-B3-Sampled";
3830 X-B3-TraceId X-B3-SpanId X-B3-ParentSpanId (ignored)
3931*/
4032
41- static const int kTraceIdHexStrLength = 32 ;
42- static const int kSpanIdHexStrLength = 16 ;
43- static const int kTraceFlagHexStrLength = 1 ;
33+ static const int kTraceIdHexStrLength = 32 ;
34+ static const int kSpanIdHexStrLength = 16 ;
4435
4536// The B3PropagatorExtractor class provides an interface that enables extracting context from
4637// headers of HTTP requests. HTTP frameworks and clients can integrate with B3Propagator by
@@ -63,21 +54,21 @@ class B3PropagatorExtractor : public TextMapPropagator<T>
6354 return context.SetValue (kSpanKey , sp);
6455 }
6556
66- static TraceId GenerateTraceIdFromString (nostd::string_view trace_id)
57+ static TraceId TraceIdFromHex (nostd::string_view trace_id)
6758 {
6859 uint8_t buf[kTraceIdHexStrLength / 2 ];
69- GenerateBuffFromHexStrPad0 (trace_id, sizeof ( buf), buf);
60+ detail::HexToBinary (trace_id, buf, sizeof ( buf) );
7061 return TraceId (buf);
7162 }
7263
73- static SpanId GenerateSpanIdFromString (nostd::string_view span_id)
64+ static SpanId SpanIdFromHex (nostd::string_view span_id)
7465 {
7566 uint8_t buf[kSpanIdHexStrLength / 2 ];
76- GenerateBuffFromHexStrPad0 (span_id, sizeof ( buf), buf);
67+ detail::HexToBinary (span_id, buf, sizeof ( buf) );
7768 return SpanId (buf);
7869 }
7970
80- static TraceFlags GenerateTraceFlagsFromString (nostd::string_view trace_flags)
71+ static TraceFlags TraceFlagsFromHex (nostd::string_view trace_flags)
8172 {
8273 if (trace_flags.length () != 1 || (trace_flags[0 ] != ' 1' && trace_flags[0 ] != ' d' ))
8374 { // check for invalid length of flags and treat 'd' as sampled
@@ -87,106 +78,48 @@ class B3PropagatorExtractor : public TextMapPropagator<T>
8778 }
8879
8980private:
90- // Converts hex numbers (string_view) into bytes stored in a buffer and pads buffer with 0.
91- static void GenerateBuffFromHexStrPad0 (nostd::string_view hexStr, int bufSize, uint8_t *buf)
92- { // we are doing this starting from "right" side for left-padding
93- nostd::string_view::size_type posInp = hexStr.length ();
94- int posOut = bufSize;
95- while (posOut--)
96- {
97- int val = 0 ;
98- if (posInp)
99- {
100- int hexDigit2 = HexToInt (hexStr[--posInp]); // low nibble
101- int hexDigit1 = 0 ;
102- if (posInp)
103- {
104- hexDigit1 = HexToInt (hexStr[--posInp]);
105- }
106- if (hexDigit1 < 0 || hexDigit2 < 0 )
107- { // malformed hex sequence. Fill entire buffer with zeroes.
108- for (int j = 0 ; j < bufSize; j++)
109- {
110- buf[j] = 0 ;
111- }
112- return ;
113- }
114- val = hexDigit1 * 16 + hexDigit2;
115- }
116- buf[posOut] = val;
117- }
118- }
119-
120- // Converts a single character to a corresponding integer (e.g. '1' to 1), return -1
121- // if the character is not a valid number in hex.
122- static int8_t HexToInt (char c)
123- {
124- if (c >= ' 0' && c <= ' 9' )
125- {
126- return (int8_t )(c - ' 0' );
127- }
128- else if (c >= ' a' && c <= ' f' )
129- {
130- return (int8_t )(c - ' a' + 10 );
131- }
132- else if (c >= ' A' && c <= ' F' )
133- {
134- return (int8_t )(c - ' A' + 10 );
135- }
136- else
137- {
138- return -1 ;
139- }
140- }
141-
14281 static SpanContext ExtractImpl (Getter getter, const T &carrier)
14382 {
144- // all these are hex values
145- nostd::string_view trace_id;
146- nostd::string_view span_id;
147- nostd::string_view trace_flags;
83+ nostd::string_view trace_id_hex;
84+ nostd::string_view span_id_hex;
85+ nostd::string_view trace_flags_hex;
14886
14987 // first let's try a single-header variant
15088 auto singleB3Header = getter (carrier, kB3CombinedHeader );
15189 if (!singleB3Header.empty ())
15290 {
153- // From: https://github.com/openzipkin/b3-propagation/blob/master/RATIONALE.md
154- // trace_id can be 16 or 32 chars
155- auto firstSep = singleB3Header.find (' -' );
156- trace_id = singleB3Header.substr (0 , firstSep);
157- if (firstSep != nostd::string_view::npos)
158- { // at least two fields are required
159- auto secondSep = singleB3Header.find (' -' , firstSep + 1 );
160- if (secondSep != nostd::string_view::npos)
161- { // more than two fields - check also trace_flags
162- span_id = singleB3Header.substr (firstSep + 1 , secondSep - firstSep - 1 );
163- if (secondSep + 1 < singleB3Header.size ())
164- {
165- trace_flags = singleB3Header.substr (secondSep + 1 , kTraceFlagHexStrLength );
166- }
167- }
168- else
169- {
170- span_id = singleB3Header.substr (firstSep + 1 );
171- }
91+ std::array<nostd::string_view, 3 > fields{};
92+ // https://github.com/openzipkin/b3-propagation/blob/master/RATIONALE.md
93+ if (detail::SplitString (singleB3Header, ' -' , fields.data (), 3 ) < 2 )
94+ {
95+ return SpanContext::GetInvalid ();
17296 }
97+
98+ trace_id_hex = fields[0 ];
99+ span_id_hex = fields[1 ];
100+ trace_flags_hex = fields[2 ];
173101 }
174102 else
175103 {
176- trace_id = getter (carrier, kB3TraceIdHeader );
177- span_id = getter (carrier, kB3SpanIdHeader );
178- trace_flags = getter (carrier, kB3SampledHeader );
104+ trace_id_hex = getter (carrier, kB3TraceIdHeader );
105+ span_id_hex = getter (carrier, kB3SpanIdHeader );
106+ trace_flags_hex = getter (carrier, kB3SampledHeader );
179107 }
180108
181- // now convert hex to objects
182- TraceId trace_id_obj = GenerateTraceIdFromString (trace_id);
183- SpanId span_id_obj = GenerateSpanIdFromString (span_id);
184- if (!trace_id_obj.IsValid () || !span_id_obj.IsValid ())
109+ if (!detail::IsValidHex (trace_id_hex) || !detail::IsValidHex (span_id_hex))
185110 {
186- return SpanContext ( false , false );
111+ return SpanContext::GetInvalid ( );
187112 }
188- TraceFlags trace_flags_obj = GenerateTraceFlagsFromString (trace_flags);
189- return SpanContext (trace_id_obj, span_id_obj, trace_flags_obj, true );
113+
114+ TraceId trace_id = TraceIdFromHex (trace_id_hex);
115+ SpanId span_id = SpanIdFromHex (span_id_hex);
116+
117+ if (!trace_id.IsValid () || !span_id.IsValid ())
118+ {
119+ return SpanContext::GetInvalid ();
120+ }
121+
122+ return SpanContext (trace_id, span_id, TraceFlagsFromHex (trace_flags_hex), true );
190123 }
191124};
192125
@@ -208,26 +141,18 @@ class B3Propagator : public B3PropagatorExtractor<T>
208141 {
209142 return ;
210143 }
211- char trace_id[kTraceIdHexStrLength ];
212- TraceId (span_context.trace_id ()).ToLowerBase16 (trace_id);
213- char span_id[kSpanIdHexStrLength ];
214- SpanId (span_context.span_id ()).ToLowerBase16 (span_id);
215- char trace_flags[2 ];
216- TraceFlags (span_context.trace_flags ()).ToLowerBase16 (trace_flags);
217- // Note: This is only temporary replacement for appendable string
218- std::string hex_string = " " ;
219- for (int i = 0 ; i < 32 ; i++)
220- {
221- hex_string.push_back (trace_id[i]);
222- }
223- hex_string.push_back (' -' );
224- for (int i = 0 ; i < 16 ; i++)
225- {
226- hex_string.push_back (span_id[i]);
227- }
228- hex_string.push_back (' -' );
229- hex_string.push_back (trace_flags[1 ]);
230- setter (carrier, kB3CombinedHeader , hex_string);
144+
145+ char trace_identity[kTraceIdHexStrLength + kSpanIdHexStrLength + 3 ];
146+ static_assert (sizeof (trace_identity) == 51 , " b3 trace identity buffer size mismatch" );
147+ span_context.trace_id ().ToLowerBase16 ({&trace_identity[0 ], kTraceIdHexStrLength });
148+ trace_identity[kTraceIdHexStrLength ] = ' -' ;
149+ span_context.span_id ().ToLowerBase16 (
150+ {&trace_identity[kTraceIdHexStrLength + 1 ], kSpanIdHexStrLength });
151+ trace_identity[kTraceIdHexStrLength + kSpanIdHexStrLength + 1 ] = ' -' ;
152+ trace_identity[kTraceIdHexStrLength + kSpanIdHexStrLength + 2 ] =
153+ span_context.trace_flags ().IsSampled () ? ' 1' : ' 0' ;
154+
155+ setter (carrier, kB3CombinedHeader , nostd::string_view (trace_identity, sizeof (trace_identity)));
231156 }
232157};
233158
0 commit comments