Skip to content

Commit 8ec5dc1

Browse files
Add BaggageLogRecordProcessor
1 parent b2f04ab commit 8ec5dc1

File tree

5 files changed

+175
-52
lines changed

5 files changed

+175
-52
lines changed
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package io.opentelemetry.contrib.baggage.processor;
2+
3+
import io.opentelemetry.api.baggage.Baggage;
4+
import io.opentelemetry.api.common.AttributeKey;
5+
import io.opentelemetry.context.Context;
6+
import io.opentelemetry.sdk.logs.LogRecordProcessor;
7+
import io.opentelemetry.sdk.logs.ReadWriteLogRecord;
8+
9+
import java.util.function.Predicate;
10+
11+
/**
12+
* This log record processor copies attributes stored in {@link Baggage} into each newly created log record.
13+
*/
14+
public class BaggageLogRecordProcessor implements LogRecordProcessor {
15+
16+
/**
17+
* Creates a new {@link BaggageLogRecordProcessor} that copies all baggage entries into the newly
18+
* created log record.
19+
*/
20+
public static BaggageLogRecordProcessor allowAllBaggageKeys() {
21+
return new BaggageLogRecordProcessor(baggageKey -> true);
22+
}
23+
24+
private final Predicate<String> baggageKeyPredicate;
25+
26+
/**
27+
* Creates a new {@link BaggageLogRecordProcessor} that copies only baggage entries with keys that pass
28+
* the provided filter into the newly created log record.
29+
*/
30+
public BaggageLogRecordProcessor(Predicate<String> baggageKeyPredicate) {
31+
this.baggageKeyPredicate = baggageKeyPredicate;
32+
}
33+
34+
@Override
35+
public void onEmit(Context context, ReadWriteLogRecord logRecord) {
36+
Baggage.fromContext(context).forEach((s, baggageEntry) -> {
37+
if (baggageKeyPredicate.test(s)) {
38+
logRecord.setAttribute(AttributeKey.stringKey(s), baggageEntry.getValue());
39+
}
40+
});
41+
}
42+
}
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.opentelemetry.contrib.baggage.processor;
7+
8+
import io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizer;
9+
import io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizerProvider;
10+
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
11+
import io.opentelemetry.sdk.logs.SdkLoggerProviderBuilder;
12+
import io.opentelemetry.sdk.trace.SdkTracerProviderBuilder;
13+
import java.util.List;
14+
15+
public class BaggageProcessorCustomizer implements AutoConfigurationCustomizerProvider {
16+
@Override
17+
public void customize(AutoConfigurationCustomizer autoConfigurationCustomizer) {
18+
autoConfigurationCustomizer
19+
.addTracerProviderCustomizer(
20+
(sdkTracerProviderBuilder, config) -> {
21+
addSpanProcessor(sdkTracerProviderBuilder, config);
22+
return sdkTracerProviderBuilder;
23+
})
24+
.addLoggerProviderCustomizer(
25+
(sdkLoggerProviderBuilder, config) -> {
26+
addLogRecordProcessor(sdkLoggerProviderBuilder, config);
27+
return sdkLoggerProviderBuilder;
28+
});
29+
}
30+
31+
private static void addSpanProcessor(
32+
SdkTracerProviderBuilder sdkTracerProviderBuilder, ConfigProperties config) {
33+
List<String> keys =
34+
config.getList("otel.java.experimental.span-attributes.copy-from-baggage.include");
35+
36+
if (keys.isEmpty()) {
37+
return;
38+
}
39+
40+
sdkTracerProviderBuilder.addSpanProcessor(createBaggageSpanProcessor(keys));
41+
}
42+
43+
static BaggageSpanProcessor createBaggageSpanProcessor(List<String> keys) {
44+
if (keys.size() == 1 && keys.get(0).equals("*")) {
45+
return BaggageSpanProcessor.allowAllBaggageKeys();
46+
}
47+
return new BaggageSpanProcessor(keys::contains);
48+
}
49+
50+
private static void addLogRecordProcessor(
51+
SdkLoggerProviderBuilder sdkLoggerProviderBuilder, ConfigProperties config) {
52+
List<String> keys =
53+
config.getList("otel.java.experimental.log-attributes.copy-from-baggage.include");
54+
55+
if (keys.isEmpty()) {
56+
return;
57+
}
58+
59+
sdkLoggerProviderBuilder.addLogRecordProcessor(createBaggageLogRecordProcessor(keys));
60+
}
61+
static BaggageLogRecordProcessor createBaggageLogRecordProcessor(List<String> keys) {
62+
if (keys.size() == 1 && keys.get(0).equals("*")) {
63+
return BaggageLogRecordProcessor.allowAllBaggageKeys();
64+
}
65+
return new BaggageLogRecordProcessor(keys::contains);
66+
}
67+
}

