Configuration class for BatchSpanProcessor (#1080)

* Add config class for BatchSpanProcessor

* Implement Configuration for BatchSpanProcessor

* goJF after rebase
This commit is contained in:
Giovanni Liva 2020-04-22 16:23:37 +02:00 committed by GitHub
parent 4bcfdb703f
commit cfba55f713
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 669 additions and 35 deletions

View File

@ -126,6 +126,7 @@ subprojects {
junit : 'junit:junit:4.12',
mockito : 'org.mockito:mockito-core:2.28.2',
truth : 'com.google.truth:truth:1.0.1',
system_rules : 'com.github.stefanbirkner:system-rules:1.19.0', // env and system properties
slf4jsimple : 'org.slf4j:slf4j-simple:1.7.25', // Compatibility layer
awaitility : 'org.awaitility:awaitility:3.0.0', // Compatibility layer
testcontainers : 'org.testcontainers:testcontainers:1.13.0',

View File

@ -232,7 +232,7 @@ public final class JaegerGrpcSpanExporter implements SpanExporter {
* @param tracerSdkProvider tracer SDK provider
*/
public void install(TracerSdkProvider tracerSdkProvider) {
BatchSpansProcessor spansProcessor = BatchSpansProcessor.newBuilder(this.build()).build();
BatchSpansProcessor spansProcessor = BatchSpansProcessor.create(this.build());
tracerSdkProvider.addSpanProcessor(spansProcessor);
}

View File

@ -18,6 +18,8 @@ dependencies {
testAnnotationProcessor libraries.auto_value
testCompile libraries.system_rules
signature "org.codehaus.mojo.signature:java17:1.0@signature"
signature "net.sf.androidscents.signature:android-api-level-24:7.0_r2@signature"
}

View File

@ -16,6 +16,9 @@
package io.opentelemetry.sdk.trace.export;
import com.google.auto.value.AutoValue;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.Maps;
import io.opentelemetry.OpenTelemetry;
import io.opentelemetry.internal.Utils;
import io.opentelemetry.metrics.LongCounter;
@ -27,7 +30,10 @@ import io.opentelemetry.sdk.trace.SpanProcessor;
import io.opentelemetry.sdk.trace.data.SpanData;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
@ -36,7 +42,10 @@ import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.annotation.concurrent.GuardedBy;
import javax.annotation.concurrent.Immutable;
/**
* Implementation of the {@link SpanProcessor} that batches spans exported by the SDK then pushes
@ -82,6 +91,33 @@ public final class BatchSpansProcessor implements SpanProcessor {
this.sampled = sampled;
}
/**
* Creates a {@code BatchSpansProcessor} instance using the default configuration.
*
* @param spanExporter The {@link SpanExporter} to use
* @return a {@code BatchSpansProcessor} instance.
*/
public static BatchSpansProcessor create(SpanExporter spanExporter) {
return create(spanExporter, Config.getDefault());
}
/**
* Creates a {@code BatchSpansProcessor} instance.
*
* @param spanExporter The {@link SpanExporter} to use
* @param config The {@link Config} to use
* @return a {@code BatchSpansProcessor} instance.
*/
public static BatchSpansProcessor create(SpanExporter spanExporter, Config config) {
return new BatchSpansProcessor(
spanExporter,
config.isExportOnlySampled(),
config.getScheduleDelayMillis(),
config.getMaxQueueSize(),
config.getMaxExportBatchSize(),
config.getExporterTimeoutMillis());
}
@Override
public void onStart(ReadableSpan span) {}
@ -394,4 +430,310 @@ public final class BatchSpansProcessor implements SpanProcessor {
}
}
}
@Immutable
@AutoValue
public abstract static class Config {
private static final long DEFAULT_SCHEDULE_DELAY_MILLIS = 5000;
private static final int DEFAULT_MAX_QUEUE_SIZE = 2048;
private static final int DEFAULT_MAX_EXPORT_BATCH_SIZE = 512;
private static final int DEFAULT_EXPORT_TIMEOUT_MILLIS = 30_000;
private static final boolean DEFAULT_EXPORT_ONLY_SAMPLED = true;
public abstract boolean isExportOnlySampled();
public abstract long getScheduleDelayMillis();
public abstract int getMaxQueueSize();
public abstract int getMaxExportBatchSize();
public abstract int getExporterTimeoutMillis();
/**
* Creates a {@link Config} object using the default configuration.
*
* @return The {@link Config} object.
* @since 0.4.0
*/
public static Config getDefault() {
return newBuilder().build();
}
/**
* Creates a {@link Config} object reading the configuration values from the environment and
* from system properties. System properties override values defined in the environment. If a
* configuration value is missing, it uses the default value.
*
* @return The {@link Config} object.
* @since 0.4.0
*/
public static Config loadFromDefaultSources() {
return newBuilder().readEnvironment().readSystemProperties().build();
}
/**
* Returns a new {@link Builder} with default options.
*
* @return a new {@code Builder} with default options.
* @since 0.4.0
*/
public static Builder newBuilder() {
return new AutoValue_BatchSpansProcessor_Config.Builder()
.setScheduleDelayMillis(DEFAULT_SCHEDULE_DELAY_MILLIS)
.setMaxQueueSize(DEFAULT_MAX_QUEUE_SIZE)
.setMaxExportBatchSize(DEFAULT_MAX_EXPORT_BATCH_SIZE)
.setExporterTimeoutMillis(DEFAULT_EXPORT_TIMEOUT_MILLIS)
.setExportOnlySampled(DEFAULT_EXPORT_ONLY_SAMPLED);
}
@AutoValue.Builder
public abstract static class Builder {
private static final String KEY_SCHEDULE_DELAY_MILLIS = "otel.bsp.schedule.delay";
private static final String KEY_MAX_QUEUE_SIZE = "otel.bsp.max.queue";
private static final String KEY_MAX_EXPORT_BATCH_SIZE = "otel.bsp.max.export.batch";
private static final String KEY_EXPORT_TIMEOUT_MILLIS = "otel.bsp.export.timeout";
private static final String KEY_SAMPLED = "otel.bsp.export.sampled";
@VisibleForTesting
protected enum NamingConvention {
DOT {
@Override
public String normalize(@Nonnull String key) {
return key.toLowerCase();
}
},
ENV_VAR {
@Override
public String normalize(@Nonnull String key) {
return key.toLowerCase().replace("_", ".");
}
};
public abstract String normalize(@Nonnull String key);
public Map<String, String> normalize(@Nonnull Map<String, String> map) {
Map<String, String> properties = new HashMap<>();
for (Map.Entry<String, String> entry : map.entrySet()) {
properties.put(normalize(entry.getKey()), entry.getValue());
}
return Collections.unmodifiableMap(properties);
}
}
/**
* Sets the configuration values from the given configuration map for only the available keys.
* This method looks for the following keys:
*
* <ul>
* <li>{@code otel.bsp.schedule.delay}: to set the delay interval between two consecutive
* exports.
* <li>{@code otel.bsp.max.queue}: to set the maximum queue size.
* <li>{@code otel.bsp.max.export.batch}: to set the maximum batch size.
* <li>{@code otel.bsp.export.timeout}: to set the maximum allowed time to export data.
* <li>{@code otel.bsp.export.sampled}: to set whether only sampled spans should be
* exported.
* </ul>
*
* @param configMap {@link Map} holding the configuration values.
* @return this.
*/
@VisibleForTesting
Builder fromConfigMap(Map<String, String> configMap, NamingConvention namingConvention) {
configMap = namingConvention.normalize(configMap);
Long longValue = getLongProperty(KEY_SCHEDULE_DELAY_MILLIS, configMap);
if (longValue != null) {
this.setScheduleDelayMillis(longValue);
}
Integer intValue = getIntProperty(KEY_MAX_QUEUE_SIZE, configMap);
if (intValue != null) {
this.setMaxQueueSize(intValue);
}
intValue = getIntProperty(KEY_MAX_EXPORT_BATCH_SIZE, configMap);
if (intValue != null) {
this.setMaxExportBatchSize(intValue);
}
intValue = getIntProperty(KEY_EXPORT_TIMEOUT_MILLIS, configMap);
if (intValue != null) {
this.setExporterTimeoutMillis(intValue);
}
Boolean boolValue = getBooleanProperty(KEY_SAMPLED, configMap);
if (boolValue != null) {
this.setExportOnlySampled(boolValue);
}
return this;
}
/**
* Sets the configuration values from the given properties object for only the available keys.
* This method looks for the following keys:
*
* <ul>
* <li>{@code otel.bsp.schedule.delay}: to set the delay interval between two consecutive
* exports.
* <li>{@code otel.bsp.max.queue}: to set the maximum queue size.
* <li>{@code otel.bsp.max.export.batch}: to set the maximum batch size.
* <li>{@code otel.bsp.export.timeout}: to set the maximum allowed time to export data.
* <li>{@code otel.bsp.export.sampled}: to set whether only sampled spans should be
* exported.
* </ul>
*
* @param properties {@link Properties} holding the configuration values.
* @return this.
*/
public Builder readProperties(Properties properties) {
return fromConfigMap(Maps.fromProperties(properties), NamingConvention.DOT);
}
/**
* Sets the configuration values from environment variables for only the available keys. This
* method looks for the following keys:
*
* <ul>
* <li>{@code OTEL_BSP_SCHEDULE_DELAY}: to set the delay interval between two consecutive
* exports.
* <li>{@code OTEL_BSP_MAX_QUEUE}: to set the maximum queue size.
* <li>{@code OTEL_BSP_MAX_EXPORT_BATCH}: to set the maximum batch size.
* <li>{@code OTEL_BSP_EXPORT_TIMEOUT}: to set the maximum allowed time to export data.
* <li>{@code OTEL_BSP_EXPORT_SAMPLED}: to set whether only sampled spans should be
* exported.
* </ul>
*
* @return this.
*/
public Builder readEnvironment() {
return fromConfigMap(System.getenv(), NamingConvention.ENV_VAR);
}
/**
* Sets the configuration values from system properties for only the available keys. This
* method looks for the following keys:
*
* <ul>
* <li>{@code otel.bsp.schedule.delay}: to set the delay interval between two consecutive
* exports.
* <li>{@code otel.bsp.max.queue}: to set the maximum queue size.
* <li>{@code otel.bsp.max.export.batch}: to set the maximum batch size.
* <li>{@code otel.bsp.export.timeout}: to set the maximum allowed time to export data.
* <li>{@code otel.bsp.export.sampled}: to set whether only sampled spans should be
* reported.
* </ul>
*
* @return this.
*/
public Builder readSystemProperties() {
return readProperties(System.getProperties());
}
/**
* Set whether only sampled spans should be exported.
*
* <p>Default value is {@code true}.
*
* @see BatchSpansProcessor.Config#DEFAULT_EXPORT_ONLY_SAMPLED
* @param sampled report only sampled spans.
* @return this.
*/
public abstract Builder setExportOnlySampled(boolean sampled);
/**
* Sets the delay interval between two consecutive exports. The actual interval may be shorter
* if the batch size is getting larger than {@code maxQueuedSpans / 2}.
*
* <p>Default value is {@code 5000}ms.
*
* @see BatchSpansProcessor.Config#DEFAULT_SCHEDULE_DELAY_MILLIS
* @param scheduleDelayMillis the delay interval between two consecutive exports.
* @return this.
*/
public abstract Builder setScheduleDelayMillis(long scheduleDelayMillis);
/**
* Sets the maximum time an exporter will be allowed to run before being cancelled.
*
* <p>Default value is {@code 30000}ms
*
* @see BatchSpansProcessor.Config#DEFAULT_EXPORT_TIMEOUT_MILLIS
* @param exporterTimeoutMillis the timeout for exports in milliseconds.
* @return this
*/
public abstract Builder setExporterTimeoutMillis(int exporterTimeoutMillis);
/**
* Sets the maximum number of Spans that are kept in the queue before start dropping.
*
* <p>See the BatchSampledSpansProcessor class description for a high-level design description
* of this class.
*
* <p>Default value is {@code 2048}.
*
* @see BatchSpansProcessor.Config#DEFAULT_MAX_QUEUE_SIZE
* @param maxQueueSize the maximum number of Spans that are kept in the queue before start
* dropping.
* @return this.
*/
public abstract Builder setMaxQueueSize(int maxQueueSize);
/**
* Sets the maximum batch size for every export. This must be smaller or equal to {@code
* maxQueuedSpans}.
*
* <p>Default value is {@code 512}.
*
* @see BatchSpansProcessor.Config#DEFAULT_MAX_EXPORT_BATCH_SIZE
* @param maxExportBatchSize the maximum batch size for every export.
* @return this.
*/
public abstract Builder setMaxExportBatchSize(int maxExportBatchSize);
abstract Config autoBuild(); // not public
/**
* Builds the {@link Config} object.
*
* @return the {@link Config} object.
*/
public Config build() {
Config config = autoBuild();
Utils.checkArgument(
config.getScheduleDelayMillis() >= 0,
"scheduleDelayMillis must greater than or equal 0.");
Utils.checkArgument(
config.getExporterTimeoutMillis() >= 0,
"exporterTimeoutMillis must greater than or equal 0.");
Utils.checkArgument(config.getMaxQueueSize() > 0, "maxQueueSize must be positive.");
Utils.checkArgument(
config.getMaxExportBatchSize() > 0, "maxExportBatchSize must be positive.");
return config;
}
@Nullable
private static Boolean getBooleanProperty(String name, Map<String, String> map) {
if (map.containsKey(name)) {
return Boolean.parseBoolean(map.get(name));
}
return null;
}
@Nullable
private static Integer getIntProperty(String name, Map<String, String> map) {
try {
return Integer.parseInt(map.get(name));
} catch (NumberFormatException ex) {
return null;
}
}
@Nullable
private static Long getLongProperty(String name, Map<String, String> map) {
try {
return Long.parseLong(map.get(name));
} catch (NumberFormatException ex) {
return null;
}
}
}
}
}

