Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
buildSrc/build.gradle.kts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts
index 8fe99cd4f7e..63d43ef97d2 100644
--- a/buildSrc/build.gradle.kts
+++ b/buildSrc/build.gradle.kts
@@ -25,7 +25,7 @@ dependencies {
implementation("me.champeau.gradle:japicmp-gradle-plugin:0.4.1")
implementation("me.champeau.jmh:jmh-gradle-plugin:0.6.8")
implementation("net.ltgt.gradle:gradle-errorprone-plugin:3.0.1")
- implementation("net.ltgt.gradle:gradle-nullaway-plugin:1.4.0")
+ implementation("net.ltgt.gradle:gradle-nullaway-plugin:1.5.0")
implementation("ru.vyarus:gradle-animalsniffer-plugin:1.6.0")
}
From f8a4d81e2415f7052543f32f5b2a6a8bc33cf0ed Mon Sep 17 00:00:00 2001
From: jack-berg <34418638+jack-berg@users.noreply.github.com>
Date: Tue, 8 Nov 2022 17:05:00 -0600
Subject: [PATCH 12/68] Optimize log hot path (#4913)
* ComponentRegistry accepts name, version, schemaUrl instead of InstrumentationScopeInfo
* Fix comment
---
.../sdk/internal/ComponentRegistry.java | 94 ++++++++++++++++---
.../sdk/internal/ComponentRegistryTest.java | 93 +++++-------------
.../sdk/logs/SdkLoggerBuilder.java | 17 ++--
.../sdk/logs/SdkLoggerProvider.java | 14 ++-
.../sdk/metrics/SdkMeterBuilder.java | 17 ++--
.../sdk/trace/SdkTracerBuilder.java | 17 ++--
6 files changed, 143 insertions(+), 109 deletions(-)
diff --git a/sdk/common/src/main/java/io/opentelemetry/sdk/internal/ComponentRegistry.java b/sdk/common/src/main/java/io/opentelemetry/sdk/internal/ComponentRegistry.java
index 952451df410..93215cf2bf4 100644
--- a/sdk/common/src/main/java/io/opentelemetry/sdk/internal/ComponentRegistry.java
+++ b/sdk/common/src/main/java/io/opentelemetry/sdk/internal/ComponentRegistry.java
@@ -5,18 +5,32 @@
package io.opentelemetry.sdk.internal;
+import io.opentelemetry.api.common.Attributes;
import io.opentelemetry.sdk.common.InstrumentationScopeInfo;
-import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
+import java.util.IdentityHashMap;
+import java.util.Map;
+import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
import java.util.function.Function;
+import javax.annotation.Nullable;
/**
* Component (tracer, meter, etc) registry class for all the provider classes (TracerProvider,
* MeterProvider, etc.).
*
+ * Components are identified by name, version, and schema. Name is required, but version and
+ * schema are optional. Therefore, we have 4 possible scenarios for component keys:
+ *
+ *
+ * - Only name is provided, represented by {@link #componentByName}
+ *
- Name and version are provided, represented by {@link #componentByNameAndVersion}
+ *
- Name and schema are provided, represented by {@link #componentByNameAndSchema}
+ *
- Name, version and schema are provided, represented by {@link
+ * #componentByNameVersionAndSchema}
+ *
+ *
* This class is internal and is hence not for public use. Its APIs are unstable and can change
* at any time.
*
@@ -24,7 +38,14 @@
*/
public final class ComponentRegistry {
- private final ConcurrentMap registry = new ConcurrentHashMap<>();
+ private final Map componentByName = new ConcurrentHashMap<>();
+ private final Map> componentByNameAndVersion = new ConcurrentHashMap<>();
+ private final Map> componentByNameAndSchema = new ConcurrentHashMap<>();
+ private final Map>> componentByNameVersionAndSchema =
+ new ConcurrentHashMap<>();
+
+ private final Set allComponents = Collections.newSetFromMap(new IdentityHashMap<>());
+
private final Function factory;
public ComponentRegistry(Function factory) {
@@ -32,19 +53,64 @@ public ComponentRegistry(Function factory) {
}
/**
- * Returns the registered value associated with this {@link InstrumentationScopeInfo scope} if
- * any, otherwise creates a new instance and associates it with the given scope.
+ * Returns the component associated with the {@code name}, {@code version}, and {@code schemaUrl}.
+ * {@link Attributes} are not part of component identity. Behavior is undefined when different
+ * {@link Attributes} are provided where {@code name}, {@code version}, and {@code schemaUrl} are
+ * identical.
*/
- public V get(InstrumentationScopeInfo instrumentationScopeInfo) {
- // Optimistic lookup, before creating the new component.
- V component = registry.get(instrumentationScopeInfo);
- if (component != null) {
- return component;
+ public V get(
+ String name, @Nullable String version, @Nullable String schemaUrl, Attributes attributes) {
+ if (version != null && schemaUrl != null) {
+ Map> componentByVersionAndSchema =
+ componentByNameVersionAndSchema.computeIfAbsent(
+ name, unused -> new ConcurrentHashMap<>());
+ Map componentBySchema =
+ componentByVersionAndSchema.computeIfAbsent(version, unused -> new ConcurrentHashMap<>());
+ return componentBySchema.computeIfAbsent(
+ schemaUrl,
+ schemaUrl1 ->
+ buildComponent(
+ InstrumentationScopeInfo.builder(name)
+ .setVersion(version)
+ .setSchemaUrl(schemaUrl1)
+ .setAttributes(attributes)
+ .build()));
+ } else if (version != null) { // schemaUrl == null
+ Map componentByVersion =
+ componentByNameAndVersion.computeIfAbsent(name, unused -> new ConcurrentHashMap<>());
+ return componentByVersion.computeIfAbsent(
+ version,
+ version1 ->
+ buildComponent(
+ InstrumentationScopeInfo.builder(name)
+ .setVersion(version1)
+ .setAttributes(attributes)
+ .build()));
+ }
+ if (schemaUrl != null) { // version == null
+ Map componentBySchema =
+ componentByNameAndSchema.computeIfAbsent(name, unused -> new ConcurrentHashMap<>());
+ return componentBySchema.computeIfAbsent(
+ schemaUrl,
+ schemaUrl1 ->
+ buildComponent(
+ InstrumentationScopeInfo.builder(name)
+ .setSchemaUrl(schemaUrl1)
+ .setAttributes(attributes)
+ .build()));
+ } else { // schemaUrl == null && version == null
+ return componentByName.computeIfAbsent(
+ name,
+ name1 ->
+ buildComponent(
+ InstrumentationScopeInfo.builder(name1).setAttributes(attributes).build()));
}
+ }
- V newComponent = factory.apply(instrumentationScopeInfo);
- V oldComponent = registry.putIfAbsent(instrumentationScopeInfo, newComponent);
- return oldComponent != null ? oldComponent : newComponent;
+ private V buildComponent(InstrumentationScopeInfo instrumentationScopeInfo) {
+ V component = factory.apply(instrumentationScopeInfo);
+ allComponents.add(component);
+ return component;
}
/**
@@ -53,6 +119,6 @@ public V get(InstrumentationScopeInfo instrumentationScopeInfo) {
* @return a {@code Collection} view of the registered components.
*/
public Collection getComponents() {
- return Collections.unmodifiableCollection(new ArrayList<>(registry.values()));
+ return Collections.unmodifiableCollection(allComponents);
}
}
diff --git a/sdk/common/src/test/java/io/opentelemetry/sdk/internal/ComponentRegistryTest.java b/sdk/common/src/test/java/io/opentelemetry/sdk/internal/ComponentRegistryTest.java
index db52d7c71d1..1e566b28972 100644
--- a/sdk/common/src/test/java/io/opentelemetry/sdk/internal/ComponentRegistryTest.java
+++ b/sdk/common/src/test/java/io/opentelemetry/sdk/internal/ComponentRegistryTest.java
@@ -8,7 +8,6 @@
import static org.assertj.core.api.Assertions.assertThat;
import io.opentelemetry.api.common.Attributes;
-import io.opentelemetry.sdk.common.InstrumentationScopeInfo;
import org.junit.jupiter.api.Test;
class ComponentRegistryTest {
@@ -22,83 +21,35 @@ class ComponentRegistryTest {
@Test
void get_SameInstance() {
- assertThat(registry.get(InstrumentationScopeInfo.builder(NAME).build()))
- .isSameAs(registry.get(InstrumentationScopeInfo.builder(NAME).build()));
- assertThat(registry.get(InstrumentationScopeInfo.builder(NAME).setVersion(VERSION).build()))
- .isSameAs(registry.get(InstrumentationScopeInfo.builder(NAME).setVersion(VERSION).build()));
- assertThat(
- registry.get(InstrumentationScopeInfo.builder(NAME).setSchemaUrl(SCHEMA_URL).build()))
+ assertThat(registry.get(NAME, null, null, Attributes.empty()))
+ .isSameAs(registry.get(NAME, null, null, Attributes.empty()))
+ .isSameAs(registry.get(NAME, null, null, Attributes.builder().put("k1", "v2").build()));
+
+ assertThat(registry.get(NAME, VERSION, null, Attributes.empty()))
+ .isSameAs(registry.get(NAME, VERSION, null, Attributes.empty()))
+ .isSameAs(registry.get(NAME, VERSION, null, Attributes.builder().put("k1", "v2").build()));
+ assertThat(registry.get(NAME, null, SCHEMA_URL, Attributes.empty()))
+ .isSameAs(registry.get(NAME, null, SCHEMA_URL, Attributes.empty()))
.isSameAs(
- registry.get(InstrumentationScopeInfo.builder(NAME).setSchemaUrl(SCHEMA_URL).build()));
- assertThat(
- registry.get(InstrumentationScopeInfo.builder(NAME).setAttributes(ATTRIBUTES).build()))
+ registry.get(NAME, null, SCHEMA_URL, Attributes.builder().put("k1", "v2").build()));
+ assertThat(registry.get(NAME, VERSION, SCHEMA_URL, Attributes.empty()))
+ .isSameAs(registry.get(NAME, VERSION, SCHEMA_URL, Attributes.empty()))
.isSameAs(
- registry.get(InstrumentationScopeInfo.builder(NAME).setAttributes(ATTRIBUTES).build()));
- assertThat(
- registry.get(
- InstrumentationScopeInfo.builder(NAME)
- .setVersion(VERSION)
- .setSchemaUrl(SCHEMA_URL)
- .setAttributes(ATTRIBUTES)
- .build()))
- .isSameAs(
- registry.get(
- InstrumentationScopeInfo.builder(NAME)
- .setVersion(VERSION)
- .setSchemaUrl(SCHEMA_URL)
- .setAttributes(ATTRIBUTES)
- .build()));
+ registry.get(NAME, VERSION, SCHEMA_URL, Attributes.builder().put("k1", "v2").build()));
}
@Test
void get_DifferentInstance() {
- InstrumentationScopeInfo allFields =
- InstrumentationScopeInfo.builder(NAME)
- .setVersion(VERSION)
- .setSchemaUrl(SCHEMA_URL)
- .setAttributes(ATTRIBUTES)
- .build();
+ assertThat(registry.get(NAME, VERSION, SCHEMA_URL, ATTRIBUTES))
+ .isNotSameAs(registry.get(NAME + "_1", VERSION, SCHEMA_URL, ATTRIBUTES))
+ .isNotSameAs(registry.get(NAME, VERSION + "_1", SCHEMA_URL, ATTRIBUTES))
+ .isNotSameAs(registry.get(NAME, VERSION, SCHEMA_URL + "_1", ATTRIBUTES));
+
+ assertThat(registry.get(NAME, VERSION, null, Attributes.empty()))
+ .isNotSameAs(registry.get(NAME, null, null, Attributes.empty()));
- assertThat(registry.get(allFields))
- .isNotSameAs(
- registry.get(
- InstrumentationScopeInfo.builder(NAME + "_1")
- .setVersion(VERSION)
- .setSchemaUrl(SCHEMA_URL)
- .setAttributes(ATTRIBUTES)
- .build()));
- assertThat(registry.get(allFields))
- .isNotSameAs(
- registry.get(
- InstrumentationScopeInfo.builder(NAME)
- .setVersion(VERSION + "_1")
- .setSchemaUrl(SCHEMA_URL)
- .setAttributes(ATTRIBUTES)
- .build()));
- assertThat(registry.get(allFields))
- .isNotSameAs(
- registry.get(
- InstrumentationScopeInfo.builder(NAME)
- .setVersion(VERSION)
- .setSchemaUrl(SCHEMA_URL + "_1")
- .setAttributes(ATTRIBUTES)
- .build()));
- assertThat(registry.get(allFields))
- .isNotSameAs(
- registry.get(
- InstrumentationScopeInfo.builder(NAME)
- .setVersion(VERSION)
- .setSchemaUrl(SCHEMA_URL)
- .setAttributes(Attributes.builder().put("k1", "v2").build())
- .build()));
- assertThat(registry.get(InstrumentationScopeInfo.builder(NAME).setVersion(VERSION).build()))
- .isNotSameAs(registry.get(InstrumentationScopeInfo.builder(NAME).build()));
- assertThat(
- registry.get(InstrumentationScopeInfo.builder(NAME).setSchemaUrl(SCHEMA_URL).build()))
- .isNotSameAs(registry.get(InstrumentationScopeInfo.builder(NAME).build()));
- assertThat(
- registry.get(InstrumentationScopeInfo.builder(NAME).setAttributes(ATTRIBUTES).build()))
- .isNotSameAs(registry.get(InstrumentationScopeInfo.builder(NAME).build()));
+ assertThat(registry.get(NAME, null, SCHEMA_URL, Attributes.empty()))
+ .isNotSameAs(registry.get(NAME, null, null, Attributes.empty()));
}
private static final class TestComponent {}
diff --git a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/SdkLoggerBuilder.java b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/SdkLoggerBuilder.java
index 8d3eeaeb7c1..d497e25f7cd 100644
--- a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/SdkLoggerBuilder.java
+++ b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/SdkLoggerBuilder.java
@@ -5,21 +5,22 @@
package io.opentelemetry.sdk.logs;
+import io.opentelemetry.api.common.Attributes;
import io.opentelemetry.api.logs.LoggerBuilder;
-import io.opentelemetry.sdk.common.InstrumentationScopeInfo;
-import io.opentelemetry.sdk.common.InstrumentationScopeInfoBuilder;
import io.opentelemetry.sdk.internal.ComponentRegistry;
import javax.annotation.Nullable;
final class SdkLoggerBuilder implements LoggerBuilder {
private final ComponentRegistry registry;
- private final InstrumentationScopeInfoBuilder scopeBuilder;
+ private final String instrumentationScopeName;
+ @Nullable private String instrumentationScopeVersion;
+ @Nullable private String schemaUrl;
@Nullable private String eventDomain;
SdkLoggerBuilder(ComponentRegistry registry, String instrumentationScopeName) {
this.registry = registry;
- this.scopeBuilder = InstrumentationScopeInfo.builder(instrumentationScopeName);
+ this.instrumentationScopeName = instrumentationScopeName;
}
@Override
@@ -30,19 +31,21 @@ public LoggerBuilder setEventDomain(String eventDomain) {
@Override
public SdkLoggerBuilder setSchemaUrl(String schemaUrl) {
- scopeBuilder.setSchemaUrl(schemaUrl);
+ this.schemaUrl = schemaUrl;
return this;
}
@Override
public SdkLoggerBuilder setInstrumentationVersion(String instrumentationScopeVersion) {
- scopeBuilder.setVersion(instrumentationScopeVersion);
+ this.instrumentationScopeVersion = instrumentationScopeVersion;
return this;
}
@Override
public SdkLogger build() {
- SdkLogger logger = registry.get(scopeBuilder.build());
+ SdkLogger logger =
+ registry.get(
+ instrumentationScopeName, instrumentationScopeVersion, schemaUrl, Attributes.empty());
return eventDomain == null ? logger : logger.withEventDomain(eventDomain);
}
}
diff --git a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/SdkLoggerProvider.java b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/SdkLoggerProvider.java
index e64190d4d94..478700742d6 100644
--- a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/SdkLoggerProvider.java
+++ b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/SdkLoggerProvider.java
@@ -5,6 +5,7 @@
package io.opentelemetry.sdk.logs;
+import io.opentelemetry.api.common.Attributes;
import io.opentelemetry.api.logs.Logger;
import io.opentelemetry.api.logs.LoggerBuilder;
import io.opentelemetry.api.logs.LoggerProvider;
@@ -17,6 +18,7 @@
import java.util.concurrent.TimeUnit;
import java.util.function.Supplier;
import java.util.logging.Level;
+import javax.annotation.Nullable;
/** SDK implementation for {@link LoggerProvider}. */
public final class SdkLoggerProvider implements LoggerProvider, Closeable {
@@ -61,7 +63,8 @@ public static SdkLoggerProviderBuilder builder() {
*/
@Override
public Logger get(String instrumentationScopeName) {
- return loggerBuilder(instrumentationScopeName).build();
+ return loggerComponentRegistry.get(
+ instrumentationNameOrDefault(instrumentationScopeName), null, null, Attributes.empty());
}
/**
@@ -75,11 +78,16 @@ public LoggerBuilder loggerBuilder(String instrumentationScopeName) {
if (isNoopLogRecordProcessor) {
return LoggerProvider.noop().loggerBuilder(instrumentationScopeName);
}
+ return new SdkLoggerBuilder(
+ loggerComponentRegistry, instrumentationNameOrDefault(instrumentationScopeName));
+ }
+
+ private static String instrumentationNameOrDefault(@Nullable String instrumentationScopeName) {
if (instrumentationScopeName == null || instrumentationScopeName.isEmpty()) {
LOGGER.fine("Logger requested without instrumentation scope name.");
- instrumentationScopeName = DEFAULT_LOGGER_NAME;
+ return DEFAULT_LOGGER_NAME;
}
- return new SdkLoggerBuilder(loggerComponentRegistry, instrumentationScopeName);
+ return instrumentationScopeName;
}
/**
diff --git a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/SdkMeterBuilder.java b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/SdkMeterBuilder.java
index 317b140c033..fde47070f29 100644
--- a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/SdkMeterBuilder.java
+++ b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/SdkMeterBuilder.java
@@ -5,36 +5,39 @@
package io.opentelemetry.sdk.metrics;
+import io.opentelemetry.api.common.Attributes;
import io.opentelemetry.api.metrics.Meter;
import io.opentelemetry.api.metrics.MeterBuilder;
-import io.opentelemetry.sdk.common.InstrumentationScopeInfo;
-import io.opentelemetry.sdk.common.InstrumentationScopeInfoBuilder;
import io.opentelemetry.sdk.internal.ComponentRegistry;
+import javax.annotation.Nullable;
class SdkMeterBuilder implements MeterBuilder {
private final ComponentRegistry registry;
- private final InstrumentationScopeInfoBuilder scopeBuilder;
+ private final String instrumentationScopeName;
+ @Nullable private String instrumentationScopeVersion;
+ @Nullable private String schemaUrl;
SdkMeterBuilder(ComponentRegistry registry, String instrumentationScopeName) {
this.registry = registry;
- this.scopeBuilder = InstrumentationScopeInfo.builder(instrumentationScopeName);
+ this.instrumentationScopeName = instrumentationScopeName;
}
@Override
public MeterBuilder setSchemaUrl(String schemaUrl) {
- scopeBuilder.setSchemaUrl(schemaUrl);
+ this.schemaUrl = schemaUrl;
return this;
}
@Override
public MeterBuilder setInstrumentationVersion(String instrumentationScopeVersion) {
- scopeBuilder.setVersion(instrumentationScopeVersion);
+ this.instrumentationScopeVersion = instrumentationScopeVersion;
return this;
}
@Override
public Meter build() {
- return registry.get(scopeBuilder.build());
+ return registry.get(
+ instrumentationScopeName, instrumentationScopeVersion, schemaUrl, Attributes.empty());
}
}
diff --git a/sdk/trace/src/main/java/io/opentelemetry/sdk/trace/SdkTracerBuilder.java b/sdk/trace/src/main/java/io/opentelemetry/sdk/trace/SdkTracerBuilder.java
index 6e9e4db321a..6c6976a7d52 100644
--- a/sdk/trace/src/main/java/io/opentelemetry/sdk/trace/SdkTracerBuilder.java
+++ b/sdk/trace/src/main/java/io/opentelemetry/sdk/trace/SdkTracerBuilder.java
@@ -5,36 +5,39 @@
package io.opentelemetry.sdk.trace;
+import io.opentelemetry.api.common.Attributes;
import io.opentelemetry.api.trace.Tracer;
import io.opentelemetry.api.trace.TracerBuilder;
-import io.opentelemetry.sdk.common.InstrumentationScopeInfo;
-import io.opentelemetry.sdk.common.InstrumentationScopeInfoBuilder;
import io.opentelemetry.sdk.internal.ComponentRegistry;
+import javax.annotation.Nullable;
class SdkTracerBuilder implements TracerBuilder {
private final ComponentRegistry registry;
- private final InstrumentationScopeInfoBuilder scopeBuilder;
+ private final String instrumentationScopeName;
+ @Nullable private String instrumentationScopeVersion;
+ @Nullable private String schemaUrl;
SdkTracerBuilder(ComponentRegistry registry, String instrumentationScopeName) {
this.registry = registry;
- this.scopeBuilder = InstrumentationScopeInfo.builder(instrumentationScopeName);
+ this.instrumentationScopeName = instrumentationScopeName;
}
@Override
public TracerBuilder setSchemaUrl(String schemaUrl) {
- scopeBuilder.setSchemaUrl(schemaUrl);
+ this.schemaUrl = schemaUrl;
return this;
}
@Override
public TracerBuilder setInstrumentationVersion(String instrumentationScopeVersion) {
- scopeBuilder.setVersion(instrumentationScopeVersion);
+ this.instrumentationScopeVersion = instrumentationScopeVersion;
return this;
}
@Override
public Tracer build() {
- return registry.get(scopeBuilder.build());
+ return registry.get(
+ instrumentationScopeName, instrumentationScopeVersion, schemaUrl, Attributes.empty());
}
}
From 2e9deb480a0ac669989b7ffa8a66cda54fd3ff97 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Wed, 9 Nov 2022 09:20:14 -0800
Subject: [PATCH 13/68] Bump com.gradle.enterprise from 3.11.3 to 3.11.4
(#4928)
Bumps com.gradle.enterprise from 3.11.3 to 3.11.4.
---
updated-dependencies:
- dependency-name: com.gradle.enterprise
dependency-type: direct:production
update-type: version-update:semver-patch
...
Signed-off-by: dependabot[bot]
Signed-off-by: dependabot[bot]
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
settings.gradle.kts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/settings.gradle.kts b/settings.gradle.kts
index bbd7c950d30..aa92f6f6e1a 100644
--- a/settings.gradle.kts
+++ b/settings.gradle.kts
@@ -2,7 +2,7 @@ pluginManagement {
plugins {
id("com.github.ben-manes.versions") version "0.43.0"
id("com.github.johnrengelman.shadow") version "7.1.2"
- id("com.gradle.enterprise") version "3.11.3"
+ id("com.gradle.enterprise") version "3.11.4"
id("io.github.gradle-nexus.publish-plugin") version "1.1.0"
id("org.jetbrains.kotlin.jvm") version "1.7.20"
id("org.graalvm.buildtools.native") version "0.9.17"
From b60f4e20b8ac5c4251a3dfbfe242e5e221ebd4b1 Mon Sep 17 00:00:00 2001
From: jack-berg <34418638+jack-berg@users.noreply.github.com>
Date: Wed, 9 Nov 2022 11:59:06 -0600
Subject: [PATCH 14/68] Add context argument to LogRecordProcessor#onEmit
(#4889)
* Add context argument to LogRecordProcessor#onEmit
* Change argument order
---
.../sdk/logs/LogRecordProcessor.java | 5 +-
.../sdk/logs/MultiLogRecordProcessor.java | 5 +-
.../sdk/logs/NoopLogRecordProcessor.java | 4 +-
.../sdk/logs/SdkLogRecordBuilder.java | 9 ++--
.../sdk/logs/SdkLoggerProviderBuilder.java | 6 ++-
.../logs/export/BatchLogRecordProcessor.java | 3 +-
.../logs/export/SimpleLogRecordProcessor.java | 3 +-
.../sdk/logs/MultiLogRecordProcessorTest.java | 10 ++--
.../sdk/logs/NoopLogRecordProcessorTest.java | 3 +-
.../sdk/logs/SdkLogRecordBuilderTest.java | 3 +-
.../sdk/logs/SdkLoggerProviderTest.java | 52 ++++++++++++++++++-
.../opentelemetry/sdk/logs/SdkLoggerTest.java | 12 +++--
.../export/BatchLogRecordProcessorTest.java | 2 +-
.../export/SimpleLogRecordProcessorTest.java | 15 +++---
14 files changed, 99 insertions(+), 33 deletions(-)
diff --git a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogRecordProcessor.java b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogRecordProcessor.java
index 6dcdf279fc6..df46275ba58 100644
--- a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogRecordProcessor.java
+++ b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogRecordProcessor.java
@@ -7,6 +7,7 @@
import io.opentelemetry.api.logs.LogRecordBuilder;
import io.opentelemetry.api.logs.Logger;
+import io.opentelemetry.context.Context;
import io.opentelemetry.sdk.common.CompletableResultCode;
import java.io.Closeable;
import java.util.ArrayList;
@@ -51,9 +52,11 @@ static LogRecordProcessor composite(Iterable processors) {
/**
* Called when a {@link Logger} {@link LogRecordBuilder#emit()}s a log record.
*
+ * @param context the context set via {@link LogRecordBuilder#setContext(Context)}, or {@link
+ * Context#current()} if not explicitly set
* @param logRecord the log record
*/
- void onEmit(ReadWriteLogRecord logRecord);
+ void onEmit(Context context, ReadWriteLogRecord logRecord);
/**
* Shutdown the log processor.
diff --git a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/MultiLogRecordProcessor.java b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/MultiLogRecordProcessor.java
index 25fe6a5049d..e84b38c86b6 100644
--- a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/MultiLogRecordProcessor.java
+++ b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/MultiLogRecordProcessor.java
@@ -5,6 +5,7 @@
package io.opentelemetry.sdk.logs;
+import io.opentelemetry.context.Context;
import io.opentelemetry.sdk.common.CompletableResultCode;
import java.util.ArrayList;
import java.util.List;
@@ -33,9 +34,9 @@ static LogRecordProcessor create(List logRecordProcessorsLis
}
@Override
- public void onEmit(ReadWriteLogRecord logRecord) {
+ public void onEmit(Context context, ReadWriteLogRecord logRecord) {
for (LogRecordProcessor logRecordProcessor : logRecordProcessors) {
- logRecordProcessor.onEmit(logRecord);
+ logRecordProcessor.onEmit(context, logRecord);
}
}
diff --git a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/NoopLogRecordProcessor.java b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/NoopLogRecordProcessor.java
index 24af6885a69..518cdfa785a 100644
--- a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/NoopLogRecordProcessor.java
+++ b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/NoopLogRecordProcessor.java
@@ -5,6 +5,8 @@
package io.opentelemetry.sdk.logs;
+import io.opentelemetry.context.Context;
+
final class NoopLogRecordProcessor implements LogRecordProcessor {
private static final NoopLogRecordProcessor INSTANCE = new NoopLogRecordProcessor();
@@ -15,5 +17,5 @@ static LogRecordProcessor getInstance() {
private NoopLogRecordProcessor() {}
@Override
- public void onEmit(ReadWriteLogRecord logRecord) {}
+ public void onEmit(Context context, ReadWriteLogRecord logRecord) {}
}
diff --git a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/SdkLogRecordBuilder.java b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/SdkLogRecordBuilder.java
index 0c333cc6fc3..e1f159aff3d 100644
--- a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/SdkLogRecordBuilder.java
+++ b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/SdkLogRecordBuilder.java
@@ -10,7 +10,6 @@
import io.opentelemetry.api.logs.LogRecordBuilder;
import io.opentelemetry.api.logs.Severity;
import io.opentelemetry.api.trace.Span;
-import io.opentelemetry.api.trace.SpanContext;
import io.opentelemetry.context.Context;
import io.opentelemetry.sdk.common.InstrumentationScopeInfo;
import io.opentelemetry.sdk.internal.AttributesMap;
@@ -27,7 +26,7 @@ final class SdkLogRecordBuilder implements EventBuilder {
private final InstrumentationScopeInfo instrumentationScopeInfo;
private long epochNanos;
- private SpanContext spanContext = SpanContext.getInvalid();
+ @Nullable private Context context;
private Severity severity = Severity.UNDEFINED_SEVERITY_NUMBER;
@Nullable private String severityText;
private Body body = Body.empty();
@@ -54,7 +53,7 @@ public SdkLogRecordBuilder setEpoch(Instant instant) {
@Override
public SdkLogRecordBuilder setContext(Context context) {
- this.spanContext = Span.fromContext(context).getSpanContext();
+ this.context = context;
return this;
}
@@ -95,15 +94,17 @@ public void emit() {
if (loggerSharedState.hasBeenShutdown()) {
return;
}
+ Context context = this.context == null ? Context.current() : this.context;
loggerSharedState
.getLogRecordProcessor()
.onEmit(
+ context,
SdkReadWriteLogRecord.create(
loggerSharedState.getLogLimits(),
loggerSharedState.getResource(),
instrumentationScopeInfo,
this.epochNanos == 0 ? this.loggerSharedState.getClock().now() : this.epochNanos,
- spanContext,
+ Span.fromContext(context).getSpanContext(),
severity,
severityText,
body,
diff --git a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/SdkLoggerProviderBuilder.java b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/SdkLoggerProviderBuilder.java
index 6f99640cf18..0b2ed52a753 100644
--- a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/SdkLoggerProviderBuilder.java
+++ b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/SdkLoggerProviderBuilder.java
@@ -9,6 +9,7 @@
import io.opentelemetry.api.logs.LogRecordBuilder;
import io.opentelemetry.api.logs.Logger;
+import io.opentelemetry.context.Context;
import io.opentelemetry.sdk.common.Clock;
import io.opentelemetry.sdk.logs.data.LogRecordData;
import io.opentelemetry.sdk.resources.Resource;
@@ -57,8 +58,9 @@ public SdkLoggerProviderBuilder setLogLimits(Supplier logLimitsSuppli
}
/**
- * Add a log processor. {@link LogRecordProcessor#onEmit(ReadWriteLogRecord)} will be called each
- * time a log is emitted by {@link Logger} instances obtained from the {@link SdkLoggerProvider}.
+ * Add a log processor. {@link LogRecordProcessor#onEmit(Context, ReadWriteLogRecord)} will be
+ * called each time a log is emitted by {@link Logger} instances obtained from the {@link
+ * SdkLoggerProvider}.
*
* @param processor the log processor
* @return this
diff --git a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/export/BatchLogRecordProcessor.java b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/export/BatchLogRecordProcessor.java
index 1c92cad0af5..f327b3b4acc 100644
--- a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/export/BatchLogRecordProcessor.java
+++ b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/export/BatchLogRecordProcessor.java
@@ -10,6 +10,7 @@
import io.opentelemetry.api.metrics.LongCounter;
import io.opentelemetry.api.metrics.Meter;
import io.opentelemetry.api.metrics.MeterProvider;
+import io.opentelemetry.context.Context;
import io.opentelemetry.sdk.common.CompletableResultCode;
import io.opentelemetry.sdk.internal.DaemonThreadFactory;
import io.opentelemetry.sdk.logs.LogRecordProcessor;
@@ -81,7 +82,7 @@ public static BatchLogRecordProcessorBuilder builder(LogRecordExporter logRecord
}
@Override
- public void onEmit(ReadWriteLogRecord logRecord) {
+ public void onEmit(Context context, ReadWriteLogRecord logRecord) {
if (logRecord == null) {
return;
}
diff --git a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/export/SimpleLogRecordProcessor.java b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/export/SimpleLogRecordProcessor.java
index b7703d4cde1..3bb510718aa 100644
--- a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/export/SimpleLogRecordProcessor.java
+++ b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/export/SimpleLogRecordProcessor.java
@@ -7,6 +7,7 @@
import static java.util.Objects.requireNonNull;
+import io.opentelemetry.context.Context;
import io.opentelemetry.sdk.common.CompletableResultCode;
import io.opentelemetry.sdk.logs.LogRecordProcessor;
import io.opentelemetry.sdk.logs.ReadWriteLogRecord;
@@ -58,7 +59,7 @@ public static LogRecordProcessor create(LogRecordExporter exporter) {
}
@Override
- public void onEmit(ReadWriteLogRecord logRecord) {
+ public void onEmit(Context context, ReadWriteLogRecord logRecord) {
try {
List logs = Collections.singletonList(logRecord.toLogRecordData());
CompletableResultCode result = logRecordExporter.export(logs);
diff --git a/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/MultiLogRecordProcessorTest.java b/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/MultiLogRecordProcessorTest.java
index 8a5a32e72b0..57aaa61fc32 100644
--- a/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/MultiLogRecordProcessorTest.java
+++ b/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/MultiLogRecordProcessorTest.java
@@ -10,6 +10,7 @@
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import io.opentelemetry.context.Context;
import io.opentelemetry.sdk.common.CompletableResultCode;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -39,7 +40,7 @@ void setup() {
void empty() {
LogRecordProcessor multiLogRecordProcessor = LogRecordProcessor.composite();
assertThat(multiLogRecordProcessor).isInstanceOf(NoopLogRecordProcessor.class);
- multiLogRecordProcessor.onEmit(logRecord);
+ multiLogRecordProcessor.onEmit(Context.current(), logRecord);
multiLogRecordProcessor.shutdown();
}
@@ -53,9 +54,10 @@ void oneLogRecordProcessor() {
void twoLogRecordProcessor() {
LogRecordProcessor multiLogRecordProcessor =
LogRecordProcessor.composite(logRecordProcessor1, logRecordProcessor2);
- multiLogRecordProcessor.onEmit(logRecord);
- verify(logRecordProcessor1).onEmit(same(logRecord));
- verify(logRecordProcessor2).onEmit(same(logRecord));
+ Context context = Context.current();
+ multiLogRecordProcessor.onEmit(context, logRecord);
+ verify(logRecordProcessor1).onEmit(same(context), same(logRecord));
+ verify(logRecordProcessor2).onEmit(same(context), same(logRecord));
multiLogRecordProcessor.forceFlush();
verify(logRecordProcessor1).forceFlush();
diff --git a/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/NoopLogRecordProcessorTest.java b/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/NoopLogRecordProcessorTest.java
index c80cb15cbcf..3a209e02041 100644
--- a/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/NoopLogRecordProcessorTest.java
+++ b/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/NoopLogRecordProcessorTest.java
@@ -7,6 +7,7 @@
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
+import io.opentelemetry.context.Context;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
@@ -20,7 +21,7 @@ class NoopLogRecordProcessorTest {
@Test
void noCrash() {
LogRecordProcessor logRecordProcessor = NoopLogRecordProcessor.getInstance();
- logRecordProcessor.onEmit(logRecord);
+ logRecordProcessor.onEmit(Context.current(), logRecord);
assertThat(logRecordProcessor.forceFlush().isSuccess()).isEqualTo(true);
assertThat(logRecordProcessor.shutdown().isSuccess()).isEqualTo(true);
}
diff --git a/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/SdkLogRecordBuilderTest.java b/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/SdkLogRecordBuilderTest.java
index 9775f2f4900..3f530d6057d 100644
--- a/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/SdkLogRecordBuilderTest.java
+++ b/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/SdkLogRecordBuilderTest.java
@@ -47,7 +47,8 @@ class SdkLogRecordBuilderTest {
@BeforeEach
void setup() {
when(loggerSharedState.getLogLimits()).thenReturn(LogLimits.getDefault());
- when(loggerSharedState.getLogRecordProcessor()).thenReturn(emittedLog::set);
+ when(loggerSharedState.getLogRecordProcessor())
+ .thenReturn((context, logRecord) -> emittedLog.set(logRecord));
when(loggerSharedState.getResource()).thenReturn(RESOURCE);
when(loggerSharedState.getClock()).thenReturn(Clock.getDefault());
diff --git a/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/SdkLoggerProviderTest.java b/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/SdkLoggerProviderTest.java
index 2eaf70bc32a..7408fdfc8dc 100644
--- a/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/SdkLoggerProviderTest.java
+++ b/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/SdkLoggerProviderTest.java
@@ -7,6 +7,7 @@
import static io.opentelemetry.sdk.testing.assertj.LogAssertions.assertThat;
import static org.assertj.core.api.Assertions.as;
+import static org.assertj.core.api.Assertions.entry;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
@@ -21,6 +22,8 @@
import io.opentelemetry.api.trace.TraceFlags;
import io.opentelemetry.api.trace.TraceState;
import io.opentelemetry.context.Context;
+import io.opentelemetry.context.ContextKey;
+import io.opentelemetry.context.Scope;
import io.opentelemetry.internal.testing.slf4j.SuppressLogger;
import io.opentelemetry.sdk.common.Clock;
import io.opentelemetry.sdk.common.CompletableResultCode;
@@ -29,6 +32,7 @@
import io.opentelemetry.sdk.resources.Resource;
import java.util.ArrayList;
import java.util.List;
+import java.util.Optional;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
import org.assertj.core.api.InstanceOfAssertFactories;
@@ -222,7 +226,7 @@ void loggerBuilder_WithLogRecordProcessor() {
SdkLoggerProvider.builder()
.setResource(resource)
.addLogRecordProcessor(
- logRecord -> {
+ (unused, logRecord) -> {
logRecord.setAttribute(null, null);
// Overwrite k1
logRecord.setAttribute(AttributeKey.stringKey("k1"), "new-v1");
@@ -262,6 +266,50 @@ void loggerBuilder_WithLogRecordProcessor() {
Attributes.builder().put("k1", "new-v1").put("k2", "v2").put("k3", "v3").build());
}
+ @Test
+ void loggerBuilder_ProcessorWithContext() {
+ ContextKey contextKey = ContextKey.named("my-context-key");
+ AtomicReference logRecordData = new AtomicReference<>();
+
+ sdkLoggerProvider =
+ SdkLoggerProvider.builder()
+ .addLogRecordProcessor(
+ (context, logRecord) ->
+ logRecord.setAttribute(
+ AttributeKey.stringKey("my-context-key"),
+ Optional.ofNullable(context.get(contextKey)).orElse("")))
+ .addLogRecordProcessor(
+ (unused, logRecord) -> logRecordData.set(logRecord.toLogRecordData()))
+ .build();
+
+ // With implicit context
+ try (Scope unused = Context.current().with(contextKey, "context-value1").makeCurrent()) {
+ sdkLoggerProvider
+ .loggerBuilder("test")
+ .build()
+ .logRecordBuilder()
+ .setBody("log message1")
+ .emit();
+ }
+ assertThat(logRecordData.get())
+ .hasBody("log message1")
+ .hasAttributes(entry(AttributeKey.stringKey("my-context-key"), "context-value1"));
+
+ // With explicit context
+ try (Scope unused = Context.current().with(contextKey, "context-value2").makeCurrent()) {
+ sdkLoggerProvider
+ .loggerBuilder("test")
+ .build()
+ .logRecordBuilder()
+ .setContext(Context.current())
+ .setBody("log message2")
+ .emit();
+ }
+ assertThat(logRecordData.get())
+ .hasBody("log message2")
+ .hasAttributes(entry(AttributeKey.stringKey("my-context-key"), "context-value2"));
+ }
+
@Test
void forceFlush() {
sdkLoggerProvider.forceFlush();
@@ -288,7 +336,7 @@ void canSetClock() {
Clock clock = mock(Clock.class);
when(clock.now()).thenReturn(now);
List seenLogs = new ArrayList<>();
- logRecordProcessor = seenLogs::add;
+ logRecordProcessor = (context, logRecord) -> seenLogs.add(logRecord);
sdkLoggerProvider =
SdkLoggerProvider.builder()
.setClock(clock)
diff --git a/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/SdkLoggerTest.java b/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/SdkLoggerTest.java
index b35b6b926a3..e96820132e4 100644
--- a/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/SdkLoggerTest.java
+++ b/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/SdkLoggerTest.java
@@ -46,7 +46,7 @@ void logRecordBuilder() {
LoggerSharedState state = mock(LoggerSharedState.class);
InstrumentationScopeInfo info = InstrumentationScopeInfo.create("foo");
AtomicReference seenLog = new AtomicReference<>();
- LogRecordProcessor logRecordProcessor = seenLog::set;
+ LogRecordProcessor logRecordProcessor = (context, logRecord) -> seenLog.set(logRecord);
Clock clock = mock(Clock.class);
when(clock.now()).thenReturn(5L);
@@ -69,7 +69,7 @@ void logRecordBuilder_maxAttributeLength() {
AtomicReference seenLog = new AtomicReference<>();
SdkLoggerProvider loggerProvider =
SdkLoggerProvider.builder()
- .addLogRecordProcessor(seenLog::set)
+ .addLogRecordProcessor((context, logRecord) -> seenLog.set(logRecord))
.setLogLimits(() -> LogLimits.builder().setMaxAttributeValueLength(maxLength).build())
.build();
LogRecordBuilder logRecordBuilder = loggerProvider.get("test").logRecordBuilder();
@@ -109,7 +109,7 @@ void logRecordBuilder_maxAttributes() {
AtomicReference seenLog = new AtomicReference<>();
SdkLoggerProvider loggerProvider =
SdkLoggerProvider.builder()
- .addLogRecordProcessor(seenLog::set)
+ .addLogRecordProcessor((context, logRecord) -> seenLog.set(logRecord))
.setLogLimits(
() -> LogLimits.builder().setMaxNumberOfAttributes(maxNumberOfAttrs).build())
.build();
@@ -140,7 +140,7 @@ void logRecordBuilder_AfterShutdown() {
loggerProvider.shutdown().join(10, TimeUnit.SECONDS);
loggerProvider.get("test").logRecordBuilder().emit();
- verify(logRecordProcessor, never()).onEmit(any());
+ verify(logRecordProcessor, never()).onEmit(any(), any());
}
@Test
@@ -148,7 +148,9 @@ void logRecordBuilder_AfterShutdown() {
void eventBuilder() {
AtomicReference seenLog = new AtomicReference<>();
SdkLoggerProvider loggerProvider =
- SdkLoggerProvider.builder().addLogRecordProcessor(seenLog::set).build();
+ SdkLoggerProvider.builder()
+ .addLogRecordProcessor((context, logRecord) -> seenLog.set(logRecord))
+ .build();
// Emit event from logger with name and add event domain
loggerProvider
diff --git a/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/export/BatchLogRecordProcessorTest.java b/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/export/BatchLogRecordProcessorTest.java
index 32cfecbed17..1039b7e34bc 100644
--- a/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/export/BatchLogRecordProcessorTest.java
+++ b/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/export/BatchLogRecordProcessorTest.java
@@ -291,7 +291,7 @@ void ignoresNullLogs() {
BatchLogRecordProcessor processor =
BatchLogRecordProcessor.builder(mockLogRecordExporter).build();
try {
- assertThatCode(() -> processor.onEmit(null)).doesNotThrowAnyException();
+ assertThatCode(() -> processor.onEmit(null, null)).doesNotThrowAnyException();
} finally {
processor.shutdown();
}
diff --git a/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/export/SimpleLogRecordProcessorTest.java b/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/export/SimpleLogRecordProcessorTest.java
index 3ce15654092..1550c68b3ef 100644
--- a/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/export/SimpleLogRecordProcessorTest.java
+++ b/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/export/SimpleLogRecordProcessorTest.java
@@ -15,6 +15,7 @@
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import io.opentelemetry.context.Context;
import io.opentelemetry.internal.testing.slf4j.SuppressLogger;
import io.opentelemetry.sdk.common.CompletableResultCode;
import io.opentelemetry.sdk.logs.LogRecordProcessor;
@@ -58,7 +59,7 @@ void create_NullExporter() {
@Test
void onEmit() {
- logRecordProcessor.onEmit(readWriteLogRecord);
+ logRecordProcessor.onEmit(Context.current(), readWriteLogRecord);
verify(logRecordExporter).export(Collections.singletonList(LOG_RECORD_DATA));
}
@@ -66,8 +67,8 @@ void onEmit() {
@SuppressLogger(SimpleLogRecordProcessor.class)
void onEmit_ExporterError() {
when(logRecordExporter.export(any())).thenThrow(new RuntimeException("Exporter error!"));
- logRecordProcessor.onEmit(readWriteLogRecord);
- logRecordProcessor.onEmit(readWriteLogRecord);
+ logRecordProcessor.onEmit(Context.current(), readWriteLogRecord);
+ logRecordProcessor.onEmit(Context.current(), readWriteLogRecord);
verify(logRecordExporter, times(2)).export(anyList());
}
@@ -78,8 +79,8 @@ void forceFlush() {
when(logRecordExporter.export(any())).thenReturn(export1, export2);
- logRecordProcessor.onEmit(readWriteLogRecord);
- logRecordProcessor.onEmit(readWriteLogRecord);
+ logRecordProcessor.onEmit(Context.current(), readWriteLogRecord);
+ logRecordProcessor.onEmit(Context.current(), readWriteLogRecord);
verify(logRecordExporter, times(2)).export(Collections.singletonList(LOG_RECORD_DATA));
@@ -101,8 +102,8 @@ void shutdown() {
when(logRecordExporter.export(any())).thenReturn(export1, export2);
- logRecordProcessor.onEmit(readWriteLogRecord);
- logRecordProcessor.onEmit(readWriteLogRecord);
+ logRecordProcessor.onEmit(Context.current(), readWriteLogRecord);
+ logRecordProcessor.onEmit(Context.current(), readWriteLogRecord);
verify(logRecordExporter, times(2)).export(Collections.singletonList(LOG_RECORD_DATA));
From 4b601ade98656ddf85c9ce4a3b62e2cb4efbe0d6 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Wed, 9 Nov 2022 11:59:33 -0600
Subject: [PATCH 15/68] Bump org.jetbrains.kotlin.jvm from 1.7.20 to 1.7.21
(#4927)
Bumps org.jetbrains.kotlin.jvm from 1.7.20 to 1.7.21.
---
updated-dependencies:
- dependency-name: org.jetbrains.kotlin.jvm
dependency-type: direct:production
update-type: version-update:semver-patch
...
Signed-off-by: dependabot[bot]
Signed-off-by: dependabot[bot]
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
settings.gradle.kts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/settings.gradle.kts b/settings.gradle.kts
index aa92f6f6e1a..8f1df84b63a 100644
--- a/settings.gradle.kts
+++ b/settings.gradle.kts
@@ -4,7 +4,7 @@ pluginManagement {
id("com.github.johnrengelman.shadow") version "7.1.2"
id("com.gradle.enterprise") version "3.11.4"
id("io.github.gradle-nexus.publish-plugin") version "1.1.0"
- id("org.jetbrains.kotlin.jvm") version "1.7.20"
+ id("org.jetbrains.kotlin.jvm") version "1.7.21"
id("org.graalvm.buildtools.native") version "0.9.17"
}
}
From ef076c2880d5df9eb5f1460837743278a37476ea Mon Sep 17 00:00:00 2001
From: jack-berg <34418638+jack-berg@users.noreply.github.com>
Date: Wed, 9 Nov 2022 16:54:18 -0600
Subject: [PATCH 16/68] Fix LogsBenchmarks (#4929)
---
.../src/jmh/java/io/opentelemetry/sdk/logs/LogsBenchmarks.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/sdk/logs/src/jmh/java/io/opentelemetry/sdk/logs/LogsBenchmarks.java b/sdk/logs/src/jmh/java/io/opentelemetry/sdk/logs/LogsBenchmarks.java
index b04baebab59..5d0cfd05f68 100644
--- a/sdk/logs/src/jmh/java/io/opentelemetry/sdk/logs/LogsBenchmarks.java
+++ b/sdk/logs/src/jmh/java/io/opentelemetry/sdk/logs/LogsBenchmarks.java
@@ -40,7 +40,7 @@ public static class BenchmarkState {
private final SdkLoggerProvider sdk =
SdkLoggerProvider.builder()
.addLogRecordProcessor(
- logRecord -> {
+ (context, logRecord) -> {
// Do nothing
})
.build();
From f83def7a4f32656c62638d34e2a45ef4440ec86c Mon Sep 17 00:00:00 2001
From: Carlos Alberto Cortez
Date: Thu, 10 Nov 2022 00:02:28 +0100
Subject: [PATCH 17/68] OpenTracing Shim: Full multiple parent support. (#4916)
* Full multiple parent support.
This includes:
* The Baggage union of ALL parents is used.
* All parents are added as Links, in order to preserve
the OpenTracing reference type as an attribute
(either CHILD_OF or FOLLOWS_FROM).
* Update opentracing-shim/src/main/java/io/opentelemetry/opentracingshim/SpanBuilderShim.java
Co-authored-by: jack-berg <34418638+jack-berg@users.noreply.github.com>
* Update opentracing-shim/src/main/java/io/opentelemetry/opentracingshim/SpanBuilderShim.java
Co-authored-by: jack-berg <34418638+jack-berg@users.noreply.github.com>
* Update opentracing-shim/src/main/java/io/opentelemetry/opentracingshim/SpanBuilderShim.java
Co-authored-by: jack-berg <34418638+jack-berg@users.noreply.github.com>
* Apply feedback.
* More feedback.
Co-authored-by: jack-berg <34418638+jack-berg@users.noreply.github.com>
---
opentracing-shim/build.gradle.kts | 2 +
.../opentracingshim/SpanBuilderShim.java | 142 +++++++++++----
.../opentracingshim/SpanBuilderShimTest.java | 165 ++++++++++++++++++
3 files changed, 278 insertions(+), 31 deletions(-)
diff --git a/opentracing-shim/build.gradle.kts b/opentracing-shim/build.gradle.kts
index 9947bc7f5c5..98129994fbc 100644
--- a/opentracing-shim/build.gradle.kts
+++ b/opentracing-shim/build.gradle.kts
@@ -12,6 +12,8 @@ dependencies {
api("io.opentracing:opentracing-api")
implementation(project(":semconv"))
+ annotationProcessor("com.google.auto.value:auto-value")
+
testImplementation(project(":sdk:testing"))
}
diff --git a/opentracing-shim/src/main/java/io/opentelemetry/opentracingshim/SpanBuilderShim.java b/opentracing-shim/src/main/java/io/opentelemetry/opentracingshim/SpanBuilderShim.java
index 5ed3baa8bf1..9c3f8db4946 100644
--- a/opentracing-shim/src/main/java/io/opentelemetry/opentracingshim/SpanBuilderShim.java
+++ b/opentracing-shim/src/main/java/io/opentelemetry/opentracingshim/SpanBuilderShim.java
@@ -10,32 +10,35 @@
import static io.opentelemetry.api.common.AttributeKey.longKey;
import static io.opentelemetry.api.common.AttributeKey.stringKey;
+import com.google.auto.value.AutoValue;
import io.opentelemetry.api.baggage.Baggage;
+import io.opentelemetry.api.baggage.BaggageBuilder;
import io.opentelemetry.api.common.AttributeKey;
+import io.opentelemetry.api.common.Attributes;
import io.opentelemetry.api.trace.SpanKind;
import io.opentelemetry.api.trace.StatusCode;
import io.opentelemetry.context.Context;
+import io.opentelemetry.semconv.trace.attributes.SemanticAttributes;
+import io.opentracing.References;
import io.opentracing.Span;
import io.opentracing.SpanContext;
import io.opentracing.Tracer.SpanBuilder;
import io.opentracing.tag.Tag;
import io.opentracing.tag.Tags;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
import java.util.concurrent.TimeUnit;
import javax.annotation.Nullable;
+import javax.annotation.concurrent.Immutable;
final class SpanBuilderShim extends BaseShimObject implements SpanBuilder {
private final String spanName;
- // The parent will be either a Span or a SpanContext.
- // Inherited baggage is supported only for the main parent.
- @Nullable private SpanShim parentSpan;
- @Nullable private SpanContextShim parentSpanContext;
+ // *All* parents are saved in this list.
+ private List allParents = Collections.emptyList();
private boolean ignoreActiveSpan;
- private final List parentLinks = new ArrayList<>();
-
@SuppressWarnings("rawtypes")
private final List spanBuilderAttributeKeys = new ArrayList<>();
@@ -44,6 +47,15 @@ final class SpanBuilderShim extends BaseShimObject implements SpanBuilder {
private boolean error;
private long startTimestampMicros;
+ private static final Attributes CHILD_OF_ATTR =
+ Attributes.of(
+ SemanticAttributes.OPENTRACING_REF_TYPE,
+ SemanticAttributes.OpentracingRefTypeValues.CHILD_OF);
+ private static final Attributes FOLLOWS_FROM_ATTR =
+ Attributes.of(
+ SemanticAttributes.OPENTRACING_REF_TYPE,
+ SemanticAttributes.OpentracingRefTypeValues.FOLLOWS_FROM);
+
public SpanBuilderShim(TelemetryInfo telemetryInfo, String spanName) {
super(telemetryInfo);
this.spanName = spanName;
@@ -57,19 +69,12 @@ public SpanBuilder asChildOf(Span parent) {
// TODO - Verify we handle a no-op Span
SpanShim spanShim = ShimUtil.getSpanShim(parent);
-
- if (parentSpan == null && parentSpanContext == null) {
- parentSpan = spanShim;
- } else {
- parentLinks.add(spanShim.getSpan().getSpanContext());
- }
-
- return this;
+ return addReference(References.CHILD_OF, spanShim.context());
}
@Override
public SpanBuilder asChildOf(SpanContext parent) {
- return addReference(null, parent);
+ return addReference(References.CHILD_OF, parent);
}
@Override
@@ -78,13 +83,30 @@ public SpanBuilder addReference(@Nullable String referenceType, SpanContext refe
return this;
}
- // TODO - Use referenceType
+ ReferenceType refType;
+ if (References.CHILD_OF.equals(referenceType)) {
+ refType = ReferenceType.CHILD_OF;
+ } else if (References.FOLLOWS_FROM.equals(referenceType)) {
+ refType = ReferenceType.FOLLOWS_FROM;
+ } else {
+ // Discard references with unrecognized type.
+ return this;
+ }
+
SpanContextShim contextShim = ShimUtil.getContextShim(referencedContext);
- if (parentSpan == null && parentSpanContext == null) {
- parentSpanContext = contextShim;
+ // Optimization for 99% situations, when there is only one parent.
+ if (allParents.size() == 0) {
+ allParents =
+ Collections.singletonList(
+ SpanParentInfo.create(
+ contextShim.getSpanContext(), contextShim.getBaggage(), refType));
} else {
- parentLinks.add(contextShim.getSpanContext());
+ if (allParents.size() == 1) {
+ allParents = new ArrayList<>(allParents);
+ }
+ allParents.add(
+ SpanParentInfo.create(contextShim.getSpanContext(), contextShim.getBaggage(), refType));
}
return this;
@@ -186,26 +208,26 @@ public SpanBuilder withStartTimestamp(long microseconds) {
@SuppressWarnings({"rawtypes", "unchecked"})
@Override
public Span start() {
- Baggage baggage = Baggage.empty();
+ Baggage baggage;
io.opentelemetry.api.trace.SpanBuilder builder = tracer().spanBuilder(spanName);
+ io.opentelemetry.api.trace.SpanContext mainParent = getMainParent(allParents);
- if (ignoreActiveSpan && parentSpan == null && parentSpanContext == null) {
+ if (ignoreActiveSpan && mainParent == null) {
builder.setNoParent();
- } else if (parentSpan != null) {
- builder.setParent(Context.root().with(parentSpan.getSpan()));
- baggage = ((SpanContextShim) parentSpan.context()).getBaggage();
- } else if (parentSpanContext != null) {
- builder.setParent(
- Context.root()
- .with(io.opentelemetry.api.trace.Span.wrap(parentSpanContext.getSpanContext())));
- baggage = parentSpanContext.getBaggage();
+ baggage = Baggage.empty();
+ } else if (mainParent != null) {
+ builder.setParent(Context.root().with(io.opentelemetry.api.trace.Span.wrap(mainParent)));
+ baggage = getAllBaggage(allParents);
} else {
// No explicit parent Span, but extracted baggage may be available.
baggage = Baggage.current();
}
- for (io.opentelemetry.api.trace.SpanContext link : parentLinks) {
- builder.addLink(link);
+ // *All* parents are processed as Links, in order to keep the reference type value.
+ for (SpanParentInfo parentInfo : allParents) {
+ builder.addLink(
+ parentInfo.getSpanContext(),
+ parentInfo.getRefType() == ReferenceType.CHILD_OF ? CHILD_OF_ATTR : FOLLOWS_FROM_ATTR);
}
if (spanKind != null) {
@@ -232,4 +254,62 @@ public Span start() {
return new SpanShim(telemetryInfo(), span, baggage);
}
+
+ // The first SpanContext with Child Of type in the entire list is used as parent,
+ // else the first SpanContext is used as parent.
+ @Nullable
+ static io.opentelemetry.api.trace.SpanContext getMainParent(List parents) {
+ if (parents.size() == 0) {
+ return null;
+ }
+
+ SpanParentInfo mainParent = parents.get(0);
+ for (SpanParentInfo parentInfo : parents) {
+ if (parentInfo.getRefType() == ReferenceType.CHILD_OF) {
+ mainParent = parentInfo;
+ break;
+ }
+ }
+
+ return mainParent.getSpanContext();
+ }
+
+ static Baggage getAllBaggage(List parents) {
+ if (parents.size() == 0) {
+ return Baggage.empty();
+ }
+
+ if (parents.size() == 1) {
+ return parents.get(0).getBaggage();
+ }
+
+ BaggageBuilder builder = Baggage.builder();
+ for (SpanParentInfo parent : parents) {
+ parent.getBaggage().forEach((key, entry) -> builder.put(key, entry.getValue()));
+ }
+
+ return builder.build();
+ }
+
+ @AutoValue
+ @Immutable
+ abstract static class SpanParentInfo {
+ private static SpanParentInfo create(
+ io.opentelemetry.api.trace.SpanContext spanContext,
+ Baggage baggage,
+ ReferenceType refType) {
+ return new AutoValue_SpanBuilderShim_SpanParentInfo(spanContext, baggage, refType);
+ }
+
+ abstract io.opentelemetry.api.trace.SpanContext getSpanContext();
+
+ abstract Baggage getBaggage();
+
+ abstract ReferenceType getRefType();
+ }
+
+ enum ReferenceType {
+ CHILD_OF,
+ FOLLOWS_FROM
+ }
}
diff --git a/opentracing-shim/src/test/java/io/opentelemetry/opentracingshim/SpanBuilderShimTest.java b/opentracing-shim/src/test/java/io/opentelemetry/opentracingshim/SpanBuilderShimTest.java
index 06fc3891d8c..05a412478c3 100644
--- a/opentracing-shim/src/test/java/io/opentelemetry/opentracingshim/SpanBuilderShimTest.java
+++ b/opentracing-shim/src/test/java/io/opentelemetry/opentracingshim/SpanBuilderShimTest.java
@@ -20,6 +20,8 @@
import io.opentelemetry.sdk.trace.data.SpanData;
import io.opentelemetry.sdk.trace.samplers.Sampler;
import io.opentelemetry.sdk.trace.samplers.SamplingResult;
+import io.opentelemetry.semconv.trace.attributes.SemanticAttributes;
+import io.opentracing.References;
import java.util.List;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -38,6 +40,143 @@ void setUp() {
GlobalOpenTelemetry.resetForTest();
}
+ @Test
+ void parent_single() {
+ SpanShim parentSpan = (SpanShim) new SpanBuilderShim(telemetryInfo, SPAN_NAME).start();
+ try {
+ SpanShim childSpan =
+ (SpanShim) new SpanBuilderShim(telemetryInfo, SPAN_NAME).asChildOf(parentSpan).start();
+
+ try {
+ SpanData spanData = ((ReadableSpan) childSpan.getSpan()).toSpanData();
+ assertThat(parentSpan.context().toSpanId()).isEqualTo(spanData.getParentSpanId());
+ } finally {
+ childSpan.finish();
+ }
+ } finally {
+ parentSpan.finish();
+ }
+ }
+
+ @Test
+ void parent_multipleFollowsFrom() {
+ SpanShim parentSpan1 = (SpanShim) new SpanBuilderShim(telemetryInfo, SPAN_NAME).start();
+ SpanShim parentSpan2 = (SpanShim) new SpanBuilderShim(telemetryInfo, SPAN_NAME).start();
+
+ try {
+ SpanShim childSpan =
+ (SpanShim)
+ new SpanBuilderShim(telemetryInfo, SPAN_NAME)
+ .addReference(References.FOLLOWS_FROM, parentSpan1.context())
+ .addReference(References.FOLLOWS_FROM, parentSpan2.context())
+ .start();
+
+ try {
+ // If no parent of CHILD_OF type exists, use the first value as main parent.
+ SpanData spanData = ((ReadableSpan) childSpan.getSpan()).toSpanData();
+ assertThat(parentSpan1.context().toSpanId()).isEqualTo(spanData.getParentSpanId());
+ } finally {
+ childSpan.finish();
+ }
+ } finally {
+ parentSpan1.finish();
+ parentSpan2.finish();
+ }
+ }
+
+ @Test
+ void parent_multipleDifferentRefType() {
+ SpanShim parentSpan1 = (SpanShim) new SpanBuilderShim(telemetryInfo, SPAN_NAME).start();
+ SpanShim parentSpan2 = (SpanShim) new SpanBuilderShim(telemetryInfo, SPAN_NAME).start();
+ SpanShim parentSpan3 = (SpanShim) new SpanBuilderShim(telemetryInfo, SPAN_NAME).start();
+
+ try {
+ SpanShim childSpan =
+ (SpanShim)
+ new SpanBuilderShim(telemetryInfo, SPAN_NAME)
+ .addReference(References.FOLLOWS_FROM, parentSpan1.context())
+ .addReference(References.CHILD_OF, parentSpan2.context())
+ .addReference(References.CHILD_OF, parentSpan3.context())
+ .start();
+
+ try {
+ // The first parent with CHILD_OF becomes the direct parent (if any).
+ SpanData spanData = ((ReadableSpan) childSpan.getSpan()).toSpanData();
+ assertThat(parentSpan2.context().toSpanId()).isEqualTo(spanData.getParentSpanId());
+ } finally {
+ childSpan.finish();
+ }
+ } finally {
+ parentSpan1.finish();
+ parentSpan2.finish();
+ parentSpan3.finish();
+ }
+ }
+
+ @Test
+ void parent_multipleLinks() {
+ SpanShim parentSpan1 = (SpanShim) new SpanBuilderShim(telemetryInfo, SPAN_NAME).start();
+ SpanShim parentSpan2 = (SpanShim) new SpanBuilderShim(telemetryInfo, SPAN_NAME).start();
+ SpanShim parentSpan3 = (SpanShim) new SpanBuilderShim(telemetryInfo, SPAN_NAME).start();
+
+ try {
+ SpanShim childSpan =
+ (SpanShim)
+ new SpanBuilderShim(telemetryInfo, SPAN_NAME)
+ .addReference(References.FOLLOWS_FROM, parentSpan1.context())
+ .addReference(References.CHILD_OF, parentSpan2.context())
+ .addReference(References.FOLLOWS_FROM, parentSpan3.context())
+ .start();
+
+ try {
+ SpanData spanData = ((ReadableSpan) childSpan.getSpan()).toSpanData();
+ List links = spanData.getLinks();
+ assertThat(links).hasSize(3);
+
+ assertThat(links.get(0).getSpanContext()).isEqualTo(parentSpan1.getSpan().getSpanContext());
+ assertThat(links.get(1).getSpanContext()).isEqualTo(parentSpan2.getSpan().getSpanContext());
+ assertThat(links.get(2).getSpanContext()).isEqualTo(parentSpan3.getSpan().getSpanContext());
+ assertThat(links.get(0).getAttributes().get(SemanticAttributes.OPENTRACING_REF_TYPE))
+ .isEqualTo(SemanticAttributes.OpentracingRefTypeValues.FOLLOWS_FROM);
+ assertThat(links.get(1).getAttributes().get(SemanticAttributes.OPENTRACING_REF_TYPE))
+ .isEqualTo(SemanticAttributes.OpentracingRefTypeValues.CHILD_OF);
+ assertThat(links.get(2).getAttributes().get(SemanticAttributes.OPENTRACING_REF_TYPE))
+ .isEqualTo(SemanticAttributes.OpentracingRefTypeValues.FOLLOWS_FROM);
+
+ } finally {
+ childSpan.finish();
+ }
+ } finally {
+ parentSpan1.finish();
+ parentSpan2.finish();
+ parentSpan3.finish();
+ }
+ }
+
+ @Test
+ void parent_wrongRefType() {
+ SpanShim parentSpan = (SpanShim) new SpanBuilderShim(telemetryInfo, SPAN_NAME).start();
+ try {
+ SpanShim childSpan =
+ (SpanShim)
+ new SpanBuilderShim(telemetryInfo, SPAN_NAME)
+ .addReference("wrongreftype-value", parentSpan.context())
+ .start();
+
+ try {
+ // Incorrect typeref values get discarded.
+ SpanData spanData = ((ReadableSpan) childSpan.getSpan()).toSpanData();
+ assertThat(spanData.getParentSpanContext())
+ .isEqualTo(io.opentelemetry.api.trace.SpanContext.getInvalid());
+ assertThat(spanData.getLinks()).isEmpty();
+ } finally {
+ childSpan.finish();
+ }
+ } finally {
+ parentSpan.finish();
+ }
+ }
+
@Test
void baggage_parent() {
SpanShim parentSpan = (SpanShim) new SpanBuilderShim(telemetryInfo, SPAN_NAME).start();
@@ -79,6 +218,32 @@ void baggage_parentContext() {
}
}
+ @Test
+ void baggage_multipleParents() {
+ SpanShim parentSpan1 = (SpanShim) new SpanBuilderShim(telemetryInfo, SPAN_NAME).start();
+ SpanShim parentSpan2 = (SpanShim) new SpanBuilderShim(telemetryInfo, SPAN_NAME).start();
+ try {
+ parentSpan1.setBaggageItem("key1", "value1");
+ parentSpan2.setBaggageItem("key2", "value2");
+
+ SpanShim childSpan =
+ (SpanShim)
+ new SpanBuilderShim(telemetryInfo, SPAN_NAME)
+ .addReference(References.FOLLOWS_FROM, parentSpan1.context())
+ .addReference(References.CHILD_OF, parentSpan2.context())
+ .start();
+ try {
+ assertThat(childSpan.getBaggageItem("key1")).isEqualTo("value1");
+ assertThat(childSpan.getBaggageItem("key2")).isEqualTo("value2");
+ } finally {
+ childSpan.finish();
+ }
+ } finally {
+ parentSpan1.finish();
+ parentSpan2.finish();
+ }
+ }
+
@Test
void baggage_spanWithInvalidSpan() {
io.opentelemetry.api.baggage.Baggage baggage =
From 36adb27cf8c10b013dfeca01d89fe17443a4f3d3 Mon Sep 17 00:00:00 2001
From: Ragnar Rova
Date: Thu, 10 Nov 2022 00:35:33 +0100
Subject: [PATCH 18/68] Allow SDK to run in environments prohibiting use of
sun.misc.Unsafe (#4902)
Some applications run under strict java.security permissions
which do not allow access to sun.misc.Unsafe.
BatchSpanProcessor uses Unsafe via jctools, but has a fallback to
ArrayBlockingQueue. Extending that fallback rule to cover
java security exceptions as well.
Co-authored-by: Jack Berg
---
sdk/trace-shaded-deps/build.gradle.kts | 5 +
.../sdk/trace/internal/JcTools.java | 18 ++-
.../internal/JcToolsSecurityManagerTest.java | 38 ++++++
.../SunMiscProhibitedSecurityManager.java | 111 ++++++++++++++++++
.../SunMiscProhibitedSecurityManagerTest.java | 41 +++++++
5 files changed, 211 insertions(+), 2 deletions(-)
create mode 100644 sdk/trace-shaded-deps/src/test/java/io/opentelemetry/sdk/trace/internal/JcToolsSecurityManagerTest.java
create mode 100644 sdk/trace-shaded-deps/src/test/java/io/opentelemetry/sdk/trace/internal/SunMiscProhibitedSecurityManager.java
create mode 100644 sdk/trace-shaded-deps/src/test/java/io/opentelemetry/sdk/trace/internal/SunMiscProhibitedSecurityManagerTest.java
diff --git a/sdk/trace-shaded-deps/build.gradle.kts b/sdk/trace-shaded-deps/build.gradle.kts
index 14f73ca4b79..c4573c976b7 100644
--- a/sdk/trace-shaded-deps/build.gradle.kts
+++ b/sdk/trace-shaded-deps/build.gradle.kts
@@ -26,3 +26,8 @@ tasks {
into("build/extracted/shadow")
}
}
+
+tasks.withType().configureEach {
+ // JcToolsSecurityManagerTest interferes with JcToolsTest
+ setForkEvery(1)
+}
diff --git a/sdk/trace-shaded-deps/src/main/java/io/opentelemetry/sdk/trace/internal/JcTools.java b/sdk/trace-shaded-deps/src/main/java/io/opentelemetry/sdk/trace/internal/JcTools.java
index a293c437aff..06976ad13d5 100644
--- a/sdk/trace-shaded-deps/src/main/java/io/opentelemetry/sdk/trace/internal/JcTools.java
+++ b/sdk/trace-shaded-deps/src/main/java/io/opentelemetry/sdk/trace/internal/JcTools.java
@@ -5,9 +5,13 @@
package io.opentelemetry.sdk.trace.internal;
+import java.util.Objects;
import java.util.Queue;
import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Consumer;
+import java.util.logging.Level;
+import java.util.logging.Logger;
import org.jctools.queues.MessagePassingQueue;
import org.jctools.queues.MpscArrayQueue;
@@ -19,14 +23,24 @@
*/
public final class JcTools {
+ private static final AtomicBoolean queueCreationWarningLogged = new AtomicBoolean();
+ private static final Logger logger = Logger.getLogger(JcTools.class.getName());
+
/**
* Returns a new {@link Queue} appropriate for use with multiple producers and a single consumer.
*/
public static Queue newFixedSizeQueue(int capacity) {
try {
return new MpscArrayQueue<>(capacity);
- } catch (java.lang.NoClassDefFoundError e) {
- // Happens when modules such as jdk.unsupported are disabled in a custom JRE distribution
+ } catch (java.lang.NoClassDefFoundError | java.lang.ExceptionInInitializerError e) {
+ if (!queueCreationWarningLogged.getAndSet(true)) {
+ logger.log(
+ Level.WARNING,
+ "Cannot create high-performance queue, reverting to ArrayBlockingQueue ({0})",
+ Objects.toString(e, "unknown cause"));
+ }
+ // Happens when modules such as jdk.unsupported are disabled in a custom JRE distribution,
+ // or a security manager preventing access to Unsafe is installed.
return new ArrayBlockingQueue<>(capacity);
}
}
diff --git a/sdk/trace-shaded-deps/src/test/java/io/opentelemetry/sdk/trace/internal/JcToolsSecurityManagerTest.java b/sdk/trace-shaded-deps/src/test/java/io/opentelemetry/sdk/trace/internal/JcToolsSecurityManagerTest.java
new file mode 100644
index 00000000000..eb2bd9199e3
--- /dev/null
+++ b/sdk/trace-shaded-deps/src/test/java/io/opentelemetry/sdk/trace/internal/JcToolsSecurityManagerTest.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.sdk.trace.internal;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import io.opentelemetry.internal.testing.slf4j.SuppressLogger;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.Queue;
+import java.util.concurrent.ArrayBlockingQueue;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.condition.EnabledOnJre;
+import org.junit.jupiter.api.condition.JRE;
+
+public class JcToolsSecurityManagerTest {
+
+ @Test
+ @EnabledOnJre({JRE.JAVA_8, JRE.JAVA_11, JRE.JAVA_17})
+ @SuppressLogger(JcTools.class)
+ void newFixedSizeQueue_SunMiscProhibited() {
+ assertThat(System.getSecurityManager()).isNull();
+ SunMiscProhibitedSecurityManager testingSecurityManager =
+ new SunMiscProhibitedSecurityManager();
+ try {
+ System.setSecurityManager(testingSecurityManager);
+ Queue