baggage-processor/src/main/java/io/opentelemetry/contrib/baggage/processor/BaggageSpanProcessorCustomizer.java

Lines changed: 0 additions & 42 deletions
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
io.opentelemetry.contrib.baggage.processor.BaggageSpanProcessorCustomizer
1+
io.opentelemetry.contrib.baggage.processor.BaggageProcessorCustomizer
Lines changed: 65 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,19 @@
2020
import io.opentelemetry.sdk.autoconfigure.internal.ComponentLoader;
2121
import io.opentelemetry.sdk.autoconfigure.internal.SpiHelper;
2222
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
23+
import io.opentelemetry.sdk.autoconfigure.spi.logs.ConfigurableLogRecordExporterProvider;
2324
import io.opentelemetry.sdk.autoconfigure.spi.traces.ConfigurableSpanExporterProvider;
25+
import io.opentelemetry.sdk.logs.ReadWriteLogRecord;
26+
import io.opentelemetry.sdk.logs.export.LogRecordExporter;
2427
import io.opentelemetry.sdk.testing.assertj.SpanDataAssert;
2528
import io.opentelemetry.sdk.testing.assertj.TracesAssert;
29+
import io.opentelemetry.sdk.testing.exporter.InMemoryLogRecordExporter;
2630
import io.opentelemetry.sdk.testing.exporter.InMemorySpanExporter;
2731
import io.opentelemetry.sdk.trace.ReadWriteSpan;
2832
import io.opentelemetry.sdk.trace.export.SpanExporter;
2933
import java.time.Duration;
3034
import java.util.Collections;
35+
import java.util.HashMap;
3136
import java.util.List;
3237
import java.util.Map;
3338
import java.util.function.Consumer;
@@ -38,28 +43,35 @@
3843
import org.mockito.junit.jupiter.MockitoExtension;
3944

