Allow for simpler creation of start-only and end-only SpanProcessors. (#5923)

This commit is contained in:
jason plumb 2023-12-04 09:40:09 -08:00 committed by GitHub
parent f1deb8ec78
commit e447e347e1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 173 additions and 23 deletions

View File

@ -5,12 +5,9 @@
package io.opentelemetry.sdk.autoconfigure.provider;
import io.opentelemetry.context.Context;
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
import io.opentelemetry.sdk.trace.ReadWriteSpan;
import io.opentelemetry.sdk.trace.ReadableSpan;
import io.opentelemetry.sdk.extension.incubator.trace.OnStartSpanProcessor;
import io.opentelemetry.sdk.trace.SdkTracerProviderBuilder;
import io.opentelemetry.sdk.trace.SpanProcessor;
@SuppressWarnings("deprecation") // Support testing of SdkTracerProviderConfigurer
public class TestTracerProviderConfigurer
@ -18,24 +15,8 @@ public class TestTracerProviderConfigurer
@Override
public void configure(SdkTracerProviderBuilder tracerProvider, ConfigProperties config) {
tracerProvider.addSpanProcessor(
new SpanProcessor() {
@Override
public void onStart(Context parentContext, ReadWriteSpan span) {
span.setAttribute("configured", config.getBoolean("otel.test.configured"));
}
@Override
public boolean isStartRequired() {
return true;
}
@Override
public void onEnd(ReadableSpan span) {}
@Override
public boolean isEndRequired() {
return false;
}
});
OnStartSpanProcessor.create(
(ctx, span) ->
span.setAttribute("configured", config.getBoolean("otel.test.configured"))));
}
}

View File

@ -0,0 +1,49 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.sdk.extension.incubator.trace;
import io.opentelemetry.context.Context;
import io.opentelemetry.sdk.trace.ReadWriteSpan;
import io.opentelemetry.sdk.trace.ReadableSpan;
import io.opentelemetry.sdk.trace.SpanProcessor;
/** A SpanProcessor implementation that is only capable of processing spans when they end. */
public final class OnEndSpanProcessor implements SpanProcessor {
private final OnEnd onEnd;
private OnEndSpanProcessor(OnEnd onEnd) {
this.onEnd = onEnd;
}
static SpanProcessor create(OnEnd onEnd) {
return new OnEndSpanProcessor(onEnd);
}
@Override
public void onEnd(ReadableSpan span) {
onEnd.apply(span);
}
@Override
public boolean isEndRequired() {
return true;
}
@Override
public void onStart(Context parentContext, ReadWriteSpan span) {
// nop
}
@Override
public boolean isStartRequired() {
return false;
}
@FunctionalInterface
public interface OnEnd {
void apply(ReadableSpan span);
}
}

View File

@ -0,0 +1,50 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.sdk.extension.incubator.trace;
import io.opentelemetry.context.Context;
import io.opentelemetry.sdk.trace.ReadWriteSpan;
import io.opentelemetry.sdk.trace.ReadableSpan;
import io.opentelemetry.sdk.trace.SpanProcessor;
/** A SpanProcessor that only handles onStart(). */
public final class OnStartSpanProcessor implements SpanProcessor {
private final OnStart onStart;
private OnStartSpanProcessor(OnStart onStart) {
this.onStart = onStart;
}
public static SpanProcessor create(OnStart onStart) {
return new OnStartSpanProcessor(onStart);
}
@Override
public void onStart(Context parentContext, ReadWriteSpan span) {
onStart.apply(parentContext, span);
}
@Override
public boolean isStartRequired() {
return true;
}
@Override
public void onEnd(ReadableSpan span) {
// nop
}
@Override
public boolean isEndRequired() {
return false;
}
@FunctionalInterface
public interface OnStart {
void apply(Context context, ReadWriteSpan span);
}
}

View File

@ -0,0 +1,31 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.sdk.extension.incubator.trace;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import io.opentelemetry.sdk.trace.ReadWriteSpan;
import io.opentelemetry.sdk.trace.ReadableSpan;
import io.opentelemetry.sdk.trace.SpanProcessor;
import java.util.concurrent.atomic.AtomicReference;
import org.junit.jupiter.api.Test;
class OnEndSpanProcessorTest {
@Test
void endOnly() {
AtomicReference<ReadableSpan> seenSpan = new AtomicReference<>();
ReadWriteSpan inputSpan = mock(ReadWriteSpan.class);
SpanProcessor processor = OnEndSpanProcessor.create(seenSpan::set);
assertThat(processor.isStartRequired()).isFalse();
assertThat(processor.isEndRequired()).isTrue();
processor.onEnd(inputSpan);
assertThat(seenSpan.get()).isSameAs(inputSpan);
}
}

View File

@ -0,0 +1,39 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.sdk.extension.incubator.trace;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import io.opentelemetry.context.Context;
import io.opentelemetry.sdk.trace.ReadWriteSpan;
import io.opentelemetry.sdk.trace.SpanProcessor;
import java.util.concurrent.atomic.AtomicReference;
import org.junit.jupiter.api.Test;
class OnStartSpanProcessorTest {
@Test
void startOnly() {
AtomicReference<Context> seenContext = new AtomicReference<>();
AtomicReference<ReadWriteSpan> seenSpan = new AtomicReference<>();
Context context = mock(Context.class);
ReadWriteSpan inputSpan = mock(ReadWriteSpan.class);
SpanProcessor processor =
OnStartSpanProcessor.create(
(ctx, span) -> {
seenContext.set(ctx);
seenSpan.set(span);
});
assertThat(processor.isStartRequired()).isTrue();
assertThat(processor.isEndRequired()).isFalse();
processor.onStart(context, inputSpan);
assertThat(seenContext.get()).isSameAs(context);
assertThat(seenSpan.get()).isSameAs(inputSpan);
}
}