View File

@ -0,0 +1,65 @@
/*
* Copyright 2019, OpenTelemetry Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* Utilities that allows different tracing services to export recorded data for sampled spans in
* their own format.
*
* <h2>Contents</h2>
*
* <ul>
* <li>{@link io.opentelemetry.sdk.trace.export.SpanExporter}
* <li>{@link io.opentelemetry.sdk.trace.export.SimpleSpansProcessor}
* <li>{@link io.opentelemetry.sdk.trace.export.BatchSpansProcessor}
* <li>{@link io.opentelemetry.sdk.trace.export.MultiSpanExporter}
* </ul>
*
* <h2>Default values for {@link io.opentelemetry.sdk.trace.export.BatchSpansProcessor.Config}</h2>
*
* <ul>
* <li>{@code SCHEDULE_DELAY_MILLIS: 5000}
* <li>{@code MAX_QUEUE_SIZE: 2048}
* <li>{@code MAX_EXPORT_BATCH_SIZE: 512}
* <li>{@code EXPORT_TIMEOUT_MILLIS: 30_000}
* <li>{@code REPORT_ONLY_SAMPLED: true}
* </ul>
*
* <p>Values for {@link io.opentelemetry.sdk.trace.export.BatchSpansProcessor.Config} can be read
* from system properties, environment variables, or {@link java.util.Properties} objects.
*
* <p>For System Properties and {@link java.util.Properties} objects, {@link
* io.opentelemetry.sdk.trace.export.BatchSpansProcessor.Config} will look for the following names:
*
* <ul>
* <li>{@code otel.bsp.schedule.delay}: sets the delay interval between two consecutive exports.
* <li>{@code otel.bsp.max.queue}: sets the maximum queue size.
* <li>{@code otel.bsp.max.export.batch}: sets the maximum batch size.
* <li>{@code otel.bsp.export.timeout}: sets the maximum allowed time to export data.
* <li>{@code otel.bsp.export.sampled}: sets whether only sampled spans should be exported.
* </ul>
*
* <p>For Environment Variable, {@link io.opentelemetry.sdk.trace.export.BatchSpansProcessor.Config}
* will look for the following names:
*
* <ul>
* <li>{@code OTEL_BSP_SCHEDULE_DELAY}: sets the delay interval between two consecutive exports.
* <li>{@code OTEL_BSP_MAX_QUEUE}: sets the maximum queue size.
* <li>{@code OTEL_BSP_MAX_EXPORT_BATCH}: sets the maximum batch size.
* <li>{@code OTEL_BSP_EXPORT_TIMEOUT}: sets the maximum allowed time to export data.
* <li>{@code OTEL_BSP_EXPORT_SAMPLED}: sets whether only sampled spans should be exported.
* </ul>
*/
package io.opentelemetry.sdk.trace.export;

