Browse Source

Add `service.name` to MDC (#9647)

Co-authored-by: Lauri Tulmin <ltulmin@splunk.com>
cleverchuk 1 year ago
parent
commit
81f8bf6231
19 changed files with 232 additions and 7 deletions
  1. 5 0
      instrumentation/log4j/log4j-context-data/log4j-context-data-2.17/javaagent/README.md
  2. 2 0
      instrumentation/log4j/log4j-context-data/log4j-context-data-2.17/javaagent/build.gradle.kts
  3. 20 0
      instrumentation/log4j/log4j-context-data/log4j-context-data-2.17/javaagent/src/test/groovy/AutoLog4j2Test.groovy
  4. 1 0
      instrumentation/log4j/log4j-context-data/log4j-context-data-2.17/library-autoconfigure/build.gradle.kts
  5. 34 1
      instrumentation/log4j/log4j-context-data/log4j-context-data-2.17/library-autoconfigure/src/main/java/io/opentelemetry/instrumentation/log4j/contextdata/v2_17/OpenTelemetryContextDataProvider.java
  6. 1 0
      instrumentation/log4j/log4j-context-data/log4j-context-data-2.7/javaagent/build.gradle.kts
  7. 21 3
      instrumentation/log4j/log4j-context-data/log4j-context-data-2.7/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/log4j/contextdata/v2_7/SpanDecoratingContextDataInjector.java
  8. 20 0
      instrumentation/log4j/log4j-context-data/log4j-context-data-2.7/javaagent/src/test/groovy/Log4j27Test.groovy
  9. 5 0
      instrumentation/log4j/log4j-mdc-1.2/javaagent/README.md
  10. 6 0
      instrumentation/log4j/log4j-mdc-1.2/javaagent/build.gradle.kts
  11. 3 0
      instrumentation/log4j/log4j-mdc-1.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/log4j/mdc/v1_2/LoggingEventInstrumentation.java
  12. 15 0
      instrumentation/log4j/log4j-mdc-1.2/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/log4j/mdc/v1_2/Log4j1MdcTest.java
  13. 4 3
      instrumentation/logback/logback-mdc-1.0/javaagent/README.md
  14. 4 0
      instrumentation/logback/logback-mdc-1.0/javaagent/build.gradle.kts
  15. 2 0
      instrumentation/logback/logback-mdc-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/logback/mdc/v1_0/LoggingEventInstrumentation.java
  16. 21 0
      instrumentation/logback/logback-mdc-1.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/logback/v1_0/LogbackTest.java
  17. 48 0
      javaagent-extension-api/src/main/java/io/opentelemetry/javaagent/bootstrap/internal/ConfiguredResourceAttributesHolder.java
  18. 4 0
      javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/AgentInstaller.java
  19. 16 0
      javaagent-tooling/src/main/java/io/opentelemetry/sdk/autoconfigure/SdkAutoconfigureAccess.java

+ 5 - 0
instrumentation/log4j/log4j-context-data/log4j-context-data-2.17/javaagent/README.md

@@ -0,0 +1,5 @@
+# Settings for the Log4j MDC instrumentation
+
+| System property                                       | Type    | Default | Description                                                        |
+|-------------------------------------------------------|---------|---------|--------------------------------------------------------------------|
+| `otel.instrumentation.common.mdc.resource-attributes` | String  |         | Comma separated list of resource attributes to expose through MDC. |

+ 2 - 0
instrumentation/log4j/log4j-context-data/log4j-context-data-2.17/javaagent/build.gradle.kts

@@ -40,6 +40,7 @@ testing {
           testTask.configure {
             jvmArgs("-Dlog4j2.is.webapp=false")
             jvmArgs("-Dlog4j2.enable.threadlocals=false")
+            jvmArgs("-Dotel.instrumentation.common.mdc.resource-attributes=service.name,telemetry.sdk.language")
           }
         }
       }
