io.opentelemetry
opentelemetry-semconv
diff --git a/extensions/opentelemetry/opentelemetry/runtime/src/main/java/io/quarkus/opentelemetry/runtime/OpenTelemetryConfig.java b/extensions/opentelemetry/opentelemetry/runtime/src/main/java/io/quarkus/opentelemetry/runtime/OpenTelemetryConfig.java
index 163fafd2f8f7e..16fdf7b4bca9c 100644
--- a/extensions/opentelemetry/opentelemetry/runtime/src/main/java/io/quarkus/opentelemetry/runtime/OpenTelemetryConfig.java
+++ b/extensions/opentelemetry/opentelemetry/runtime/src/main/java/io/quarkus/opentelemetry/runtime/OpenTelemetryConfig.java
@@ -1,5 +1,7 @@
package io.quarkus.opentelemetry.runtime;
+import java.util.List;
+
import io.quarkus.opentelemetry.runtime.tracing.TracerConfig;
import io.quarkus.runtime.annotations.ConfigItem;
import io.quarkus.runtime.annotations.ConfigRoot;
@@ -15,6 +17,16 @@ public final class OpenTelemetryConfig {
@ConfigItem(defaultValue = "true")
public boolean enabled;
+ /**
+ * Comma separated list of OpenTelemetry propagators which must be supported.
+ *
+ * Valid values are {@code b3, b3multi, baggage, jaeger, ottrace, tracecontext, xray}.
+ *
+ * Default value is {@code traceContext,baggage}
+ */
+ @ConfigItem(defaultValue = "tracecontext,baggage")
+ public List propagators;
+
/** Build / static runtime config for tracer */
public TracerConfig tracer;
}
diff --git a/extensions/opentelemetry/opentelemetry/runtime/src/main/java/io/quarkus/opentelemetry/runtime/OpenTelemetryRecorder.java b/extensions/opentelemetry/opentelemetry/runtime/src/main/java/io/quarkus/opentelemetry/runtime/OpenTelemetryRecorder.java
index f427ee304d8b1..ff0f126a0e0ad 100644
--- a/extensions/opentelemetry/opentelemetry/runtime/src/main/java/io/quarkus/opentelemetry/runtime/OpenTelemetryRecorder.java
+++ b/extensions/opentelemetry/opentelemetry/runtime/src/main/java/io/quarkus/opentelemetry/runtime/OpenTelemetryRecorder.java
@@ -3,9 +3,7 @@
import java.util.function.Supplier;
import io.opentelemetry.api.GlobalOpenTelemetry;
-import io.opentelemetry.api.trace.propagation.W3CTraceContextPropagator;
import io.opentelemetry.context.ContextStorage;
-import io.opentelemetry.context.propagation.ContextPropagators;
import io.opentelemetry.sdk.OpenTelemetrySdk;
import io.opentelemetry.sdk.OpenTelemetrySdkBuilder;
import io.opentelemetry.sdk.trace.SdkTracerProvider;
@@ -23,7 +21,7 @@ public void resetGlobalOpenTelemetryForDevMode() {
}
/* STATIC INIT */
- public void createOpenTelemetry(RuntimeValue tracerProvider) {
+ public void createOpenTelemetry(RuntimeValue tracerProvider, OpenTelemetryConfig openTelemetryConfig) {
OpenTelemetrySdkBuilder builder = OpenTelemetrySdk.builder();
// Set tracer provider if present
@@ -31,8 +29,7 @@ public void createOpenTelemetry(RuntimeValue tracerProvider)
builder.setTracerProvider(tracerProvider.getValue());
}
- // Add propagators. //TODO Need a way to handle this with config
- builder.setPropagators(ContextPropagators.create(W3CTraceContextPropagator.getInstance()));
+ builder.setPropagators(OpenTelemetryUtil.mapPropagators(openTelemetryConfig.propagators));
builder.buildAndRegisterGlobal();
}
diff --git a/extensions/opentelemetry/opentelemetry/runtime/src/main/java/io/quarkus/opentelemetry/runtime/OpenTelemetryUtil.java b/extensions/opentelemetry/opentelemetry/runtime/src/main/java/io/quarkus/opentelemetry/runtime/OpenTelemetryUtil.java
new file mode 100644
index 0000000000000..31d572715adce
--- /dev/null
+++ b/extensions/opentelemetry/opentelemetry/runtime/src/main/java/io/quarkus/opentelemetry/runtime/OpenTelemetryUtil.java
@@ -0,0 +1,51 @@
+package io.quarkus.opentelemetry.runtime;
+
+import java.util.List;
+import java.util.Map;
+import java.util.ServiceLoader;
+import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.stream.StreamSupport;
+
+import io.opentelemetry.api.baggage.propagation.W3CBaggagePropagator;
+import io.opentelemetry.api.trace.propagation.W3CTraceContextPropagator;
+import io.opentelemetry.context.propagation.ContextPropagators;
+import io.opentelemetry.context.propagation.TextMapPropagator;
+import io.opentelemetry.sdk.autoconfigure.spi.ConfigurablePropagatorProvider;
+
+public final class OpenTelemetryUtil {
+ private OpenTelemetryUtil() {
+ }
+
+ private static TextMapPropagator getPropagator(
+ String name, Map spiPropagators) {
+ if ("tracecontext".equals(name)) {
+ return W3CTraceContextPropagator.getInstance();
+ }
+ if ("baggage".equals(name)) {
+ return W3CBaggagePropagator.getInstance();
+ }
+
+ TextMapPropagator spiPropagator = spiPropagators.get(name);
+ if (spiPropagator != null) {
+ return spiPropagator;
+ }
+ throw new IllegalArgumentException(
+ "Unrecognized value for propagator: " + name
+ + ". Make sure the artifact including the propagator is on the classpath.");
+ }
+
+ public static ContextPropagators mapPropagators(List propagators) {
+ Map spiPropagators = StreamSupport.stream(
+ ServiceLoader.load(ConfigurablePropagatorProvider.class).spliterator(), false)
+ .collect(
+ Collectors.toMap(ConfigurablePropagatorProvider::getName,
+ ConfigurablePropagatorProvider::getPropagator));
+
+ Set selectedPropagators = propagators.stream()
+ .map(propagator -> getPropagator(propagator.trim(), spiPropagators))
+ .collect(Collectors.toSet());
+
+ return ContextPropagators.create(TextMapPropagator.composite(selectedPropagators));
+ }
+}
diff --git a/extensions/opentelemetry/opentelemetry/runtime/src/main/java/io/quarkus/opentelemetry/runtime/graal/OpenTelemetrySdkAutoConfiguration.java b/extensions/opentelemetry/opentelemetry/runtime/src/main/java/io/quarkus/opentelemetry/runtime/graal/OpenTelemetrySdkAutoConfiguration.java
new file mode 100644
index 0000000000000..c12a42bb93d21
--- /dev/null
+++ b/extensions/opentelemetry/opentelemetry/runtime/src/main/java/io/quarkus/opentelemetry/runtime/graal/OpenTelemetrySdkAutoConfiguration.java
@@ -0,0 +1,20 @@
+package io.quarkus.opentelemetry.runtime.graal;
+
+import com.oracle.svm.core.annotate.Substitute;
+import com.oracle.svm.core.annotate.TargetClass;
+
+import io.opentelemetry.sdk.OpenTelemetrySdk;
+
+// We can remove this substitution once AutoConfigure SPI is a separate artifact
+@TargetClass(className = "io.opentelemetry.sdk.autoconfigure.OpenTelemetrySdkAutoConfiguration")
+@Substitute
+public final class OpenTelemetrySdkAutoConfiguration {
+ @Substitute
+ private OpenTelemetrySdkAutoConfiguration() {
+ }
+
+ @Substitute
+ public static OpenTelemetrySdk initialize() {
+ return null;
+ }
+}
diff --git a/extensions/opentelemetry/opentelemetry/runtime/src/main/java/io/quarkus/opentelemetry/runtime/tracing/DelayedAttributes.java b/extensions/opentelemetry/opentelemetry/runtime/src/main/java/io/quarkus/opentelemetry/runtime/tracing/DelayedAttributes.java
new file mode 100644
index 0000000000000..ba62e9275cad0
--- /dev/null
+++ b/extensions/opentelemetry/opentelemetry/runtime/src/main/java/io/quarkus/opentelemetry/runtime/tracing/DelayedAttributes.java
@@ -0,0 +1,96 @@
+package io.quarkus.opentelemetry.runtime.tracing;
+
+import java.util.Collections;
+import java.util.Map;
+import java.util.function.BiConsumer;
+
+import org.jboss.logging.Logger;
+
+import io.opentelemetry.api.common.AttributeKey;
+import io.opentelemetry.api.common.Attributes;
+import io.opentelemetry.api.common.AttributesBuilder;
+
+/**
+ * Class enabling Quarkus to instantiate a {@link io.opentelemetry.api.trace.TracerProvider}
+ * during static initialization and set a {@link Attributes} delegate during runtime initialization.
+ */
+public class DelayedAttributes implements Attributes {
+ private static final Logger log = Logger.getLogger(DelayedAttributes.class);
+ private boolean warningLogged = false;
+
+ private Attributes delegate;
+
+ /**
+ * Set the actual {@link Attributes} to use as the delegate.
+ *
+ * @param delegate Properly constructed {@link Attributes}.
+ */
+ public void setAttributesDelegate(Attributes delegate) {
+ this.delegate = delegate;
+ }
+
+ @Override
+ public T get(AttributeKey attributeKey) {
+ if (delegate == null) {
+ logDelegateNotFound();
+ return null;
+ }
+ return delegate.get(attributeKey);
+ }
+
+ @Override
+ public void forEach(BiConsumer super AttributeKey>, ? super Object> biConsumer) {
+ if (delegate == null) {
+ logDelegateNotFound();
+ return;
+ }
+ delegate.forEach(biConsumer);
+ }
+
+ @Override
+ public int size() {
+ if (delegate == null) {
+ logDelegateNotFound();
+ return 0;
+ }
+ return delegate.size();
+ }
+
+ @Override
+ public boolean isEmpty() {
+ if (delegate == null) {
+ logDelegateNotFound();
+ return true;
+ }
+ return delegate.isEmpty();
+ }
+
+ @Override
+ public Map, Object> asMap() {
+ if (delegate == null) {
+ logDelegateNotFound();
+ return Collections.emptyMap();
+ }
+ return delegate.asMap();
+ }
+
+ @Override
+ public AttributesBuilder toBuilder() {
+ if (delegate == null) {
+ logDelegateNotFound();
+ return Attributes.builder();
+ }
+ return delegate.toBuilder();
+ }
+
+ /**
+ * If we haven't previously logged an error,
+ * log an error about a missing {@code delegate} and set {@code warningLogged=true}
+ */
+ private void logDelegateNotFound() {
+ if (!warningLogged) {
+ log.warn("No Attributes delegate specified, no action taken.");
+ warningLogged = true;
+ }
+ }
+}
diff --git a/extensions/opentelemetry/opentelemetry/runtime/src/main/java/io/quarkus/opentelemetry/runtime/tracing/LateBoundSampler.java b/extensions/opentelemetry/opentelemetry/runtime/src/main/java/io/quarkus/opentelemetry/runtime/tracing/LateBoundSampler.java
new file mode 100644
index 0000000000000..a5068d7c39472
--- /dev/null
+++ b/extensions/opentelemetry/opentelemetry/runtime/src/main/java/io/quarkus/opentelemetry/runtime/tracing/LateBoundSampler.java
@@ -0,0 +1,67 @@
+package io.quarkus.opentelemetry.runtime.tracing;
+
+import java.util.List;
+
+import org.jboss.logging.Logger;
+
+import io.opentelemetry.api.common.Attributes;
+import io.opentelemetry.api.trace.SpanKind;
+import io.opentelemetry.context.Context;
+import io.opentelemetry.sdk.trace.data.LinkData;
+import io.opentelemetry.sdk.trace.samplers.Sampler;
+import io.opentelemetry.sdk.trace.samplers.SamplingDecision;
+import io.opentelemetry.sdk.trace.samplers.SamplingResult;
+
+/**
+ * Class enabling Quarkus to instantiate a {@link io.opentelemetry.api.trace.TracerProvider}
+ * during static initialization and set a {@link Sampler} delegate during runtime initialization.
+ */
+public class LateBoundSampler implements Sampler {
+ private static final Logger log = Logger.getLogger(LateBoundSampler.class);
+ private boolean warningLogged = false;
+
+ private Sampler delegate;
+
+ /**
+ * Set the actual {@link Sampler} to use as the delegate.
+ *
+ * @param delegate Properly constructed {@link Sampler}.
+ */
+ public void setSamplerDelegate(Sampler delegate) {
+ this.delegate = delegate;
+ }
+
+ @Override
+ public SamplingResult shouldSample(Context parentContext,
+ String traceId,
+ String name,
+ SpanKind spanKind,
+ Attributes attributes,
+ List parentLinks) {
+ if (delegate == null) {
+ logDelegateNotFound();
+ return SamplingResult.create(SamplingDecision.RECORD_AND_SAMPLE);
+ }
+ return delegate.shouldSample(parentContext, traceId, name, spanKind, attributes, parentLinks);
+ }
+
+ @Override
+ public String getDescription() {
+ if (delegate == null) {
+ logDelegateNotFound();
+ return "";
+ }
+ return delegate.getDescription();
+ }
+
+ /**
+ * If we haven't previously logged an error,
+ * log an error about a missing {@code delegate} and set {@code warningLogged=true}
+ */
+ private void logDelegateNotFound() {
+ if (!warningLogged) {
+ log.warn("No Sampler delegate specified, no action taken.");
+ warningLogged = true;
+ }
+ }
+}
diff --git a/extensions/opentelemetry/opentelemetry/runtime/src/main/java/io/quarkus/opentelemetry/runtime/tracing/TracerConfig.java b/extensions/opentelemetry/opentelemetry/runtime/src/main/java/io/quarkus/opentelemetry/runtime/tracing/TracerConfig.java
index 05f34bb968f46..acf791f2f15bf 100644
--- a/extensions/opentelemetry/opentelemetry/runtime/src/main/java/io/quarkus/opentelemetry/runtime/tracing/TracerConfig.java
+++ b/extensions/opentelemetry/opentelemetry/runtime/src/main/java/io/quarkus/opentelemetry/runtime/tracing/TracerConfig.java
@@ -1,5 +1,6 @@
package io.quarkus.opentelemetry.runtime.tracing;
+import java.util.List;
import java.util.Optional;
import io.quarkus.runtime.annotations.ConfigGroup;
@@ -19,6 +20,16 @@ public class TracerConfig {
/** Build / static runtime config for span exporters */
public SpanExporterConfig exporter;
+ /**
+ * Comma separated list of resources that represents the entity that is
+ * producing telemetry.
+ *
+ * Valid values are {@code beanstalk, ec2, ecs, eks, host, lambda, os,
+ * process, processruntime}.
+ */
+ @ConfigItem
+ public Optional> resources;
+
/** Build / static runtime config for span exporters */
@ConfigGroup
public static class SpanExporterConfig {
diff --git a/extensions/opentelemetry/opentelemetry/runtime/src/main/java/io/quarkus/opentelemetry/runtime/tracing/TracerProducer.java b/extensions/opentelemetry/opentelemetry/runtime/src/main/java/io/quarkus/opentelemetry/runtime/tracing/TracerProducer.java
index a2c8126796462..4b4d0c85d9921 100644
--- a/extensions/opentelemetry/opentelemetry/runtime/src/main/java/io/quarkus/opentelemetry/runtime/tracing/TracerProducer.java
+++ b/extensions/opentelemetry/opentelemetry/runtime/src/main/java/io/quarkus/opentelemetry/runtime/tracing/TracerProducer.java
@@ -9,6 +9,18 @@
@Singleton
public class TracerProducer {
+ @Produces
+ @Singleton
+ public DelayedAttributes getDelayedAttributes() {
+ return new DelayedAttributes();
+ }
+
+ @Produces
+ @Singleton
+ public LateBoundSampler getLateBoundSampler() {
+ return new LateBoundSampler();
+ }
+
@Produces
@Singleton
@DefaultBean
diff --git a/extensions/opentelemetry/opentelemetry/runtime/src/main/java/io/quarkus/opentelemetry/runtime/tracing/TracerRecorder.java b/extensions/opentelemetry/opentelemetry/runtime/src/main/java/io/quarkus/opentelemetry/runtime/tracing/TracerRecorder.java
index 673296ab0ffa6..a04809de2f634 100644
--- a/extensions/opentelemetry/opentelemetry/runtime/src/main/java/io/quarkus/opentelemetry/runtime/tracing/TracerRecorder.java
+++ b/extensions/opentelemetry/opentelemetry/runtime/src/main/java/io/quarkus/opentelemetry/runtime/tracing/TracerRecorder.java
@@ -1,18 +1,22 @@
package io.quarkus.opentelemetry.runtime.tracing;
+import java.util.Optional;
import java.util.function.Consumer;
import javax.enterprise.inject.Any;
import javax.enterprise.inject.Instance;
import javax.enterprise.inject.spi.BeanManager;
+import javax.enterprise.inject.spi.CDI;
import io.opentelemetry.api.common.Attributes;
import io.opentelemetry.sdk.resources.Resource;
+import io.opentelemetry.sdk.trace.IdGenerator;
import io.opentelemetry.sdk.trace.SdkTracerProvider;
import io.opentelemetry.sdk.trace.SdkTracerProviderBuilder;
import io.opentelemetry.sdk.trace.SpanProcessor;
import io.opentelemetry.sdk.trace.export.SimpleSpanProcessor;
import io.opentelemetry.sdk.trace.export.SpanExporter;
+import io.opentelemetry.sdk.trace.samplers.Sampler;
import io.opentelemetry.semconv.resource.attributes.ResourceAttributes;
import io.quarkus.arc.Arc;
import io.quarkus.opentelemetry.runtime.tracing.vertx.VertxTracingAdapter;
@@ -31,19 +35,40 @@ public Consumer setVertxTracingOptions() {
}
/* STATIC INIT */
- public RuntimeValue createTracerProvider(String serviceName, String serviceVersion,
+ public RuntimeValue createTracerProvider(TracerConfig config,
+ String serviceName,
+ String serviceVersion,
ShutdownContext shutdownContext) {
BeanManager beanManager = Arc.container().beanManager();
+
+ Instance idGenerator = beanManager.createInstance()
+ .select(IdGenerator.class, Any.Literal.INSTANCE);
+
SdkTracerProviderBuilder builder = SdkTracerProvider.builder();
+ // Define ID Generator if present
+ if (idGenerator.isResolvable()) {
+ builder.setIdGenerator(idGenerator.get());
+ }
+
+ DelayedAttributes delayedAttributes = beanManager.createInstance()
+ .select(DelayedAttributes.class, Any.Literal.INSTANCE).get();
+
+ delayedAttributes.setAttributesDelegate(Resource.getDefault()
+ .merge(Resource.create(
+ Attributes.of(
+ ResourceAttributes.SERVICE_NAME, serviceName,
+ ResourceAttributes.SERVICE_VERSION, serviceVersion)))
+ .getAttributes());
+
// Define Service Resource
- builder.setResource(
- Resource.getDefault()
- .merge(
- Resource.create(
- Attributes.of(
- ResourceAttributes.SERVICE_NAME, serviceName,
- ResourceAttributes.SERVICE_VERSION, serviceVersion))));
+ builder.setResource(Resource.create(delayedAttributes));
+
+ LateBoundSampler lateBoundSampler = beanManager.createInstance()
+ .select(LateBoundSampler.class, Any.Literal.INSTANCE).get();
+
+ // Set LateBoundSampler
+ builder.setSampler(lateBoundSampler);
// Find all SpanExporter instances
Instance allExporters = beanManager.createInstance()
@@ -70,4 +95,49 @@ public RuntimeValue createTracerProvider(String serviceName,
public void setupVertxTracer() {
vertxTracingAdapter.init();
}
+
+ /* RUNTIME INIT */
+ public void setupResources(TracerRuntimeConfig config) {
+ // Find all Resource instances
+ Instance allResources = CDI.current()
+ .getBeanManager()
+ .createInstance()
+ .select(Resource.class, Any.Literal.INSTANCE);
+
+ // Merge resource instances with env attributes
+ Resource resource = allResources.stream()
+ .reduce(Resource.empty(), Resource::merge)
+ .merge(config.resourceAttributes
+ .map(TracerUtil::mapResourceAttributes)
+ .orElseGet(Resource::empty));
+
+ // Update Delayed attributes to contain new runtime attributes if necessary
+ if (resource.getAttributes().size() > 0) {
+ DelayedAttributes delayedAttributes = CDI.current()
+ .select(DelayedAttributes.class).get();
+
+ delayedAttributes.setAttributesDelegate(
+ delayedAttributes.toBuilder()
+ .putAll(resource.getAttributes())
+ .build());
+ }
+ }
+
+ /* RUNTIME INIT */
+ public void setupSampler(TracerRuntimeConfig config) {
+ LateBoundSampler lateBoundSampler = CDI.current().select(LateBoundSampler.class, Any.Literal.INSTANCE).get();
+ Optional samplerBean = CDI.current()
+ .select(Sampler.class, Any.Literal.INSTANCE)
+ .stream()
+ .filter(o -> !(o instanceof LateBoundSampler))
+ .findFirst();
+
+ // Define Sampler using bean if present
+ if (samplerBean.isPresent()) {
+ lateBoundSampler.setSamplerDelegate(samplerBean.get());
+ } else {
+ // Define Sampler using config
+ lateBoundSampler.setSamplerDelegate(TracerUtil.mapSampler(config.sampler));
+ }
+ }
}
diff --git a/extensions/opentelemetry/opentelemetry/runtime/src/main/java/io/quarkus/opentelemetry/runtime/tracing/TracerRuntimeConfig.java b/extensions/opentelemetry/opentelemetry/runtime/src/main/java/io/quarkus/opentelemetry/runtime/tracing/TracerRuntimeConfig.java
new file mode 100644
index 0000000000000..17b484688c6e6
--- /dev/null
+++ b/extensions/opentelemetry/opentelemetry/runtime/src/main/java/io/quarkus/opentelemetry/runtime/tracing/TracerRuntimeConfig.java
@@ -0,0 +1,54 @@
+package io.quarkus.opentelemetry.runtime.tracing;
+
+import java.util.List;
+import java.util.Optional;
+
+import io.quarkus.runtime.annotations.ConfigGroup;
+import io.quarkus.runtime.annotations.ConfigItem;
+import io.quarkus.runtime.annotations.ConfigPhase;
+import io.quarkus.runtime.annotations.ConfigRoot;
+
+@ConfigRoot(name = "opentelemetry.tracer", phase = ConfigPhase.RUN_TIME)
+public class TracerRuntimeConfig {
+
+ /**
+ * A comma separated list of name=value resource attributes that
+ * represents the entity producing telemetry
+ * (eg. {@code service.name=authservice}).
+ */
+ @ConfigItem
+ Optional> resourceAttributes;
+
+ /** Config for sampler */
+ public SamplerConfig sampler;
+
+ @ConfigGroup
+ public static class SamplerConfig {
+ /**
+ * The sampler to use for tracing
+ *
+ * Valid values are {@code off, on, ratio}.
+ *
+ * Defaults to {@code on}.
+ */
+ @ConfigItem(name = ConfigItem.PARENT, defaultValue = "on")
+ public String samplerName;
+
+ /**
+ * The sampler ratio to use for tracing
+ *
+ * Only supported by the {@code ratio} sampler.
+ */
+ public Optional ratio;
+
+ /**
+ * If the sampler to use for tracing is parent based
+ *
+ * Valid values are {@code true, false}.
+ *
+ * Defaults to {@code true}.
+ */
+ @ConfigItem(defaultValue = "true")
+ public Boolean parentBased;
+ }
+}
diff --git a/extensions/opentelemetry/opentelemetry/runtime/src/main/java/io/quarkus/opentelemetry/runtime/tracing/TracerUtil.java b/extensions/opentelemetry/opentelemetry/runtime/src/main/java/io/quarkus/opentelemetry/runtime/tracing/TracerUtil.java
new file mode 100644
index 0000000000000..a637db71a3fd4
--- /dev/null
+++ b/extensions/opentelemetry/opentelemetry/runtime/src/main/java/io/quarkus/opentelemetry/runtime/tracing/TracerUtil.java
@@ -0,0 +1,53 @@
+package io.quarkus.opentelemetry.runtime.tracing;
+
+import java.util.AbstractMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.stream.Collectors;
+
+import io.opentelemetry.api.common.Attributes;
+import io.opentelemetry.api.common.AttributesBuilder;
+import io.opentelemetry.sdk.resources.Resource;
+import io.opentelemetry.sdk.trace.samplers.Sampler;
+
+public class TracerUtil {
+ private TracerUtil() {
+ }
+
+ public static Resource mapResourceAttributes(List resourceAttributes) {
+ AttributesBuilder attributesBuilder = Attributes.builder();
+
+ resourceAttributes.stream()
+ .map(keyValuePair -> keyValuePair.split("=", 2))
+ .map(keyValuePair -> new AbstractMap.SimpleImmutableEntry<>(keyValuePair[0].trim(), keyValuePair[1].trim()))
+ .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (first, next) -> next, LinkedHashMap::new))
+ .forEach(attributesBuilder::put);
+
+ return Resource.create(attributesBuilder.build());
+ }
+
+ private static Sampler getBaseSampler(String samplerName, Optional ratio) {
+ switch (samplerName) {
+ case "on":
+ return Sampler.alwaysOn();
+ case "off":
+ return Sampler.alwaysOff();
+ case "ratio":
+ return Sampler.traceIdRatioBased(ratio.orElse(1.0d));
+ default:
+ throw new IllegalArgumentException("Unrecognized value for sampler: " + samplerName);
+ }
+ }
+
+ public static Sampler mapSampler(TracerRuntimeConfig.SamplerConfig samplerConfig) {
+ Sampler sampler = getBaseSampler(samplerConfig.samplerName, samplerConfig.ratio);
+
+ if (samplerConfig.parentBased) {
+ return Sampler.parentBased(sampler);
+ }
+
+ return sampler;
+ }
+}