11package datadog .trace .core .baggage ;
22
3- import static java .util .Collections .emptyMap ;
4-
53import datadog .context .Context ;
64import datadog .context .propagation .CarrierSetter ;
75import datadog .context .propagation .CarrierVisitor ;
1917import java .util .HashMap ;
2018import java .util .Map ;
2119import java .util .function .BiConsumer ;
20+ import javax .annotation .Nullable ;
2221import javax .annotation .ParametersAreNonnullByDefault ;
2322import org .slf4j .Logger ;
2423import org .slf4j .LoggerFactory ;
@@ -142,8 +141,7 @@ public <C> Context extract(Context context, C carrier, CarrierVisitor<C> visitor
142141 private class BaggageExtractor implements BiConsumer <String , String > {
143142 private static final char KEY_VALUE_SEPARATOR = '=' ;
144143 private static final char PAIR_SEPARATOR = ',' ;
145- private Baggage extracted ;
146- private String w3cHeader ;
144+ @ Nullable private Baggage extracted ;
147145
148146 /** URL decode value */
149147 private String decode (final String value ) {
@@ -156,41 +154,42 @@ private String decode(final String value) {
156154 return decoded ;
157155 }
158156
159- private Map < String , String > parseBaggageHeaders (String input ) {
157+ private Baggage parseBaggageHeaders (String input ) {
160158 Map <String , String > baggage = new HashMap <>();
161159 int start = 0 ;
162- boolean truncatedCache = false ;
160+ String w3cHeader = input ;
163161 int pairSeparatorInd = input .indexOf (PAIR_SEPARATOR );
164162 pairSeparatorInd = pairSeparatorInd == -1 ? input .length () : pairSeparatorInd ;
165163 int kvSeparatorInd = input .indexOf (KEY_VALUE_SEPARATOR );
166164 while (kvSeparatorInd != -1 ) {
167165 int end = pairSeparatorInd ;
166+ boolean limitReached = baggage .size () >= maxItems || end > maxBytes ;
167+ if (limitReached ) {
168+ // if header was not invalidated already, and we go out of range:
169+ // - fully invalidate if it's after the first k/v pair,
170+ // - otherwise ignore from the current k/v separator
171+ w3cHeader = (w3cHeader == null || start == 0 ) ? null : w3cHeader .substring (0 , start - 1 );
172+ break ;
173+ }
168174 if (kvSeparatorInd > end ) {
169175 LOG .debug (
170176 "Dropping baggage headers due to key with no value {}" , input .substring (start , end ));
171177 BAGGAGE_METRICS .onBaggageMalformed ();
172- return emptyMap () ;
178+ return null ;
173179 }
174180 String key = decode (input .substring (start , kvSeparatorInd ).trim ());
175181 String value = decode (input .substring (kvSeparatorInd + 1 , end ).trim ());
176182 if (key .isEmpty () || value .isEmpty ()) {
177183 LOG .debug ("Dropping baggage headers due to empty k/v {}:{}" , key , value );
178184 BAGGAGE_METRICS .onBaggageMalformed ();
179- return emptyMap () ;
185+ return null ;
180186 }
181187 baggage .put (key , value );
182188
183189 // need to percent-encode non-ascii headers we pass down
184- if (UTF_ESCAPER .keyNeedsEncoding (key ) || UTF_ESCAPER .valNeedsEncoding (value )) {
185- truncatedCache = true ;
186- this .w3cHeader = null ;
187- } else if (!truncatedCache && (end > maxBytes || baggage .size () > maxItems )) {
188- if (start == 0 ) { // if we go out of range after first k/v pair, there is no cache
189- this .w3cHeader = null ;
190- } else {
191- this .w3cHeader = input .substring (0 , start - 1 ); // -1 to ignore the k/v separator
192- }
193- truncatedCache = true ;
190+ if (w3cHeader != null
191+ && (UTF_ESCAPER .keyNeedsEncoding (key ) || UTF_ESCAPER .valNeedsEncoding (value ))) {
192+ w3cHeader = null ;
194193 }
195194
196195 kvSeparatorInd = input .indexOf (KEY_VALUE_SEPARATOR , pairSeparatorInd + 1 );
@@ -199,20 +198,16 @@ private Map<String, String> parseBaggageHeaders(String input) {
199198 start = end + 1 ;
200199 }
201200
202- if (!truncatedCache ) {
203- this .w3cHeader = input ;
204- }
205-
206- return baggage ;
201+ return baggage .isEmpty () ? null : Baggage .create (baggage , w3cHeader );
207202 }
208203
209204 @ Override
210205 public void accept (String key , String value ) {
211206 // Only process tags that are relevant to baggage
212207 if (BAGGAGE_KEY .equalsIgnoreCase (key )) {
213- Map < String , String > baggage = parseBaggageHeaders (value );
214- if (! baggage . isEmpty () ) {
215- this .extracted = Baggage . create ( baggage , this . w3cHeader ) ;
208+ Baggage parsed = parseBaggageHeaders (value );
209+ if (parsed != null ) {
210+ this .extracted = parsed ;
216211 }
217212 }
218213 }
0 commit comments