View File

@ -28,7 +28,10 @@ import io.opentelemetry.trace.Tracer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
@ -36,7 +39,10 @@ import javax.annotation.Nullable;
import javax.annotation.concurrent.GuardedBy;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.contrib.java.lang.system.EnvironmentVariables;
import org.junit.contrib.java.lang.system.ProvideSystemProperty;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import org.mockito.ArgumentMatchers;
@ -65,6 +71,80 @@ public class BatchSpansProcessorTest {
tracerSdkFactory.shutdown();
}
@RunWith(JUnit4.class)
public static class ConfigurationSystemPropertiesTest {
@Rule
public final ProvideSystemProperty systemProperties =
new ProvideSystemProperty("otel.bsp.schedule.delay", "5")
.and("otel.bsp.max.queue", "5")
.and("otel.bsp.export.timeout", "5")
.and("otel.bsp.export.sampled", "false");
@Test
public void testSystemProperties() {
BatchSpansProcessor.Config config = BatchSpansProcessor.Config.loadFromDefaultSources();
assertThat(config.getScheduleDelayMillis()).isEqualTo(5);
assertThat(config.getMaxQueueSize()).isEqualTo(5);
// This is not defined and should be equal to the default values
assertThat(config.getMaxExportBatchSize())
.isEqualTo(BatchSpansProcessor.Config.getDefault().getMaxExportBatchSize());
assertThat(config.getExporterTimeoutMillis()).isEqualTo(5);
assertThat(config.isExportOnlySampled()).isEqualTo(false);
}
}
@RunWith(JUnit4.class)
public static class ConfigurationEnvironmentVariablesTest {
@Rule
public final EnvironmentVariables environmentVariables =
new EnvironmentVariables()
.set("OTEL_BSP_MAX_QUEUE", "22")
.set("OTEL_BSP_EXPORT_TIMEOUT", "22")
.set("OTEL_BSP_EXPORT_SAMPLED", "true");
@Test
public void testEnvironmentVariables() {
BatchSpansProcessor.Config config = BatchSpansProcessor.Config.loadFromDefaultSources();
BatchSpansProcessor.Config defaultConf = BatchSpansProcessor.Config.getDefault();
// This is not defined and should be equal to the default values
assertThat(config.getScheduleDelayMillis()).isEqualTo(defaultConf.getScheduleDelayMillis());
assertThat(config.getMaxQueueSize()).isEqualTo(22);
// This is not defined and should be equal to the default values
assertThat(config.getMaxExportBatchSize()).isEqualTo(defaultConf.getMaxExportBatchSize());
assertThat(config.getExporterTimeoutMillis()).isEqualTo(22);
assertThat(config.isExportOnlySampled()).isEqualTo(true);
}
}
@RunWith(JUnit4.class)
public static class ConfigurationSystemAndEnvironmentTest {
@Rule
public final ProvideSystemProperty systemProperties =
new ProvideSystemProperty("otel.bsp.max.queue", "5")
.and("otel.bsp.export.timeout", "5")
.and("otel.bsp.export.sampled", "false");
@Rule
public final EnvironmentVariables environmentVariables =
new EnvironmentVariables()
.set("OTEL_BSP_SCHEDULE_DELAY", "22")
.set("OTEL_BSP_MAX_QUEUE", "22")
.set("OTEL_BSP_EXPORT_TIMEOUT", "22")
.set("OTEL_BSP_EXPORT_SAMPLED", "true");
@Test
public void testSystemAndEnv() {
BatchSpansProcessor.Config config = BatchSpansProcessor.Config.loadFromDefaultSources();
BatchSpansProcessor.Config defaultConf = BatchSpansProcessor.Config.getDefault();
assertThat(config.getScheduleDelayMillis()).isEqualTo(22);
assertThat(config.getMaxQueueSize()).isEqualTo(5);
// This is not defined and should be equal to the default values
assertThat(config.getMaxExportBatchSize()).isEqualTo(defaultConf.getMaxExportBatchSize());
assertThat(config.getExporterTimeoutMillis()).isEqualTo(5);
assertThat(config.isExportOnlySampled()).isEqualTo(false);
}
}
private ReadableSpan createSampledEndedSpan(String spanName) {
io.opentelemetry.trace.Span span =
TestUtils.startSpanWithSampler(tracerSdkFactory, tracer, spanName, Samplers.alwaysOn())
@ -73,6 +153,128 @@ public class BatchSpansProcessorTest {
return (ReadableSpan) span;
}
@Test
public void testConfiguration() {
BatchSpansProcessor.Config config;
BatchSpansProcessor.Config defConfig = BatchSpansProcessor.Config.getDefault();
config = BatchSpansProcessor.Config.newBuilder().build();
// check defaults
assertThat(config.getScheduleDelayMillis()).isEqualTo(defConfig.getScheduleDelayMillis());
assertThat(config.getMaxQueueSize()).isEqualTo(defConfig.getMaxQueueSize());
assertThat(config.getMaxExportBatchSize()).isEqualTo(defConfig.getMaxExportBatchSize());
assertThat(config.getExporterTimeoutMillis()).isEqualTo(defConfig.getExporterTimeoutMillis());
assertThat(config.isExportOnlySampled()).isEqualTo(defConfig.isExportOnlySampled());
// check system configuration
Map<String, String> configMap = new HashMap<>();
configMap.put("otel.bsp.schedule.delay", "1");
configMap.put("otel.bsp.max.queue", "1");
configMap.put("otel.bsp.max.export.batch", "1");
configMap.put("otel.bsp.export.timeout", "1");
configMap.put("otel.bsp.export.sampled", "false");
config =
BatchSpansProcessor.Config.newBuilder()
.fromConfigMap(configMap, BatchSpansProcessor.Config.Builder.NamingConvention.DOT)
.build();
assertThat(config.getScheduleDelayMillis()).isEqualTo(1);
assertThat(config.getMaxQueueSize()).isEqualTo(1);
assertThat(config.getMaxExportBatchSize()).isEqualTo(1);
assertThat(config.getExporterTimeoutMillis()).isEqualTo(1);
assertThat(config.isExportOnlySampled()).isEqualTo(false);
// check properties
Properties properties = new Properties();
for (Map.Entry<String, String> entry : configMap.entrySet()) {
properties.put(entry.getKey(), entry.getValue());
}
config = BatchSpansProcessor.Config.newBuilder().readProperties(properties).build();
assertThat(config.getScheduleDelayMillis()).isEqualTo(1);
assertThat(config.getMaxQueueSize()).isEqualTo(1);
assertThat(config.getMaxExportBatchSize()).isEqualTo(1);
assertThat(config.getExporterTimeoutMillis()).isEqualTo(1);
assertThat(config.isExportOnlySampled()).isEqualTo(false);
// Check env vars
configMap.clear();
configMap.put("OTEL_BSP_SCHEDULE_DELAY", "2");
configMap.put("OTEL_BSP_MAX_QUEUE", "2");
configMap.put("OTEL_BSP_MAX_EXPORT_BATCH", "2");
configMap.put("OTEL_BSP_EXPORT_TIMEOUT", "2");
configMap.put("OTEL_BSP_EXPORT_SAMPLED", "true");
config =
BatchSpansProcessor.Config.newBuilder()
.fromConfigMap(configMap, BatchSpansProcessor.Config.Builder.NamingConvention.ENV_VAR)
.build();
assertThat(config.getScheduleDelayMillis()).isEqualTo(2);
assertThat(config.getMaxQueueSize()).isEqualTo(2);
assertThat(config.getMaxExportBatchSize()).isEqualTo(2);
assertThat(config.getExporterTimeoutMillis()).isEqualTo(2);
assertThat(config.isExportOnlySampled()).isEqualTo(true);
// Check mixing conventions
configMap.clear();
configMap.put("OTEL_BSP_schedule_DELAY", "3");
configMap.put("OTEL.BSP.MAX_QUEUE", "3");
configMap.put("OTEL_bsp.MAX_EXPORT_BATCH", "3");
configMap.put("OTEL_BSP_ExPoRt_TIMEOUT", "3");
configMap.put("OTEL_bSp.EXPORT.SAmpleD", "false");
config =
BatchSpansProcessor.Config.newBuilder()
.fromConfigMap(configMap, BatchSpansProcessor.Config.Builder.NamingConvention.ENV_VAR)
.build();
assertThat(config.getScheduleDelayMillis()).isEqualTo(3);
assertThat(config.getMaxQueueSize()).isEqualTo(3);
assertThat(config.getMaxExportBatchSize()).isEqualTo(3);
assertThat(config.getExporterTimeoutMillis()).isEqualTo(3);
assertThat(config.isExportOnlySampled()).isEqualTo(false);
}
@Test
public void testOnlySetPropertiesOverrideDefaults() {
BatchSpansProcessor.Config config;
Map<String, String> configMap = new HashMap<>();
// check only set values are written
configMap.clear();
configMap.put("OTEL_BSP_SCHEDULE_DELAY", "1");
config =
BatchSpansProcessor.Config.newBuilder()
.fromConfigMap(configMap, BatchSpansProcessor.Config.Builder.NamingConvention.ENV_VAR)
.build();
assertThat(config.getScheduleDelayMillis()).isEqualTo(1);
assertThat(config.getMaxQueueSize()).isEqualTo(2048);
assertThat(config.getMaxExportBatchSize()).isEqualTo(512);
assertThat(config.getExporterTimeoutMillis()).isEqualTo(30_000);
assertThat(config.isExportOnlySampled()).isEqualTo(true);
}
@Test
public void testUserSetPropertiesOverrideDefaults() {
BatchSpansProcessor.Config config;
Map<String, String> configMap = new HashMap<>();
// check only set values are written
configMap.clear();
configMap.put("otel.bsp.schedule.delay", "1");
configMap.put("otel.bsp.max.queue", "1");
configMap.put("otel.bsp.max.export.batch", "1");
configMap.put("otel.bsp.export.timeout", "1");
configMap.put("otel.bsp.export.sampled", "false");
config =
BatchSpansProcessor.Config.newBuilder()
.fromConfigMap(configMap, BatchSpansProcessor.Config.Builder.NamingConvention.DOT)
.setScheduleDelayMillis(2)
.setMaxQueueSize(2)
.setMaxExportBatchSize(2)
.setExporterTimeoutMillis(2)
.setExportOnlySampled(true)
.build();
assertThat(config.getScheduleDelayMillis()).isEqualTo(2);
assertThat(config.getMaxQueueSize()).isEqualTo(2);
assertThat(config.getMaxExportBatchSize()).isEqualTo(2);
assertThat(config.getExporterTimeoutMillis()).isEqualTo(2);
assertThat(config.isExportOnlySampled()).isEqualTo(true);
}
// TODO(bdrutu): Fix this when Sampler return RECORD option.
/*
private ReadableSpan createNotSampledRecordingEventsEndedSpan(String spanName) {
@ -91,8 +293,7 @@ public class BatchSpansProcessorTest {
@Test
public void startEndRequirements() {
BatchSpansProcessor spansProcessor =
BatchSpansProcessor.newBuilder(new WaitingSpanExporter(0)).build();
BatchSpansProcessor spansProcessor = BatchSpansProcessor.create(new WaitingSpanExporter(0));
assertThat(spansProcessor.isStartRequired()).isFalse();
assertThat(spansProcessor.isEndRequired()).isTrue();
}
@ -101,9 +302,11 @@ public class BatchSpansProcessorTest {
public void exportDifferentSampledSpans() {
WaitingSpanExporter waitingSpanExporter = new WaitingSpanExporter(2);
tracerSdkFactory.addSpanProcessor(
BatchSpansProcessor.newBuilder(waitingSpanExporter)
.setScheduleDelayMillis(MAX_SCHEDULE_DELAY_MILLIS)
.build());
BatchSpansProcessor.create(
waitingSpanExporter,
BatchSpansProcessor.Config.newBuilder()
.setScheduleDelayMillis(MAX_SCHEDULE_DELAY_MILLIS)
.build()));
ReadableSpan span1 = createSampledEndedSpan(SPAN_NAME_1);
ReadableSpan span2 = createSampledEndedSpan(SPAN_NAME_2);
@ -114,12 +317,14 @@ public class BatchSpansProcessorTest {
@Test
public void exportMoreSpansThanTheBufferSize() {
WaitingSpanExporter waitingSpanExporter = new WaitingSpanExporter(6);
tracerSdkFactory.addSpanProcessor(
BatchSpansProcessor.newBuilder(waitingSpanExporter)
BatchSpansProcessor.Config config =
BatchSpansProcessor.Config.newBuilder()
.setMaxQueueSize(6)
.setMaxExportBatchSize(2)
.setScheduleDelayMillis(MAX_SCHEDULE_DELAY_MILLIS)
.build());
.build();
tracerSdkFactory.addSpanProcessor(BatchSpansProcessor.create(waitingSpanExporter, config));
ReadableSpan span1 = createSampledEndedSpan(SPAN_NAME_1);
ReadableSpan span2 = createSampledEndedSpan(SPAN_NAME_1);
@ -141,12 +346,15 @@ public class BatchSpansProcessorTest {
@Test
public void forceExport() {
WaitingSpanExporter waitingSpanExporter = new WaitingSpanExporter(1, 1);
BatchSpansProcessor batchSpansProcessor =
BatchSpansProcessor.newBuilder(waitingSpanExporter)
BatchSpansProcessor.Config config =
BatchSpansProcessor.Config.newBuilder()
.setMaxQueueSize(10_000)
.setMaxExportBatchSize(2_000)
.setScheduleDelayMillis(10_000) // 10s
.build();
BatchSpansProcessor batchSpansProcessor =
BatchSpansProcessor.create(waitingSpanExporter, config);
tracerSdkFactory.addSpanProcessor(batchSpansProcessor);
for (int i = 0; i < 100; i++) {
createSampledEndedSpan("notExported");
@ -164,12 +372,15 @@ public class BatchSpansProcessorTest {
public void exportSpansToMultipleServices() {
WaitingSpanExporter waitingSpanExporter = new WaitingSpanExporter(2);
WaitingSpanExporter waitingSpanExporter2 = new WaitingSpanExporter(2);
tracerSdkFactory.addSpanProcessor(
BatchSpansProcessor.newBuilder(
MultiSpanExporter.create(
Arrays.<SpanExporter>asList(waitingSpanExporter, waitingSpanExporter2)))
BatchSpansProcessor.Config config =
BatchSpansProcessor.Config.newBuilder()
.setScheduleDelayMillis(MAX_SCHEDULE_DELAY_MILLIS)
.build());
.build();
tracerSdkFactory.addSpanProcessor(
BatchSpansProcessor.create(
MultiSpanExporter.create(
Arrays.<SpanExporter>asList(waitingSpanExporter, waitingSpanExporter2)),
config));
ReadableSpan span1 = createSampledEndedSpan(SPAN_NAME_1);
ReadableSpan span2 = createSampledEndedSpan(SPAN_NAME_2);
@ -183,13 +394,16 @@ public class BatchSpansProcessorTest {
public void exportMoreSpansThanTheMaximumLimit() {
final int maxQueuedSpans = 8;
WaitingSpanExporter waitingSpanExporter = new WaitingSpanExporter(maxQueuedSpans);
tracerSdkFactory.addSpanProcessor(
BatchSpansProcessor.newBuilder(
MultiSpanExporter.create(Arrays.asList(blockingSpanExporter, waitingSpanExporter)))
BatchSpansProcessor.Config config =
BatchSpansProcessor.Config.newBuilder()
.setScheduleDelayMillis(MAX_SCHEDULE_DELAY_MILLIS)
.setMaxQueueSize(maxQueuedSpans)
.setMaxExportBatchSize(maxQueuedSpans / 2)
.build());
.build();
tracerSdkFactory.addSpanProcessor(
BatchSpansProcessor.create(
MultiSpanExporter.create(Arrays.asList(blockingSpanExporter, waitingSpanExporter)),
config));
List<SpanData> spansToExport = new ArrayList<>(maxQueuedSpans + 1);
// Wait to block the worker thread in the BatchSampledSpansProcessor. This ensures that no items
@ -247,11 +461,14 @@ public class BatchSpansProcessorTest {
.when(mockServiceHandler)
.export(ArgumentMatchers.<SpanData>anyList());
tracerSdkFactory.addSpanProcessor(
BatchSpansProcessor.newBuilder(
MultiSpanExporter.create(Arrays.asList(mockServiceHandler, waitingSpanExporter)))
BatchSpansProcessor.Config config =
BatchSpansProcessor.Config.newBuilder()
.setScheduleDelayMillis(MAX_SCHEDULE_DELAY_MILLIS)
.build());
.build();
tracerSdkFactory.addSpanProcessor(
BatchSpansProcessor.create(
MultiSpanExporter.create(Arrays.asList(mockServiceHandler, waitingSpanExporter)),
config));
ReadableSpan span1 = createSampledEndedSpan(SPAN_NAME_1);
List<SpanData> exported = waitingSpanExporter.waitForExport();
assertThat(exported).containsExactly(span1.toSpanData());
@ -281,12 +498,14 @@ public class BatchSpansProcessorTest {
};
int exporterTimeoutMillis = 100;
tracerSdkFactory.addSpanProcessor(
BatchSpansProcessor.newBuilder(waitingSpanExporter)
BatchSpansProcessor.Config config =
BatchSpansProcessor.Config.newBuilder()
.setExporterTimeoutMillis(exporterTimeoutMillis)
.setScheduleDelayMillis(1)
.setMaxQueueSize(1)
.build());
.build();
tracerSdkFactory.addSpanProcessor(BatchSpansProcessor.create(waitingSpanExporter, config));
ReadableSpan span = createSampledEndedSpan(SPAN_NAME_1);
List<SpanData> exported = waitingSpanExporter.waitForExport();
@ -300,10 +519,11 @@ public class BatchSpansProcessorTest {
@Test
public void exportNotSampledSpans() {
WaitingSpanExporter waitingSpanExporter = new WaitingSpanExporter(1);
tracerSdkFactory.addSpanProcessor(
BatchSpansProcessor.newBuilder(waitingSpanExporter)
BatchSpansProcessor.Config config =
BatchSpansProcessor.Config.newBuilder()
.setScheduleDelayMillis(MAX_SCHEDULE_DELAY_MILLIS)
.build());
.build();
tracerSdkFactory.addSpanProcessor(BatchSpansProcessor.create(waitingSpanExporter, config));
createNotSampledEndedSpan(SPAN_NAME_1);
createNotSampledEndedSpan(SPAN_NAME_2);
@ -355,8 +575,10 @@ public class BatchSpansProcessorTest {
public void shutdownFlushes() {
WaitingSpanExporter waitingSpanExporter = new WaitingSpanExporter(1);
// Set the export delay to zero, for no timeout, in order to confirm the #flush() below works
tracerSdkFactory.addSpanProcessor(
BatchSpansProcessor.newBuilder(waitingSpanExporter).setScheduleDelayMillis(0).build());
BatchSpansProcessor.Config config =
BatchSpansProcessor.Config.newBuilder().setScheduleDelayMillis(0).build();
tracerSdkFactory.addSpanProcessor(BatchSpansProcessor.create(waitingSpanExporter, config));
ReadableSpan span2 = createSampledEndedSpan(SPAN_NAME_2);

View File

@ -117,10 +117,12 @@ public class SimpleSpansProcessorTest {
@Test
public void tracerSdk_NotSampled_Span() {
WaitingSpanExporter waitingSpanExporter = new WaitingSpanExporter(1);
tracerSdkFactory.addSpanProcessor(
BatchSpansProcessor.newBuilder(waitingSpanExporter)
BatchSpansProcessor.Config config =
BatchSpansProcessor.Config.newBuilder()
.setScheduleDelayMillis(MAX_SCHEDULE_DELAY_MILLIS)
.build());
.build();
tracerSdkFactory.addSpanProcessor(BatchSpansProcessor.create(waitingSpanExporter, config));
TestUtils.startSpanWithSampler(tracerSdkFactory, tracer, SPAN_NAME, Samplers.alwaysOff())
.startSpan()