4045
@ExtendWith(MockitoExtension.class)
41-
class BaggageSpanProcessorCustomizerTest {
46+
class BaggageProcessorCustomizerTest {
4247

4348
private static final String MEMORY_EXPORTER = "memory";
4449

4550
@Test
4651
void test_customizer() {
4752
assertCustomizer(Collections.emptyMap(), span -> span.hasTotalAttributeCount(0));
53+
Map<String, String> properties = new HashMap<>();
54+
properties.put("otel.java.experimental.span-attributes.copy-from-baggage.include", "key");
55+
properties.put("otel.java.experimental.log-attributes.copy-from-baggage.include", "key");
56+
// TODO try use
57+
// AttributeAssertion attributeAssertion = OpenTelemetryAssertions.equalTo(AttributeKey.stringKey("key"), "value");
4858
assertCustomizer(
49-
Collections.singletonMap(
50-
"otel.java.experimental.span-attributes.copy-from-baggage.include", "key"),
59+
properties,
5160
span -> span.hasAttribute(AttributeKey.stringKey("key"), "value"));
5261
}
5362

5463
private static void assertCustomizer(
5564
Map<String, String> properties, Consumer<SpanDataAssert> spanDataAssertConsumer) {
5665

5766
InMemorySpanExporter spanExporter = InMemorySpanExporter.create();
67+
InMemoryLogRecordExporter logExporter = InMemoryLogRecordExporter.create();
5868

59-
OpenTelemetrySdk sdk = getOpenTelemetrySdk(properties, spanExporter);
69+
OpenTelemetrySdk sdk = getOpenTelemetrySdk(properties, spanExporter, logExporter);
6070
try (Scope ignore = Baggage.current().toBuilder().put("key", "value").build().makeCurrent()) {
6171
sdk.getTracer("test").spanBuilder("test").startSpan().end();
72+
sdk.getLogsBridge().get("test").logRecordBuilder().setBody ("test").emit();
6273
}
74+
// TODO verify log record attributes
6375
await()
6476
.atMost(Duration.ofSeconds(1))
6577
.untilAsserted(
@@ -70,9 +82,10 @@ private static void assertCustomizer(
7082
}
7183

7284
private static OpenTelemetrySdk getOpenTelemetrySdk(
73-
Map<String, String> properties, InMemorySpanExporter spanExporter) {
85+
Map<String, String> properties, InMemorySpanExporter spanExporter,
86+
InMemoryLogRecordExporter logRecordExporter) {
7487
SpiHelper spiHelper =
75-
SpiHelper.create(BaggageSpanProcessorCustomizerTest.class.getClassLoader());
88+
SpiHelper.create(BaggageProcessorCustomizerTest.class.getClassLoader());
7689

7790
AutoConfiguredOpenTelemetrySdkBuilder sdkBuilder =
7891
AutoConfiguredOpenTelemetrySdk.builder()
@@ -88,7 +101,7 @@ private static OpenTelemetrySdk getOpenTelemetrySdk(
88101
"otel.metrics.exporter",
89102
"none",
90103
"otel.logs.exporter",
91-
"none"))
104+
MEMORY_EXPORTER))
92105
.addPropertiesSupplier(() -> properties);
93106
AutoConfigureUtil.setComponentLoader(
94107
sdkBuilder,
@@ -105,6 +118,20 @@ public SpanExporter createExporter(ConfigProperties configProperties) {
105118
return spanExporter;
106119
}
107120

121+
@Override
122+
public String getName() {
123+
return MEMORY_EXPORTER;
124+
}
125+
});
126+
} else if (spiClass == ConfigurableLogRecordExporterProvider.class) {
127+
return Collections.singletonList(
128+
(T)
129+
new ConfigurableLogRecordExporterProvider() {
130+
@Override
131+
public LogRecordExporter createExporter(ConfigProperties configProperties) {
132+
return logRecordExporter;
133+
}
134+
108135
@Override
109136
public String getName() {
110137
return MEMORY_EXPORTER;
@@ -120,7 +147,7 @@ public String getName() {
120147
@Test
121148
public void test_baggageSpanProcessor_adds_attributes_to_spans(@Mock ReadWriteSpan span) {
122149
try (BaggageSpanProcessor processor =
123-
BaggageSpanProcessorCustomizer.createProcessor(Collections.singletonList("*"))) {
150+
BaggageProcessorCustomizer.createBaggageSpanProcessor(Collections.singletonList("*"))) {
124151
try (Scope ignore = Baggage.current().toBuilder().put("key", "value").build().makeCurrent()) {
125152
processor.onStart(Context.current(), span);
126153
verify(span).setAttribute("key", "value");
@@ -132,7 +159,7 @@ public void test_baggageSpanProcessor_adds_attributes_to_spans(@Mock ReadWriteSp
132159
public void test_baggageSpanProcessor_adds_attributes_to_spans_when_key_filter_matches(
133160
@Mock ReadWriteSpan span) {
134161
try (BaggageSpanProcessor processor =
135-
BaggageSpanProcessorCustomizer.createProcessor(Collections.singletonList("key"))) {
162+
BaggageProcessorCustomizer.createBaggageSpanProcessor(Collections.singletonList("key"))) {
136163
try (Scope ignore =
137164
Baggage.current().toBuilder()
138165
.put("key", "value")
@@ -145,4 +172,33 @@ public void test_baggageSpanProcessor_adds_attributes_to_spans_when_key_filter_m
145172
}
146173
}
147174
}
175+
176+
@Test
177+
public void test_baggageLogRecordProcessor_adds_attributes_to_logRecord(@Mock ReadWriteLogRecord logRecord) {
178+
try (BaggageLogRecordProcessor processor =
179+
BaggageProcessorCustomizer.createBaggageLogRecordProcessor(Collections.singletonList("*"))) {
180+
try (Scope ignore = Baggage.current().toBuilder().put("key", "value").build().makeCurrent()) {
181+
processor.onEmit(Context.current(), logRecord);
182+
verify(logRecord).setAttribute(AttributeKey.stringKey("key"), "value");
183+
}
184+
}
185+
}
186+
187+
@Test
188+
public void test_baggageLogRecordProcessor_adds_attributes_to_spans_when_key_filter_matches(
189+
@Mock ReadWriteLogRecord logRecord) {
190+
try (BaggageLogRecordProcessor processor =
191+
BaggageProcessorCustomizer.createBaggageLogRecordProcessor(Collections.singletonList("key"))) {
192+
try (Scope ignore =
193+
Baggage.current().toBuilder()
194+
.put("key", "value")
195+
.put("other", "value")
196+
.build()
197+
.makeCurrent()) {
198+
processor.onEmit(Context.current(), logRecord);
199+
verify(logRecord).setAttribute(AttributeKey.stringKey("key"), "value");
200+
verify(logRecord, Mockito.never()).setAttribute(AttributeKey.stringKey("other"), "value");
201+
}
202+
}
203+
}
148204
}

0 commit comments

Comments
 (0)