@@ -74,6 +75,7 @@ tasks {
   test {
     jvmArgs("-Dlog4j2.is.webapp=false")
     jvmArgs("-Dlog4j2.enable.threadlocals=true")
+    jvmArgs("-Dotel.instrumentation.common.mdc.resource-attributes=service.name,telemetry.sdk.language")
   }
 
   named("check") {

+ 20 - 0
instrumentation/log4j/log4j-context-data/log4j-context-data-2.17/javaagent/src/test/groovy/AutoLog4j2Test.groovy

@@ -3,7 +3,27 @@
  * SPDX-License-Identifier: Apache-2.0
  */
 
+import io.opentelemetry.instrumentation.log4j.contextdata.ListAppender
 import io.opentelemetry.instrumentation.test.AgentTestTrait
+import org.apache.logging.log4j.LogManager
 
 class AutoLog4j2Test extends Log4j2Test implements AgentTestTrait {
+
+  def "resource attributes"() {
+    given:
+    def logger = LogManager.getLogger("TestLogger")
+
+    when:
+    logger.info("log message 1")
+
+    def events = ListAppender.get().getEvents()
+
+    then:
+    events.size() == 1
+    events[0].message == "log message 1"
+    events[0].contextData["trace_id"] == null
+    events[0].contextData["span_id"] == null
+    events[0].contextData["service.name"] == "unknown_service:java"
+    events[0].contextData["telemetry.sdk.language"] == "java"
+  }
 }

+ 1 - 0
instrumentation/log4j/log4j-context-data/log4j-context-data-2.17/library-autoconfigure/build.gradle.kts

@@ -5,6 +5,7 @@ plugins {
 base.archivesName.set("${base.archivesName.get()}-autoconfigure")
 
 dependencies {
+  compileOnly(project(":javaagent-extension-api"))
   library("org.apache.logging.log4j:log4j-core:2.17.0")
 
   testImplementation(project(":instrumentation:log4j:log4j-context-data:log4j-context-data-common:testing"))

+ 34 - 1
instrumentation/log4j/log4j-context-data/log4j-context-data-2.17/library-autoconfigure/src/main/java/io/opentelemetry/instrumentation/log4j/contextdata/v2_17/OpenTelemetryContextDataProvider.java

@@ -15,6 +15,7 @@ import io.opentelemetry.api.trace.Span;
 import io.opentelemetry.api.trace.SpanContext;
 import io.opentelemetry.context.Context;
 import io.opentelemetry.instrumentation.api.internal.ConfigPropertiesUtil;
+import io.opentelemetry.javaagent.bootstrap.internal.ConfiguredResourceAttributesHolder;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
@@ -25,9 +26,39 @@ import org.apache.logging.log4j.core.util.ContextDataProvider;
  * #supplyContextData()} is called when a log entry is created.
  */
 public class OpenTelemetryContextDataProvider implements ContextDataProvider {
+
   private static final boolean BAGGAGE_ENABLED =
       ConfigPropertiesUtil.getBoolean("otel.instrumentation.log4j-context-data.add-baggage", false);
 
+  private static final boolean configuredResourceAttributeAccessible =
+      isConfiguredResourceAttributeAccessible();
+
+  private static final Map<String, String> staticContextData = getStaticContextData();
+
+  private static Map<String, String> getStaticContextData() {
+    if (configuredResourceAttributeAccessible) {
+      return ConfiguredResourceAttributesHolder.getResourceAttributes();
+    }
+    return Collections.emptyMap();
+  }
+
+  /**
+   * Checks whether {@link ConfiguredResourceAttributesHolder} is available in classpath. The result
+   * is true if {@link ConfiguredResourceAttributesHolder} can be loaded, false otherwise.
+   *
+   * @return A boolean
+   */
+  private static boolean isConfiguredResourceAttributeAccessible() {
+    try {
+      Class.forName(
+          "io.opentelemetry.javaagent.bootstrap.internal.ConfiguredResourceAttributesHolder");
+      return true;
+
+    } catch (ClassNotFoundException ok) {
+      return false;
+    }
+  }
+
   /**
    * Returns context from the current span when available.
    *
@@ -39,10 +70,12 @@ public class OpenTelemetryContextDataProvider implements ContextDataProvider {
     Context context = Context.current();
     Span currentSpan = Span.fromContext(context);
     if (!currentSpan.getSpanContext().isValid()) {
-      return Collections.emptyMap();
+      return staticContextData;
     }
 
     Map<String, String> contextData = new HashMap<>();
+    contextData.putAll(staticContextData);
+
     SpanContext spanContext = currentSpan.getSpanContext();
     contextData.put(TRACE_ID, spanContext.getTraceId());
     contextData.put(SPAN_ID, spanContext.getSpanId());

+ 1 - 0
instrumentation/log4j/log4j-context-data/log4j-context-data-2.7/javaagent/build.gradle.kts

@@ -26,6 +26,7 @@ tasks {
     filter {
       excludeTestsMatching("Log4j27BaggageTest")
     }
+    jvmArgs("-Dotel.instrumentation.common.mdc.resource-attributes=service.name,telemetry.sdk.language")
   }
 
   val testAddBaggage by registering(Test::class) {

+ 21 - 3
instrumentation/log4j/log4j-context-data/log4j-context-data-2.7/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/log4j/contextdata/v2_7/SpanDecoratingContextDataInjector.java

@@ -14,6 +14,7 @@ import io.opentelemetry.api.baggage.BaggageEntry;
 import io.opentelemetry.api.trace.Span;
 import io.opentelemetry.api.trace.SpanContext;
 import io.opentelemetry.context.Context;
+import io.opentelemetry.javaagent.bootstrap.internal.ConfiguredResourceAttributesHolder;
 import io.opentelemetry.javaagent.bootstrap.internal.InstrumentationConfig;
 import java.util.List;
 import java.util.Map;
@@ -28,6 +29,8 @@ public final class SpanDecoratingContextDataInjector implements ContextDataInjec
       InstrumentationConfig.get()
           .getBoolean("otel.instrumentation.log4j-context-data.add-baggage", false);
 
+  private static final StringMap staticContextData = getStaticContextData();
+
   private final ContextDataInjector delegate;
 
   public SpanDecoratingContextDataInjector(ContextDataInjector delegate) {
@@ -40,17 +43,17 @@ public final class SpanDecoratingContextDataInjector implements ContextDataInjec
 
     if (contextData.containsKey(TRACE_ID)) {
       // Assume already instrumented event if traceId is present.
-      return contextData;
+      return staticContextData.isEmpty() ? contextData : newContextData(contextData);
     }
 
     Context context = Context.current();
     Span span = Span.fromContext(context);
     SpanContext currentContext = span.getSpanContext();
     if (!currentContext.isValid()) {
-      return contextData;
+      return staticContextData.isEmpty() ? contextData : newContextData(contextData);
     }
 
-    StringMap newContextData = new SortedArrayStringMap(contextData);
+    StringMap newContextData = newContextData(contextData);
     newContextData.putValue(TRACE_ID, currentContext.getTraceId());
     newContextData.putValue(SPAN_ID, currentContext.getSpanId());
     newContextData.putValue(TRACE_FLAGS, currentContext.getTraceFlags().asHex());
@@ -69,4 +72,19 @@ public final class SpanDecoratingContextDataInjector implements ContextDataInjec
   public ReadOnlyStringMap rawContextData() {
     return delegate.rawContextData();
   }
+
+  private static StringMap newContextData(StringMap contextData) {
+    StringMap newContextData = new SortedArrayStringMap(contextData);
+    newContextData.putAll(staticContextData);
+    return newContextData;
+  }
+
+  private static StringMap getStaticContextData() {
+    StringMap map = new SortedArrayStringMap();
+    for (Map.Entry<String, String> entry :
+        ConfiguredResourceAttributesHolder.getResourceAttributes().entrySet()) {
+      map.putValue(entry.getKey(), entry.getValue());
+    }
+    return map;
+  }
 }

+ 20 - 0
instrumentation/log4j/log4j-context-data/log4j-context-data-2.7/javaagent/src/test/groovy/Log4j27Test.groovy

@@ -3,7 +3,27 @@
  * SPDX-License-Identifier: Apache-2.0
  */
 
+import io.opentelemetry.instrumentation.log4j.contextdata.ListAppender
 import io.opentelemetry.instrumentation.test.AgentTestTrait
+import org.apache.logging.log4j.LogManager
 
 class Log4j27Test extends Log4j2Test implements AgentTestTrait {
+
+  def "resource attributes"() {
+    given:
+    def logger = LogManager.getLogger("TestLogger")
+
+    when:
+    logger.info("log message 1")
+
+    def events = ListAppender.get().getEvents()
+
+    then:
+    events.size() == 1
+    events[0].message == "log message 1"
+    events[0].contextData["trace_id"] == null
+    events[0].contextData["span_id"] == null
+    events[0].contextData["service.name"] == "unknown_service:java"
+    events[0].contextData["telemetry.sdk.language"] == "java"
+  }
 }

+ 5 - 0
instrumentation/log4j/log4j-mdc-1.2/javaagent/README.md

@@ -0,0 +1,5 @@
+# Settings for the Log4j MDC instrumentation
+
+| System property                                       | Type    | Default | Description                                                        |
+|-------------------------------------------------------|---------|---------|--------------------------------------------------------------------|
+| `otel.instrumentation.common.mdc.resource-attributes` | String  |         | Comma separated list of resource attributes to expose through MDC. |

+ 6 - 0
instrumentation/log4j/log4j-mdc-1.2/javaagent/build.gradle.kts

@@ -30,3 +30,9 @@ configurations {
     exclude("javax.jms", "jms")
   }
 }
+
+tasks {
+  test {
+    jvmArgs("-Dotel.instrumentation.common.mdc.resource-attributes=service.name,telemetry.sdk.language")
+  }
+}

+ 3 - 0
instrumentation/log4j/log4j-mdc-1.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/log4j/mdc/v1_2/LoggingEventInstrumentation.java

@@ -18,6 +18,7 @@ import io.opentelemetry.api.trace.SpanContext;
 import io.opentelemetry.context.Context;
 import io.opentelemetry.instrumentation.api.util.VirtualField;
 import io.opentelemetry.javaagent.bootstrap.Java8BytecodeBridge;
+import io.opentelemetry.javaagent.bootstrap.internal.ConfiguredResourceAttributesHolder;
 import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
 import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
 import net.bytebuddy.asm.Advice;
@@ -79,6 +80,8 @@ public class LoggingEventInstrumentation implements TypeInstrumentation {
           default:
             // do nothing
         }
+      } else if (value == null) {
+        value = ConfiguredResourceAttributesHolder.getAttributeValue(key);
       }
     }
   }

+ 15 - 0
instrumentation/log4j/log4j-mdc-1.2/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/log4j/mdc/v1_2/Log4j1MdcTest.java

@@ -90,4 +90,19 @@ public class Log4j1MdcTest {
     assertEquals(events.get(2).getMDC("span_id"), span2.getSpanContext().getSpanId());
     assertEquals(events.get(2).getMDC("trace_flags"), "01");
   }
+
+  @Test
+  void resourceAttributes() {
+    logger.info("log message 1");
+
+    List<LoggingEvent> events = ListAppender.getEvents();
+
+    assertEquals(1, events.size());
+    assertEquals("log message 1", events.get(0).getMessage());
+    assertNull(events.get(0).getMDC("trace_id"));
+    assertNull(events.get(0).getMDC("span_id"));
+    assertNull(events.get(0).getMDC("trace_flags"));
+    assertEquals("unknown_service:java", events.get(0).getMDC("service.name"));
+    assertEquals("java", events.get(0).getMDC("telemetry.sdk.language"));
+  }
 }

