Configuration class for BatchSpanProcessor (#1080)
* Add config class for BatchSpanProcessor * Implement Configuration for BatchSpanProcessor * goJF after rebase
This commit is contained in:
parent
4bcfdb703f
commit
cfba55f713
|
|
@ -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',
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
Loading…
Reference in New Issue