Skip to content
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 17 additions & 19 deletions baggage-processor/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@ Do not put sensitive information in Baggage.
If you are using the OpenTelemetry SDK auto-configuration, you can add the span and log baggage
processors through configuration.

| Property | Description |
|--------------------------------------------------------------------|---------------------------------------------------------------------------------------------------|
| `otel.java.experimental.span-attributes.copy-from-baggage.include` | Add baggage entries as span attributes, e.g. `key1,key2` or `*` to add all baggage items as keys. |
| `otel.java.experimental.log-attributes.copy-from-baggage.include` | Add baggage entries as log attributes, e.g. `key1,key2` or `*` to add all baggage items as keys. |
| Property | Description |
|--------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `otel.java.experimental.span-attributes.copy-from-baggage.include` | Add baggage entries as span attributes, e.g. `key1,key*`, [wildcard pattern matching](https://github.com/open-telemetry/opentelemetry-configuration/blob/main/CONTRIBUTING.md#properties-requiring-pattern-matching) is supported. |
| `otel.java.experimental.log-attributes.copy-from-baggage.include` | Add baggage entries as log attributes, e.g. `key1,key*`, [wildcard pattern matching](https://github.com/open-telemetry/opentelemetry-configuration/blob/main/CONTRIBUTING.md#properties-requiring-pattern-matching) is supported. |
Comment thread
SylvainJuge marked this conversation as resolved.
Outdated

### Usage with declarative configuration

Expand Down Expand Up @@ -55,40 +55,38 @@ This will configure the respective processor to include baggage keys listed in `
exclude those in `excluded` as explained in
[Properties requiring pattern matching](https://github.com/open-telemetry/opentelemetry-configuration/blob/main/CONTRIBUTING.md#properties-requiring-pattern-matching).

When both `included` and `excluded` are empty or not set, all the baggage entries will be copied.
When only `included` is set, only the baggage entries matching the patterns in `included` will be copied (opt-in).
When only `excluded` is set, all baggage entries except those matching the patterns in `excluded` will be copied (opt-out).

### Usage through programmatic activation

Add the span and log processor when configuring the tracer and logger providers.

To configure the span and log processors to copy all baggage entries during configuration:

```java
import io.opentelemetry.contrib.baggage.processor;
import io.opentelemetry.contrib.baggage.processor.BaggageSpanProcessor;
import io.opentelemetry.contrib.baggage.processor.BaggageLogProcessor;

// ...

TracerProvider tracerProvider = SdkTracerProvider.builder()
.addSpanProcessor(BaggageSpanProcessor.allowAllBaggageKeys())
.addSpanProcessor(new BaggageSpanProcessor(Collections.singletonList("*"), null))
.build();

LoggerProvider loggerProvider = SdkLoggerProvider.builder()
.addLogRecordProcessor(BaggageLogRecordProcessor.allowAllBaggageKeys())
.addLogProcessor(new BaggageLogProcessor(Collections.singletonList("*"), null))
.build();
Comment thread
SylvainJuge marked this conversation as resolved.
```

Alternatively, you can provide a custom baggage key predicate to select which baggage keys you want to copy.

For example, to only copy baggage entries that start with `my-key`:

```java
new BaggageSpanProcessor(baggageKey -> baggageKey.startsWith("my-key"));
new BaggageLogRecordProcessor(baggageKey -> baggageKey.startsWith("my-key"));
```
Alternatively, you can provide a custom baggage key wildcard to select which baggage keys you want to copy.

For example, to only copy baggage entries that match the regex `^key.+`:
For example, to only copy baggage entries that start with `my-key` and ignore keys that end with `*-ignored`

```java
Pattern pattern = Pattern.compile("^key.+");
new BaggageSpanProcessor(baggageKey -> pattern.matcher(baggageKey).matches());
new BaggageLogRecordProcessor(baggageKey -> pattern.matcher(baggageKey).matches());
new BaggageSpanProcessor(Collections.singletonList("my-key*"), Collections.singletonList("*-ignored"));
new BaggageLogRecordProcessor(Collections.singletonList("my-key*"), Collections.singletonList("*-ignored"));
```

## Component owners
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
import com.google.auto.service.AutoService;
import io.opentelemetry.api.incubator.config.DeclarativeConfigProperties;
import io.opentelemetry.sdk.autoconfigure.spi.internal.ComponentProvider;
import io.opentelemetry.sdk.common.internal.IncludeExcludePredicate;
import io.opentelemetry.sdk.logs.LogRecordProcessor;

@AutoService(ComponentProvider.class)
Expand All @@ -21,9 +20,8 @@ public String getName() {
@Override
public LogRecordProcessor create(DeclarativeConfigProperties config) {
return new BaggageLogRecordProcessor(
IncludeExcludePredicate.createPatternMatching(
config.getScalarList("included", String.class),
config.getScalarList("excluded", String.class)));
config.getScalarList("included", String.class),
config.getScalarList("excluded", String.class));
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,12 @@
import io.opentelemetry.api.baggage.Baggage;
import io.opentelemetry.api.common.AttributeKey;
import io.opentelemetry.context.Context;
import io.opentelemetry.sdk.common.internal.IncludeExcludePredicate;
import io.opentelemetry.sdk.logs.LogRecordProcessor;
import io.opentelemetry.sdk.logs.ReadWriteLogRecord;
import java.util.Collection;
import java.util.function.Predicate;
import javax.annotation.Nullable;

/**
* This log record processor copies attributes stored in {@link Baggage} into each newly created log
Expand All @@ -21,19 +24,37 @@ public final class BaggageLogRecordProcessor implements LogRecordProcessor {
private final Predicate<String> baggageKeyPredicate;

/**
* Creates a new {@link BaggageLogRecordProcessor} that copies only baggage entries with keys that
* pass the provided filter into the newly created log record.
* @deprecated Use {@link #BaggageLogRecordProcessor(Collection, Collection)} instead.
Comment thread
SylvainJuge marked this conversation as resolved.
Outdated
*/
@Deprecated
public BaggageLogRecordProcessor(Predicate<String> baggageKeyPredicate) {
this.baggageKeyPredicate = baggageKeyPredicate;
}

/**
* Creates a new {@link BaggageLogRecordProcessor} that copies baggage entries with keys that pass
* the provided include/exclude filtering into the newly created log record, when both arguments
* are null or empty all baggage are included.
*
* @param included list of included attribute patterns to include
* @param excluded list of excluded attribute patterns to exclude
Comment thread
SylvainJuge marked this conversation as resolved.
Outdated
*/
public BaggageLogRecordProcessor(
@Nullable Collection<String> included, @Nullable Collection<String> excluded) {
this.baggageKeyPredicate = IncludeExcludePredicate.createPatternMatching(included, excluded);
}
Comment thread
SylvainJuge marked this conversation as resolved.

/**
* Creates a new {@link BaggageLogRecordProcessor} that copies all baggage entries into the newly
* created log record.
*
* @return baggage log processor including all attributes
* @deprecated use {@code new BaggageLogRecordProcessor(Collections.singletonList("*"), null)}
* instead
*/
@Deprecated
public static BaggageLogRecordProcessor allowAllBaggageKeys() {
return new BaggageLogRecordProcessor(baggageKey -> true);
return new BaggageLogRecordProcessor(excluded -> true);
Comment thread
SylvainJuge marked this conversation as resolved.
Outdated
}
Comment thread
SylvainJuge marked this conversation as resolved.

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,7 @@ private static void addSpanProcessor(
}

// need to add before the batch span processor
sdkTracerProviderBuilder.addSpanProcessorFirst(createBaggageSpanProcessor(keys));
}

static BaggageSpanProcessor createBaggageSpanProcessor(List<String> keys) {
if (keys.size() == 1 && keys.get(0).equals("*")) {
return BaggageSpanProcessor.allowAllBaggageKeys();
}
Comment on lines -47 to -49
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[for reviewer] this optimization is not really necessary as an equivalent is implemented in GlobUtils, we could however do this in IncludeExcludePredicate as a follow-up improvement.

return new BaggageSpanProcessor(keys::contains);
sdkTracerProviderBuilder.addSpanProcessorFirst(new BaggageSpanProcessor(keys, null));
}

private static void addLogRecordProcessor(
Expand All @@ -60,13 +53,6 @@ private static void addLogRecordProcessor(
}

// need to add before the batch log processor
sdkLoggerProviderBuilder.addLogRecordProcessorFirst(createBaggageLogRecordProcessor(keys));
}

static BaggageLogRecordProcessor createBaggageLogRecordProcessor(List<String> keys) {
if (keys.size() == 1 && keys.get(0).equals("*")) {
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[for reviewer] this optimization is not really necessary as an equivalent is implemented in GlobUtils, we could however do this in IncludeExcludePredicate as a follow-up improvement.

return BaggageLogRecordProcessor.allowAllBaggageKeys();
}
return new BaggageLogRecordProcessor(keys::contains);
sdkLoggerProviderBuilder.addLogRecordProcessorFirst(new BaggageLogRecordProcessor(keys, null));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
import com.google.auto.service.AutoService;
import io.opentelemetry.api.incubator.config.DeclarativeConfigProperties;
import io.opentelemetry.sdk.autoconfigure.spi.internal.ComponentProvider;
import io.opentelemetry.sdk.common.internal.IncludeExcludePredicate;
import io.opentelemetry.sdk.trace.SpanProcessor;

@AutoService(ComponentProvider.class)
Expand All @@ -21,9 +20,8 @@ public String getName() {
@Override
public SpanProcessor create(DeclarativeConfigProperties config) {
return new BaggageSpanProcessor(
IncludeExcludePredicate.createPatternMatching(
config.getScalarList("included", String.class),
config.getScalarList("excluded", String.class)));
config.getScalarList("included", String.class),
config.getScalarList("excluded", String.class));
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,13 @@

import io.opentelemetry.api.baggage.Baggage;
import io.opentelemetry.context.Context;
import io.opentelemetry.sdk.common.internal.IncludeExcludePredicate;
import io.opentelemetry.sdk.trace.ReadWriteSpan;
import io.opentelemetry.sdk.trace.ReadableSpan;
import io.opentelemetry.sdk.trace.SpanProcessor;
import java.util.Collection;
import java.util.function.Predicate;
import javax.annotation.Nullable;

/**
* This span processor copies attributes stored in {@link Baggage} into each newly created {@link
Expand All @@ -20,17 +23,35 @@ public final class BaggageSpanProcessor implements SpanProcessor {
private final Predicate<String> baggageKeyPredicate;

/**
* Creates a new {@link BaggageSpanProcessor} that copies only baggage entries with keys that pass
* the provided filter into the newly created {@link io.opentelemetry.api.trace.Span}.
* @deprecated Use {@link #BaggageSpanProcessor(Collection, Collection)} instead.
*/
@Deprecated
public BaggageSpanProcessor(Predicate<String> baggageKeyPredicate) {
this.baggageKeyPredicate = baggageKeyPredicate;
}

/**
* Creates a new {@link BaggageSpanProcessor} that copies baggage entries with keys that pass the
* provided include/exclude filtering into the newly created {@link
* io.opentelemetry.api.trace.Span}, when both arguments are null or empty all baggage are
* included.
*
* @param included list of included attribute patterns to include
* @param excluded list of excluded attribute patterns to exclude
Comment thread
SylvainJuge marked this conversation as resolved.
Outdated
*/
public BaggageSpanProcessor(
@Nullable Collection<String> included, @Nullable Collection<String> excluded) {
this.baggageKeyPredicate = IncludeExcludePredicate.createPatternMatching(included, excluded);
}

Comment thread
SylvainJuge marked this conversation as resolved.
/**
* Creates a new {@link BaggageSpanProcessor} that copies all baggage entries into the newly
* created {@link io.opentelemetry.api.trace.Span}.
* created span.
*
* @return baggage span processor including all attributes
* @deprecated use {@code new BaggageSpanProcessor(Collections.singletonList("*"), null)} instead
*/
@Deprecated
public static BaggageSpanProcessor allowAllBaggageKeys() {
return new BaggageSpanProcessor(baggageKey -> true);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
package io.opentelemetry.contrib.baggage.processor;

import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat;
import static java.util.Collections.singletonList;
import static org.awaitility.Awaitility.await;
import static org.mockito.Mockito.verify;

Expand Down Expand Up @@ -122,7 +123,7 @@ private static OpenTelemetrySdk getOpenTelemetrySdk(
@Override
public <T> List<T> load(Class<T> spiClass) {
if (spiClass.equals(ConfigurableSpanExporterProvider.class)) {
return Collections.singletonList(
return singletonList(
spiClass.cast(
new ConfigurableSpanExporterProvider() {
@Override
Expand All @@ -137,7 +138,7 @@ public String getName() {
}
}));
} else if (spiClass.equals(ConfigurableLogRecordExporterProvider.class)) {
return Collections.singletonList(
return singletonList(
spiClass.cast(
new ConfigurableLogRecordExporterProvider() {
@Override
Expand All @@ -160,8 +161,7 @@ public String getName() {

@Test
void test_baggageSpanProcessor_adds_attributes_to_spans(@Mock ReadWriteSpan span) {
try (BaggageSpanProcessor processor =
BaggageProcessorCustomizer.createBaggageSpanProcessor(Collections.singletonList("*"))) {
try (BaggageSpanProcessor processor = new BaggageSpanProcessor(singletonList("*"), null)) {
try (Scope ignore = Baggage.current().toBuilder().put("key", "value").build().makeCurrent()) {
processor.onStart(Context.current(), span);
verify(span).setAttribute("key", "value");
Expand All @@ -172,8 +172,7 @@ void test_baggageSpanProcessor_adds_attributes_to_spans(@Mock ReadWriteSpan span
@Test
void test_baggageSpanProcessor_adds_attributes_to_spans_when_key_filter_matches(
@Mock ReadWriteSpan span) {
try (BaggageSpanProcessor processor =
BaggageProcessorCustomizer.createBaggageSpanProcessor(Collections.singletonList("key"))) {
try (BaggageSpanProcessor processor = new BaggageSpanProcessor(singletonList("key"), null)) {
try (Scope ignore =
Baggage.current().toBuilder()
.put("key", "value")
Expand All @@ -191,8 +190,7 @@ void test_baggageSpanProcessor_adds_attributes_to_spans_when_key_filter_matches(
void test_baggageLogRecordProcessor_adds_attributes_to_logRecord(
@Mock ReadWriteLogRecord logRecord) {
try (BaggageLogRecordProcessor processor =
BaggageProcessorCustomizer.createBaggageLogRecordProcessor(
Collections.singletonList("*"))) {
new BaggageLogRecordProcessor(singletonList("*"), null)) {
try (Scope ignore = Baggage.current().toBuilder().put("key", "value").build().makeCurrent()) {
processor.onEmit(Context.current(), logRecord);
verify(logRecord).setAttribute(AttributeKey.stringKey("key"), "value");
Expand All @@ -204,8 +202,7 @@ void test_baggageLogRecordProcessor_adds_attributes_to_logRecord(
void test_baggageLogRecordProcessor_adds_attributes_to_spans_when_key_filter_matches(
@Mock ReadWriteLogRecord logRecord) {
try (BaggageLogRecordProcessor processor =
BaggageProcessorCustomizer.createBaggageLogRecordProcessor(
Collections.singletonList("key"))) {
new BaggageLogRecordProcessor(singletonList("k*"), null)) {
try (Scope ignore =
Baggage.current().toBuilder()
.put("key", "value")
Expand All @@ -218,4 +215,23 @@ void test_baggageLogRecordProcessor_adds_attributes_to_spans_when_key_filter_mat
}
}
}

@Test
void test_baggageLogRecordProcessor_adds_attributes_to_spans_include_exclude(
@Mock ReadWriteLogRecord logRecord) {
Comment thread
SylvainJuge marked this conversation as resolved.
try (BaggageLogRecordProcessor processor =
new BaggageLogRecordProcessor(singletonList("key*"), singletonList("*excluded"))) {
try (Scope ignore =
Baggage.current().toBuilder()
.put("key", "value")
.put("key_is_excluded", "value")
.build()
.makeCurrent()) {
processor.onEmit(Context.current(), logRecord);
verify(logRecord).setAttribute(AttributeKey.stringKey("key"), "value");
verify(logRecord, Mockito.never())
.setAttribute(AttributeKey.stringKey("key_is_excluded"), "value");
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,12 @@

package io.opentelemetry.contrib.baggage.processor;

import static java.util.Collections.singletonList;

import io.opentelemetry.api.baggage.Baggage;
import io.opentelemetry.context.Context;
import io.opentelemetry.context.Scope;
import io.opentelemetry.sdk.trace.ReadWriteSpan;
import java.util.regex.Pattern;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
Expand All @@ -21,7 +22,7 @@ class BaggageSpanProcessorTest {

@Test
void test_baggageSpanProcessor_adds_attributes_to_spans(@Mock ReadWriteSpan span) {
try (BaggageSpanProcessor processor = BaggageSpanProcessor.allowAllBaggageKeys()) {
try (BaggageSpanProcessor processor = new BaggageSpanProcessor(null, null)) {
try (Scope ignore = Baggage.current().toBuilder().put("key", "value").build().makeCurrent()) {
processor.onStart(Context.current(), span);
Mockito.verify(span).setAttribute("key", "value");
Expand All @@ -32,7 +33,7 @@ void test_baggageSpanProcessor_adds_attributes_to_spans(@Mock ReadWriteSpan span
@Test
void test_baggageSpanProcessor_adds_attributes_to_spans_when_key_filter_matches(
@Mock ReadWriteSpan span) {
try (BaggageSpanProcessor processor = new BaggageSpanProcessor(key -> key.startsWith("k"))) {
try (BaggageSpanProcessor processor = new BaggageSpanProcessor(singletonList("k*"), null)) {
try (Scope ignore =
Baggage.current().toBuilder()
.put("key", "value")
Expand All @@ -47,20 +48,19 @@ void test_baggageSpanProcessor_adds_attributes_to_spans_when_key_filter_matches(
}

@Test
void test_baggageSpanProcessor_adds_attributes_to_spans_when_key_filter_matches_regex(
void test_baggageSpanProcessor_adds_attributes_to_spans_include_exclude(
@Mock ReadWriteSpan span) {
Pattern pattern = Pattern.compile("k.*");
try (BaggageSpanProcessor processor =
new BaggageSpanProcessor(key -> pattern.matcher(key).matches())) {
new BaggageSpanProcessor(singletonList("k*"), singletonList("*ignored"))) {
try (Scope ignore =
Baggage.current().toBuilder()
.put("key", "value")
.put("other", "value")
.put("key_is_ignored", "value")
.build()
.makeCurrent()) {
processor.onStart(Context.current(), span);
Mockito.verify(span).setAttribute("key", "value");
Mockito.verify(span, Mockito.never()).setAttribute("other", "value");
Mockito.verify(span, Mockito.never()).setAttribute("key_is_ignored", "value");
}
}
}
Expand Down
Loading