+ 4 - 3
instrumentation/logback/logback-mdc-1.0/javaagent/README.md

@@ -1,5 +1,6 @@
 # Settings for the Logback MDC instrumentation
 
-| System property                                | Type    | Default | Description                                     |
-| ---------------------------------------------- | ------- | ------- | ----------------------------------------------- |
-| `otel.instrumentation.logback-mdc.add-baggage` | Boolean | `false` | Enable exposing baggage attributes through MDC. |
+| System property                                       | Type    | Default | Description                                                        |
+|-------------------------------------------------------|---------|---------|--------------------------------------------------------------------|
+| `otel.instrumentation.logback-mdc.add-baggage`        | Boolean | `false` | Enable exposing baggage attributes through MDC.                    |
+| `otel.instrumentation.common.mdc.resource-attributes` | String  |         | Comma separated list of resource attributes to expose through MDC. |

+ 4 - 0
instrumentation/logback/logback-mdc-1.0/javaagent/build.gradle.kts

@@ -63,6 +63,10 @@ dependencies {
 }
 
 tasks {
+  test {
+    jvmArgs("-Dotel.instrumentation.common.mdc.resource-attributes=service.name,telemetry.sdk.language")
+  }
+
   named("check") {
     dependsOn(testing.suites)
   }

+ 2 - 0
instrumentation/logback/logback-mdc-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/logback/mdc/v1_0/LoggingEventInstrumentation.java

@@ -24,6 +24,7 @@ import io.opentelemetry.context.Context;
 import io.opentelemetry.instrumentation.api.util.VirtualField;
 import io.opentelemetry.instrumentation.logback.mdc.v1_0.internal.UnionMap;
 import io.opentelemetry.javaagent.bootstrap.Java8BytecodeBridge;
+import io.opentelemetry.javaagent.bootstrap.internal.ConfiguredResourceAttributesHolder;
 import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
 import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
 import java.util.HashMap;
@@ -80,6 +81,7 @@ public class LoggingEventInstrumentation implements TypeInstrumentation {
         spanContextData.put(SPAN_ID, spanContext.getSpanId());
         spanContextData.put(TRACE_FLAGS, spanContext.getTraceFlags().asHex());
       }
+      spanContextData.putAll(ConfiguredResourceAttributesHolder.getResourceAttributes());
 
       if (LogbackSingletons.addBaggage()) {
         Baggage baggage = Java8BytecodeBridge.baggageFromContext(context);

+ 21 - 0
instrumentation/logback/logback-mdc-1.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/logback/v1_0/LogbackTest.java

@@ -5,9 +5,14 @@
 
 package io.opentelemetry.javaagent.instrumentation.logback.v1_0;
 
+import static org.assertj.core.api.Assertions.assertThat;
+
+import ch.qos.logback.classic.spi.ILoggingEvent;
 import io.opentelemetry.instrumentation.logback.mdc.v1_0.AbstractLogbackTest;
 import io.opentelemetry.instrumentation.testing.junit.AgentInstrumentationExtension;
 import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension;
+import java.util.List;
+import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.RegisterExtension;
 
 class LogbackTest extends AbstractLogbackTest {
@@ -19,4 +24,20 @@ class LogbackTest extends AbstractLogbackTest {
   public InstrumentationExtension getInstrumentationExtension() {
     return agentTesting;
   }
+
+  @Test
+  void resourceAttributes() {
+    logger.info("log message 1");
+
+    List<ILoggingEvent> events = listAppender.list;
+
+    assertThat(events.size()).isEqualTo(1);
+    assertThat(events.get(0).getMessage()).isEqualTo("log message 1");
+    assertThat(events.get(0).getMDCPropertyMap().get("trace_id")).isNull();
+    assertThat(events.get(0).getMDCPropertyMap().get("span_id")).isNull();
+    assertThat(events.get(0).getMDCPropertyMap().get("trace_flags")).isNull();
+    assertThat(events.get(0).getMDCPropertyMap().get("service.name"))
+        .isEqualTo("unknown_service:java");
+    assertThat(events.get(0).getMDCPropertyMap().get("telemetry.sdk.language")).isEqualTo("java");
+  }
 }

+ 48 - 0
javaagent-extension-api/src/main/java/io/opentelemetry/javaagent/bootstrap/internal/ConfiguredResourceAttributesHolder.java

@@ -0,0 +1,48 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.javaagent.bootstrap.internal;
+
+import static io.opentelemetry.api.common.AttributeKey.stringKey;
+
+import io.opentelemetry.api.common.Attributes;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import javax.annotation.Nullable;
+
+/**
+ * This class is internal and is hence not for public use. Its APIs are unstable and can change at
+ * any time.
+ */
+public final class ConfiguredResourceAttributesHolder {
+
+  private static final Map<String, String> resourceAttributes = new HashMap<>();
+
+  public static Map<String, String> getResourceAttributes() {
+    return resourceAttributes;
+  }
+
+  public static void initialize(Attributes resourceAttribute) {
+    List<String> mdcResourceAttributes =
+        InstrumentationConfig.get()
+            .getList(
+                "otel.instrumentation.common.mdc.resource-attributes", Collections.emptyList());
+    for (String key : mdcResourceAttributes) {
+      String value = resourceAttribute.get(stringKey(key));
+      if (value != null) {
+        ConfiguredResourceAttributesHolder.resourceAttributes.put(key, value);
+      }
+    }
+  }
+
+  @Nullable
+  public static String getAttributeValue(String key) {
+    return resourceAttributes.get(key);
+  }
+
+  private ConfiguredResourceAttributesHolder() {}
+}

+ 4 - 0
javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/AgentInstaller.java

@@ -26,6 +26,7 @@ import io.opentelemetry.javaagent.bootstrap.InstrumentedTaskClasses;
 import io.opentelemetry.javaagent.bootstrap.http.HttpServerResponseCustomizer;
 import io.opentelemetry.javaagent.bootstrap.http.HttpServerResponseCustomizerHolder;
 import io.opentelemetry.javaagent.bootstrap.http.HttpServerResponseMutator;
+import io.opentelemetry.javaagent.bootstrap.internal.ConfiguredResourceAttributesHolder;
 import io.opentelemetry.javaagent.bootstrap.internal.InstrumentationConfig;
 import io.opentelemetry.javaagent.extension.AgentListener;
 import io.opentelemetry.javaagent.extension.ignore.IgnoredTypesConfigurer;
@@ -41,6 +42,7 @@ import io.opentelemetry.javaagent.tooling.ignore.IgnoredTypesMatcher;
 import io.opentelemetry.javaagent.tooling.muzzle.AgentTooling;
 import io.opentelemetry.javaagent.tooling.util.Trie;
 import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk;
+import io.opentelemetry.sdk.autoconfigure.SdkAutoconfigureAccess;
 import io.opentelemetry.sdk.autoconfigure.internal.AutoConfigureUtil;
 import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
 import java.lang.instrument.Instrumentation;
@@ -125,6 +127,8 @@ public class AgentInstaller {
     copyNecessaryConfigToSystemProperties(sdkConfig);
 
     setBootstrapPackages(sdkConfig, extensionClassLoader);
+    ConfiguredResourceAttributesHolder.initialize(
+        SdkAutoconfigureAccess.getResourceAttributes(autoConfiguredSdk));
 
     for (BeforeAgentListener agentListener :
         loadOrdered(BeforeAgentListener.class, extensionClassLoader)) {

+ 16 - 0
javaagent-tooling/src/main/java/io/opentelemetry/sdk/autoconfigure/SdkAutoconfigureAccess.java

@@ -0,0 +1,16 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.sdk.autoconfigure;
+
+import io.opentelemetry.api.common.Attributes;
+
+public final class SdkAutoconfigureAccess {
+  public static Attributes getResourceAttributes(AutoConfiguredOpenTelemetrySdk sdk) {
+    return sdk.getResource().getAttributes();
+  }
+
+  private SdkAutoconfigureAccess() {}
+}