Skip to content

Commit 4dae677

Browse files
committed
Allow context implementation to skip interim copy when adding two entries at the same time (such as adding span plus baggage)
1 parent 19e55b6 commit 4dae677

File tree

3 files changed

+59
-2
lines changed

3 files changed

+59
-2
lines changed

components/context/src/main/java/datadog/context/Context.java

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ static Context detachFrom(Object carrier) {
114114
/**
115115
* Creates a copy of this context with the given key-value set.
116116
*
117-
* <p>Existing value with the given key will be replaced, and mapping to a {@code null} value will
117+
* <p>Existing value with the given key will be replaced. Mapping to a {@code null} value will
118118
* remove the key-value from the context copy.
119119
*
120120
* @param <T> the type of the value.
@@ -124,6 +124,28 @@ static Context detachFrom(Object carrier) {
124124
*/
125125
<T> Context with(ContextKey<T> key, @Nullable T value);
126126

127+
/**
128+
* Creates a copy of this context with the given pair of key-values.
129+
*
130+
* <p>Existing values with the given keys will be replaced. Mapping to a {@code null} value will
131+
* remove the key-value from the context copy.
132+
*
133+
* @param <T> the type of the first value.
134+
* @param <U> the type of the second value.
135+
* @param firstKey the first key to store the first value.
136+
* @param firstValue the first value to store.
137+
* @param secondKey the second key to store the second value.
138+
* @param secondValue the second value to store.
139+
* @return a new context with the pair of key-values set.
140+
*/
141+
default <T, U> Context with(
142+
ContextKey<T> firstKey,
143+
@Nullable T firstValue,
144+
ContextKey<U> secondKey,
145+
@Nullable U secondValue) {
146+
return with(firstKey, firstValue).with(secondKey, secondValue);
147+
}
148+
127149
/**
128150
* Creates a copy of this context with the implicit key is mapped to the value.
129151
*

components/context/src/test/java/datadog/context/ContextTest.java

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,41 @@ void testWith(Context context) {
6363
assertDoesNotThrow(() -> context.with(null), "Null implicitly keyed value not throw exception");
6464
}
6565

66+
@ParameterizedTest
67+
@MethodSource("contextImplementations")
68+
void testWithPair(Context context) {
69+
// Test retrieving value
70+
String stringValue = "value";
71+
Context context1 = context.with(BOOLEAN_KEY, false, STRING_KEY, stringValue);
72+
assertEquals(stringValue, context1.get(STRING_KEY));
73+
assertEquals(false, context1.get(BOOLEAN_KEY));
74+
// Test overriding value
75+
String stringValue2 = "value2";
76+
Context context2 = context1.with(STRING_KEY, stringValue2, BOOLEAN_KEY, true);
77+
assertEquals(stringValue2, context2.get(STRING_KEY));
78+
assertEquals(true, context2.get(BOOLEAN_KEY));
79+
// Test clearing value
80+
Context context3 = context2.with(BOOLEAN_KEY, null, STRING_KEY, null);
81+
assertNull(context3.get(STRING_KEY));
82+
assertNull(context3.get(BOOLEAN_KEY));
83+
// Test null key handling
84+
assertThrows(
85+
NullPointerException.class,
86+
() -> context.with(null, "test", STRING_KEY, "test"),
87+
"Context forbids null keys");
88+
assertThrows(
89+
NullPointerException.class,
90+
() -> context.with(STRING_KEY, "test", null, "test"),
91+
"Context forbids null keys");
92+
// Test null value handling
93+
assertDoesNotThrow(
94+
() -> context.with(BOOLEAN_KEY, null, STRING_KEY, "test"),
95+
"Null value should not throw exception");
96+
assertDoesNotThrow(
97+
() -> context.with(STRING_KEY, "test", BOOLEAN_KEY, null),
98+
"Null value should not throw exception");
99+
}
100+
66101
@ParameterizedTest
67102
@MethodSource("contextImplementations")
68103
void testGet(Context original) {

internal-api/src/main/java/datadog/trace/bootstrap/instrumentation/api/AgentSpan.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,6 @@ default <T> T get(ContextKey<T> key) {
167167

168168
@Override
169169
default <T> Context with(ContextKey<T> key, @Nullable T value) {
170-
return Context.root().with(SPAN_KEY, this).with(key, value);
170+
return Context.root().with(SPAN_KEY, this, key, value);
171171
}
172172
}

0 commit comments

Comments
 (0)