4
4
5
5
import io .sentry .protocol .SentryId ;
6
6
import io .sentry .protocol .TransactionNameSource ;
7
+ import io .sentry .util .AutoClosableReentrantLock ;
7
8
import io .sentry .util .SampleRateUtils ;
8
9
import io .sentry .util .StringUtils ;
9
10
import java .io .UnsupportedEncodingException ;
13
14
import java .text .DecimalFormatSymbols ;
14
15
import java .util .ArrayList ;
15
16
import java .util .Arrays ;
16
- import java .util .HashMap ;
17
+ import java .util .Collections ;
17
18
import java .util .List ;
18
19
import java .util .Locale ;
19
20
import java .util .Map ;
@@ -44,13 +45,15 @@ protected DecimalFormat initialValue() {
44
45
private static final DecimalFormatterThreadLocal decimalFormatter =
45
46
new DecimalFormatterThreadLocal ();
46
47
47
- final @ NotNull Map <String , String > keyValues ;
48
- @ Nullable Double sampleRate ;
49
- @ Nullable Double sampleRand ;
48
+ private final @ NotNull ConcurrentHashMap <String , String > keyValues ;
49
+ private final @ NotNull AutoClosableReentrantLock keyValuesLock = new AutoClosableReentrantLock ();
50
50
51
- final @ Nullable String thirdPartyHeader ;
51
+ private @ Nullable Double sampleRate ;
52
+ private @ Nullable Double sampleRand ;
53
+
54
+ private final @ Nullable String thirdPartyHeader ;
52
55
private boolean mutable ;
53
- private boolean shouldFreeze ;
56
+ private final boolean shouldFreeze ;
54
57
final @ NotNull ILogger logger ;
55
58
56
59
@ NotNull
@@ -99,7 +102,9 @@ public static Baggage fromHeader(
99
102
final @ Nullable String headerValue ,
100
103
final boolean includeThirdPartyValues ,
101
104
final @ NotNull ILogger logger ) {
102
- final @ NotNull Map <String , String > keyValues = new HashMap <>();
105
+
106
+ final @ NotNull ConcurrentHashMap <String , String > keyValues = new ConcurrentHashMap <>();
107
+
103
108
final @ NotNull List <String > thirdPartyKeyValueStrings = new ArrayList <>();
104
109
boolean shouldFreeze = false ;
105
110
@@ -196,7 +201,7 @@ public static Baggage fromEvent(
196
201
197
202
@ ApiStatus .Internal
198
203
public Baggage (final @ NotNull ILogger logger ) {
199
- this (new HashMap <>(), null , null , null , true , false , logger );
204
+ this (new ConcurrentHashMap <>(), null , null , null , true , false , logger );
200
205
}
201
206
202
207
@ ApiStatus .Internal
@@ -213,12 +218,12 @@ public Baggage(final @NotNull Baggage baggage) {
213
218
214
219
@ ApiStatus .Internal
215
220
public Baggage (
216
- final @ NotNull Map <String , String > keyValues ,
221
+ final @ NotNull ConcurrentHashMap <String , String > keyValues ,
217
222
final @ Nullable Double sampleRate ,
218
223
final @ Nullable Double sampleRand ,
219
224
final @ Nullable String thirdPartyHeader ,
220
- boolean isMutable ,
221
- boolean shouldFreeze ,
225
+ final boolean isMutable ,
226
+ final boolean shouldFreeze ,
222
227
final @ NotNull ILogger logger ) {
223
228
this .keyValues = keyValues ;
224
229
this .sampleRate = sampleRate ;
@@ -260,7 +265,10 @@ public String getThirdPartyHeader() {
260
265
separator = "," ;
261
266
}
262
267
263
- final Set <String > keys = new TreeSet <>(keyValues .keySet ());
268
+ final Set <String > keys ;
269
+ try (final @ NotNull ISentryLifecycleToken ignored = keyValuesLock .acquire ()) {
270
+ keys = new TreeSet <>(Collections .list (keyValues .keys ()));
271
+ }
264
272
keys .add (DSCKeys .SAMPLE_RATE );
265
273
keys .add (DSCKeys .SAMPLE_RAND );
266
274
@@ -440,38 +448,38 @@ public void setReplayId(final @Nullable String replayId) {
440
448
set (DSCKeys .REPLAY_ID , replayId );
441
449
}
442
450
443
- @ ApiStatus .Internal
444
- public void set (final @ NotNull String key , final @ Nullable String value ) {
445
- set (key , value , false );
446
- }
447
-
448
451
/**
449
- * Sets / updates a value
452
+ * Sets / updates a value, but only if the baggage is still mutable.
450
453
*
451
454
* @param key key
452
455
* @param value value to set
453
- * @param force ignores mutability of this baggage and sets the value anyways
454
456
*/
455
- private void set (final @ NotNull String key , final @ Nullable String value , final boolean force ) {
456
- if (mutable || force ) {
457
- this .keyValues .put (key , value );
457
+ @ ApiStatus .Internal
458
+ public void set (final @ NotNull String key , final @ Nullable String value ) {
459
+ if (mutable ) {
460
+ if (value == null ) {
461
+ keyValues .remove (key );
462
+ } else {
463
+ keyValues .put (key , value );
464
+ }
458
465
}
459
466
}
460
467
461
468
@ ApiStatus .Internal
462
469
public @ NotNull Map <String , Object > getUnknown () {
463
470
final @ NotNull Map <String , Object > unknown = new ConcurrentHashMap <>();
464
- for (Map .Entry <String , String > keyValue : this .keyValues .entrySet ()) {
465
- final @ NotNull String key = keyValue .getKey ();
466
- final @ Nullable String value = keyValue .getValue ();
467
- if (!DSCKeys .ALL .contains (key )) {
468
- if (value != null ) {
469
- final @ NotNull String unknownKey = key .replaceFirst (SENTRY_BAGGAGE_PREFIX , "" );
470
- unknown .put (unknownKey , value );
471
+ try (final @ NotNull ISentryLifecycleToken ignored = keyValuesLock .acquire ()) {
472
+ for (final Map .Entry <String , String > keyValue : keyValues .entrySet ()) {
473
+ final @ NotNull String key = keyValue .getKey ();
474
+ final @ Nullable String value = keyValue .getValue ();
475
+ if (!DSCKeys .ALL .contains (key )) {
476
+ if (value != null ) {
477
+ final @ NotNull String unknownKey = key .replaceFirst (SENTRY_BAGGAGE_PREFIX , "" );
478
+ unknown .put (unknownKey , value );
479
+ }
471
480
}
472
481
}
473
482
}
474
-
475
483
return unknown ;
476
484
}
477
485
0 commit comments