From 10bca8b2b2482e83272c8cfc353ede89999a84ce Mon Sep 17 00:00:00 2001
From: jack-berg <34418638+jack-berg@users.noreply.github.com>
Date: Wed, 23 Oct 2024 14:28:41 -0500
Subject: [PATCH] Enable reusuable_data memory mode by default (#6799)

---
 .../internal/ExporterBuilderUtil.java         | 12 +++++++++++-
 .../OtlpHttpLogRecordExporterBuilder.java     |  2 +-
 .../OtlpHttpMetricExporterBuilder.java        |  2 +-
 .../trace/OtlpHttpSpanExporterBuilder.java    |  2 +-
 .../OtlpGrpcLogRecordExporterBuilder.java     |  2 +-
 .../OtlpGrpcMetricExporterBuilder.java        |  2 +-
 .../trace/OtlpGrpcSpanExporterBuilder.java    |  2 +-
 .../OtlpLogRecordExporterProviderTest.java    | 12 ++++++------
 .../OtlpMetricExporterProviderTest.java       | 12 ++++++------
 .../OtlpSpanExporterProviderTest.java         | 14 +++++++-------
 .../testing/internal/FakeTelemetryUtil.java   | 19 ++++++++-----------
 .../prometheus/PrometheusHttpServer.java      | 11 +++++++++--
 .../PrometheusHttpServerBuilder.java          |  8 +++++++-
 .../prometheus/PrometheusHttpServerTest.java  |  4 +++-
 .../PrometheusMetricReaderProviderTest.java   |  6 +++---
 15 files changed, 66 insertions(+), 44 deletions(-)

diff --git a/exporters/common/src/main/java/io/opentelemetry/exporter/internal/ExporterBuilderUtil.java b/exporters/common/src/main/java/io/opentelemetry/exporter/internal/ExporterBuilderUtil.java
index 4e05183bb1a..9e3a1fcf266 100644
--- a/exporters/common/src/main/java/io/opentelemetry/exporter/internal/ExporterBuilderUtil.java
+++ b/exporters/common/src/main/java/io/opentelemetry/exporter/internal/ExporterBuilderUtil.java
@@ -21,6 +21,7 @@
 import java.net.URISyntaxException;
 import java.util.Locale;
 import java.util.function.Consumer;
+import java.util.logging.Logger;
 
 /**
  * Utilities for exporter builders.
@@ -30,6 +31,8 @@
  */
 public final class ExporterBuilderUtil {
 
+  private static final Logger logger = Logger.getLogger(ExporterBuilderUtil.class.getName());
+
   /** Validate OTLP endpoint. */
   public static URI validateEndpoint(String endpoint) {
     URI uri;
@@ -50,7 +53,14 @@ public static URI validateEndpoint(String endpoint) {
   /** Invoke the {@code memoryModeConsumer} with the configured {@link MemoryMode}. */
   public static void configureExporterMemoryMode(
       ConfigProperties config, Consumer<MemoryMode> memoryModeConsumer) {
-    String memoryModeStr = config.getString("otel.java.experimental.exporter.memory_mode");
+    String memoryModeStr = config.getString("otel.java.exporter.memory_mode");
+    if (memoryModeStr == null) {
+      memoryModeStr = config.getString("otel.java.experimental.exporter.memory_mode");
+      if (memoryModeStr != null) {
+        logger.warning(
+            "otel.java.experimental.exporter.memory_mode was set but has been replaced with otel.java.exporter.memory_mode and will be removed in a future release");
+      }
+    }
     if (memoryModeStr == null) {
       return;
     }
diff --git a/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/http/logs/OtlpHttpLogRecordExporterBuilder.java b/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/http/logs/OtlpHttpLogRecordExporterBuilder.java
index 0d2654051f4..0602cf2b506 100644
--- a/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/http/logs/OtlpHttpLogRecordExporterBuilder.java
+++ b/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/http/logs/OtlpHttpLogRecordExporterBuilder.java
@@ -35,7 +35,7 @@
 public final class OtlpHttpLogRecordExporterBuilder {
 
   private static final String DEFAULT_ENDPOINT = "http://localhost:4318/v1/logs";
-  private static final MemoryMode DEFAULT_MEMORY_MODE = MemoryMode.IMMUTABLE_DATA;
+  private static final MemoryMode DEFAULT_MEMORY_MODE = MemoryMode.REUSABLE_DATA;
 
   private final HttpExporterBuilder<Marshaler> delegate;
   private MemoryMode memoryMode;
diff --git a/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/http/metrics/OtlpHttpMetricExporterBuilder.java b/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/http/metrics/OtlpHttpMetricExporterBuilder.java
index 49a1c45183d..e0cb6f4a493 100644
--- a/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/http/metrics/OtlpHttpMetricExporterBuilder.java
+++ b/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/http/metrics/OtlpHttpMetricExporterBuilder.java
@@ -43,7 +43,7 @@ public final class OtlpHttpMetricExporterBuilder {
 
   private static final AggregationTemporalitySelector DEFAULT_AGGREGATION_TEMPORALITY_SELECTOR =
       AggregationTemporalitySelector.alwaysCumulative();
-  private static final MemoryMode DEFAULT_MEMORY_MODE = MemoryMode.IMMUTABLE_DATA;
+  private static final MemoryMode DEFAULT_MEMORY_MODE = MemoryMode.REUSABLE_DATA;
 
   private final HttpExporterBuilder<Marshaler> delegate;
   private AggregationTemporalitySelector aggregationTemporalitySelector =
diff --git a/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/http/trace/OtlpHttpSpanExporterBuilder.java b/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/http/trace/OtlpHttpSpanExporterBuilder.java
index fe91ceb6da7..fb547af942a 100644
--- a/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/http/trace/OtlpHttpSpanExporterBuilder.java
+++ b/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/http/trace/OtlpHttpSpanExporterBuilder.java
@@ -35,7 +35,7 @@
 public final class OtlpHttpSpanExporterBuilder {
 
   private static final String DEFAULT_ENDPOINT = "http://localhost:4318/v1/traces";
-  private static final MemoryMode DEFAULT_MEMORY_MODE = MemoryMode.IMMUTABLE_DATA;
+  private static final MemoryMode DEFAULT_MEMORY_MODE = MemoryMode.REUSABLE_DATA;
 
   private final HttpExporterBuilder<Marshaler> delegate;
   private MemoryMode memoryMode;
diff --git a/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/logs/OtlpGrpcLogRecordExporterBuilder.java b/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/logs/OtlpGrpcLogRecordExporterBuilder.java
index 8f082855b75..2ab6e29be09 100644
--- a/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/logs/OtlpGrpcLogRecordExporterBuilder.java
+++ b/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/logs/OtlpGrpcLogRecordExporterBuilder.java
@@ -43,7 +43,7 @@ public final class OtlpGrpcLogRecordExporterBuilder {
   private static final String DEFAULT_ENDPOINT_URL = "http://localhost:4317";
   private static final URI DEFAULT_ENDPOINT = URI.create(DEFAULT_ENDPOINT_URL);
   private static final long DEFAULT_TIMEOUT_SECS = 10;
-  private static final MemoryMode DEFAULT_MEMORY_MODE = MemoryMode.IMMUTABLE_DATA;
+  private static final MemoryMode DEFAULT_MEMORY_MODE = MemoryMode.REUSABLE_DATA;
 
   // Visible for testing
   final GrpcExporterBuilder<Marshaler> delegate;
diff --git a/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/metrics/OtlpGrpcMetricExporterBuilder.java b/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/metrics/OtlpGrpcMetricExporterBuilder.java
index 4a975e257c6..c6f02dec4c7 100644
--- a/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/metrics/OtlpGrpcMetricExporterBuilder.java
+++ b/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/metrics/OtlpGrpcMetricExporterBuilder.java
@@ -50,7 +50,7 @@ public final class OtlpGrpcMetricExporterBuilder {
   private static final long DEFAULT_TIMEOUT_SECS = 10;
   private static final AggregationTemporalitySelector DEFAULT_AGGREGATION_TEMPORALITY_SELECTOR =
       AggregationTemporalitySelector.alwaysCumulative();
-  private static final MemoryMode DEFAULT_MEMORY_MODE = MemoryMode.IMMUTABLE_DATA;
+  private static final MemoryMode DEFAULT_MEMORY_MODE = MemoryMode.REUSABLE_DATA;
 
   // Visible for testing
   final GrpcExporterBuilder<Marshaler> delegate;
diff --git a/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/trace/OtlpGrpcSpanExporterBuilder.java b/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/trace/OtlpGrpcSpanExporterBuilder.java
index 370c3b5bd2c..0a24398eeed 100644
--- a/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/trace/OtlpGrpcSpanExporterBuilder.java
+++ b/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/trace/OtlpGrpcSpanExporterBuilder.java
@@ -39,7 +39,7 @@ public final class OtlpGrpcSpanExporterBuilder {
   private static final String DEFAULT_ENDPOINT_URL = "http://localhost:4317";
   private static final URI DEFAULT_ENDPOINT = URI.create(DEFAULT_ENDPOINT_URL);
   private static final long DEFAULT_TIMEOUT_SECS = 10;
-  private static final MemoryMode DEFAULT_MEMORY_MODE = MemoryMode.IMMUTABLE_DATA;
+  private static final MemoryMode DEFAULT_MEMORY_MODE = MemoryMode.REUSABLE_DATA;
 
   // Visible for testing
   final GrpcExporterBuilder<Marshaler> delegate;
diff --git a/exporters/otlp/all/src/test/java/io/opentelemetry/exporter/otlp/internal/OtlpLogRecordExporterProviderTest.java b/exporters/otlp/all/src/test/java/io/opentelemetry/exporter/otlp/internal/OtlpLogRecordExporterProviderTest.java
index bab89d8a69a..47ed7859cd7 100644
--- a/exporters/otlp/all/src/test/java/io/opentelemetry/exporter/otlp/internal/OtlpLogRecordExporterProviderTest.java
+++ b/exporters/otlp/all/src/test/java/io/opentelemetry/exporter/otlp/internal/OtlpLogRecordExporterProviderTest.java
@@ -129,7 +129,7 @@ void createExporter_GrpcDefaults() {
       verify(grpcBuilder, never()).setTrustedCertificates(any());
       verify(grpcBuilder, never()).setClientTls(any(), any());
       assertThat(grpcBuilder).extracting("delegate").extracting("retryPolicy").isNotNull();
-      getMemoryMode(exporter).isEqualTo(MemoryMode.IMMUTABLE_DATA);
+      getMemoryMode(exporter).isEqualTo(MemoryMode.REUSABLE_DATA);
     }
     Mockito.verifyNoInteractions(httpBuilder);
   }
@@ -183,7 +183,7 @@ void createExporter_GrpcWithSignalConfiguration() throws CertificateEncodingExce
     config.put("otel.exporter.otlp.logs.compression", "gzip");
     config.put("otel.exporter.otlp.timeout", "1s");
     config.put("otel.exporter.otlp.logs.timeout", "15s");
-    config.put("otel.java.experimental.exporter.memory_mode", "reusable_data");
+    config.put("otel.java.exporter.memory_mode", "immutable_data");
 
     try (LogRecordExporter exporter =
         provider.createExporter(DefaultConfigProperties.createFromMap(config))) {
@@ -196,7 +196,7 @@ void createExporter_GrpcWithSignalConfiguration() throws CertificateEncodingExce
       verify(grpcBuilder).setTrustedCertificates(serverTls.certificate().getEncoded());
       verify(grpcBuilder)
           .setClientTls(clientTls.privateKey().getEncoded(), clientTls.certificate().getEncoded());
-      getMemoryMode(exporter).isEqualTo(MemoryMode.REUSABLE_DATA);
+      getMemoryMode(exporter).isEqualTo(MemoryMode.IMMUTABLE_DATA);
     }
     Mockito.verifyNoInteractions(httpBuilder);
   }
@@ -216,7 +216,7 @@ void createExporter_HttpDefaults() {
       verify(httpBuilder, never()).setTrustedCertificates(any());
       verify(httpBuilder, never()).setClientTls(any(), any());
       assertThat(httpBuilder).extracting("delegate").extracting("retryPolicy").isNotNull();
-      getMemoryMode(exporter).isEqualTo(MemoryMode.IMMUTABLE_DATA);
+      getMemoryMode(exporter).isEqualTo(MemoryMode.REUSABLE_DATA);
     }
     Mockito.verifyNoInteractions(grpcBuilder);
   }
@@ -269,7 +269,7 @@ void createExporter_HttpWithSignalConfiguration() throws CertificateEncodingExce
     config.put("otel.exporter.otlp.logs.compression", "gzip");
     config.put("otel.exporter.otlp.timeout", "1s");
     config.put("otel.exporter.otlp.logs.timeout", "15s");
-    config.put("otel.java.experimental.exporter.memory_mode", "reusable_data");
+    config.put("otel.java.exporter.memory_mode", "immutable_data");
 
     try (LogRecordExporter exporter =
         provider.createExporter(DefaultConfigProperties.createFromMap(config))) {
@@ -282,7 +282,7 @@ void createExporter_HttpWithSignalConfiguration() throws CertificateEncodingExce
       verify(httpBuilder).setTrustedCertificates(serverTls.certificate().getEncoded());
       verify(httpBuilder)
           .setClientTls(clientTls.privateKey().getEncoded(), clientTls.certificate().getEncoded());
-      getMemoryMode(exporter).isEqualTo(MemoryMode.REUSABLE_DATA);
+      getMemoryMode(exporter).isEqualTo(MemoryMode.IMMUTABLE_DATA);
     }
     Mockito.verifyNoInteractions(grpcBuilder);
   }
diff --git a/exporters/otlp/all/src/test/java/io/opentelemetry/exporter/otlp/internal/OtlpMetricExporterProviderTest.java b/exporters/otlp/all/src/test/java/io/opentelemetry/exporter/otlp/internal/OtlpMetricExporterProviderTest.java
index 3956b4f62d8..3d0a4098328 100644
--- a/exporters/otlp/all/src/test/java/io/opentelemetry/exporter/otlp/internal/OtlpMetricExporterProviderTest.java
+++ b/exporters/otlp/all/src/test/java/io/opentelemetry/exporter/otlp/internal/OtlpMetricExporterProviderTest.java
@@ -128,7 +128,7 @@ void createExporter_GrpcDefaults() {
       verify(grpcBuilder, never()).setTrustedCertificates(any());
       verify(grpcBuilder, never()).setClientTls(any(), any());
       assertThat(grpcBuilder).extracting("delegate").extracting("retryPolicy").isNotNull();
-      assertThat(exporter.getMemoryMode()).isEqualTo(MemoryMode.IMMUTABLE_DATA);
+      assertThat(exporter.getMemoryMode()).isEqualTo(MemoryMode.REUSABLE_DATA);
     }
     Mockito.verifyNoInteractions(httpBuilder);
   }
@@ -178,7 +178,7 @@ void createExporter_GrpcWithSignalConfiguration() throws CertificateEncodingExce
     config.put("otel.exporter.otlp.metrics.compression", "gzip");
     config.put("otel.exporter.otlp.timeout", "1s");
     config.put("otel.exporter.otlp.metrics.timeout", "15s");
-    config.put("otel.java.experimental.exporter.memory_mode", "reusable_data");
+    config.put("otel.java.exporter.memory_mode", "immutable_data");
 
     try (MetricExporter exporter =
         provider.createExporter(DefaultConfigProperties.createFromMap(config))) {
@@ -191,7 +191,7 @@ void createExporter_GrpcWithSignalConfiguration() throws CertificateEncodingExce
       verify(grpcBuilder).setTrustedCertificates(serverTls.certificate().getEncoded());
       verify(grpcBuilder)
           .setClientTls(clientTls.privateKey().getEncoded(), clientTls.certificate().getEncoded());
-      assertThat(exporter.getMemoryMode()).isEqualTo(MemoryMode.REUSABLE_DATA);
+      assertThat(exporter.getMemoryMode()).isEqualTo(MemoryMode.IMMUTABLE_DATA);
     }
     Mockito.verifyNoInteractions(httpBuilder);
   }
@@ -212,7 +212,7 @@ void createExporter_HttpDefaults() {
       verify(httpBuilder, never()).setTrustedCertificates(any());
       verify(httpBuilder, never()).setClientTls(any(), any());
       assertThat(httpBuilder).extracting("delegate").extracting("retryPolicy").isNotNull();
-      assertThat(exporter.getMemoryMode()).isEqualTo(MemoryMode.IMMUTABLE_DATA);
+      assertThat(exporter.getMemoryMode()).isEqualTo(MemoryMode.REUSABLE_DATA);
     }
     Mockito.verifyNoInteractions(grpcBuilder);
   }
@@ -265,7 +265,7 @@ void createExporter_HttpWithSignalConfiguration() throws CertificateEncodingExce
     config.put("otel.exporter.otlp.metrics.compression", "gzip");
     config.put("otel.exporter.otlp.timeout", "1s");
     config.put("otel.exporter.otlp.metrics.timeout", "15s");
-    config.put("otel.java.experimental.exporter.memory_mode", "reusable_data");
+    config.put("otel.java.exporter.memory_mode", "immutable_data");
 
     try (MetricExporter exporter =
         provider.createExporter(DefaultConfigProperties.createFromMap(config))) {
@@ -278,7 +278,7 @@ void createExporter_HttpWithSignalConfiguration() throws CertificateEncodingExce
       verify(httpBuilder).setTrustedCertificates(serverTls.certificate().getEncoded());
       verify(httpBuilder)
           .setClientTls(clientTls.privateKey().getEncoded(), clientTls.certificate().getEncoded());
-      assertThat(exporter.getMemoryMode()).isEqualTo(MemoryMode.REUSABLE_DATA);
+      assertThat(exporter.getMemoryMode()).isEqualTo(MemoryMode.IMMUTABLE_DATA);
     }
     Mockito.verifyNoInteractions(grpcBuilder);
   }
diff --git a/exporters/otlp/all/src/test/java/io/opentelemetry/exporter/otlp/internal/OtlpSpanExporterProviderTest.java b/exporters/otlp/all/src/test/java/io/opentelemetry/exporter/otlp/internal/OtlpSpanExporterProviderTest.java
index 084826d47ff..46d2e8ea218 100644
--- a/exporters/otlp/all/src/test/java/io/opentelemetry/exporter/otlp/internal/OtlpSpanExporterProviderTest.java
+++ b/exporters/otlp/all/src/test/java/io/opentelemetry/exporter/otlp/internal/OtlpSpanExporterProviderTest.java
@@ -130,7 +130,7 @@ void createExporter_GrpcDefaults() {
       verify(grpcBuilder, never()).setTrustedCertificates(any());
       verify(grpcBuilder, never()).setClientTls(any(), any());
       assertThat(grpcBuilder).extracting("delegate").extracting("retryPolicy").isNotNull();
-      getMemoryMode(exporter).isEqualTo(MemoryMode.IMMUTABLE_DATA);
+      getMemoryMode(exporter).isEqualTo(MemoryMode.REUSABLE_DATA);
     }
     Mockito.verifyNoInteractions(httpBuilder);
   }
@@ -184,7 +184,7 @@ void createExporter_GrpcWithSignalConfiguration() throws CertificateEncodingExce
     config.put("otel.exporter.otlp.traces.compression", "gzip");
     config.put("otel.exporter.otlp.timeout", "1s");
     config.put("otel.exporter.otlp.traces.timeout", "15s");
-    config.put("otel.java.experimental.exporter.memory_mode", "reusable_data");
+    config.put("otel.java.exporter.memory_mode", "immutable_data");
 
     try (SpanExporter exporter =
         provider.createExporter(DefaultConfigProperties.createFromMap(config))) {
@@ -197,7 +197,7 @@ void createExporter_GrpcWithSignalConfiguration() throws CertificateEncodingExce
       verify(grpcBuilder).setTrustedCertificates(serverTls.certificate().getEncoded());
       verify(grpcBuilder)
           .setClientTls(clientTls.privateKey().getEncoded(), clientTls.certificate().getEncoded());
-      getMemoryMode(exporter).isEqualTo(MemoryMode.REUSABLE_DATA);
+      getMemoryMode(exporter).isEqualTo(MemoryMode.IMMUTABLE_DATA);
     }
     Mockito.verifyNoInteractions(httpBuilder);
   }
@@ -217,7 +217,7 @@ void createExporter_HttpDefaults() {
       verify(httpBuilder, never()).setTrustedCertificates(any());
       verify(httpBuilder, never()).setClientTls(any(), any());
       assertThat(httpBuilder).extracting("delegate").extracting("retryPolicy").isNotNull();
-      getMemoryMode(exporter).isEqualTo(MemoryMode.IMMUTABLE_DATA);
+      getMemoryMode(exporter).isEqualTo(MemoryMode.REUSABLE_DATA);
     }
     Mockito.verifyNoInteractions(grpcBuilder);
   }
@@ -249,7 +249,7 @@ void createExporter_HttpWithGeneralConfiguration() throws CertificateEncodingExc
       verify(httpBuilder)
           .setClientTls(clientTls.privateKey().getEncoded(), clientTls.certificate().getEncoded());
       assertThat(httpBuilder).extracting("delegate").extracting("retryPolicy").isNull();
-      getMemoryMode(exporter).isEqualTo(MemoryMode.IMMUTABLE_DATA);
+      getMemoryMode(exporter).isEqualTo(MemoryMode.REUSABLE_DATA);
     }
     Mockito.verifyNoInteractions(grpcBuilder);
   }
@@ -273,7 +273,7 @@ void createExporter_HttpWithSignalConfiguration() throws CertificateEncodingExce
     config.put("otel.exporter.otlp.traces.compression", "gzip");
     config.put("otel.exporter.otlp.timeout", "1s");
     config.put("otel.exporter.otlp.traces.timeout", "15s");
-    config.put("otel.java.experimental.exporter.memory_mode", "reusable_data");
+    config.put("otel.java.exporter.memory_mode", "immutable_data");
 
     try (SpanExporter exporter =
         provider.createExporter(DefaultConfigProperties.createFromMap(config))) {
@@ -286,7 +286,7 @@ void createExporter_HttpWithSignalConfiguration() throws CertificateEncodingExce
       verify(httpBuilder).setTrustedCertificates(serverTls.certificate().getEncoded());
       verify(httpBuilder)
           .setClientTls(clientTls.privateKey().getEncoded(), clientTls.certificate().getEncoded());
-      getMemoryMode(exporter).isEqualTo(MemoryMode.REUSABLE_DATA);
+      getMemoryMode(exporter).isEqualTo(MemoryMode.IMMUTABLE_DATA);
     }
     Mockito.verifyNoInteractions(grpcBuilder);
   }
diff --git a/exporters/otlp/testing-internal/src/main/java/io/opentelemetry/exporter/otlp/testing/internal/FakeTelemetryUtil.java b/exporters/otlp/testing-internal/src/main/java/io/opentelemetry/exporter/otlp/testing/internal/FakeTelemetryUtil.java
index 2375e35aef1..2bdf65ef23e 100644
--- a/exporters/otlp/testing-internal/src/main/java/io/opentelemetry/exporter/otlp/testing/internal/FakeTelemetryUtil.java
+++ b/exporters/otlp/testing-internal/src/main/java/io/opentelemetry/exporter/otlp/testing/internal/FakeTelemetryUtil.java
@@ -33,6 +33,11 @@ public class FakeTelemetryUtil {
 
   private static final String TRACE_ID = "00000000000000000000000000abc123";
   private static final String SPAN_ID = "0000000000def456";
+  private static final InstrumentationScopeInfo SCOPE_INFO =
+      InstrumentationScopeInfo.builder("testLib")
+          .setVersion("1.0")
+          .setSchemaUrl("http://url")
+          .build();
 
   /** Generate a fake {@link MetricData}. */
   public static MetricData generateFakeMetricData() {
@@ -40,7 +45,7 @@ public static MetricData generateFakeMetricData() {
     long endNs = startNs + TimeUnit.MILLISECONDS.toNanos(900);
     return ImmutableMetricData.createLongSum(
         Resource.empty(),
-        InstrumentationScopeInfo.empty(),
+        SCOPE_INFO,
         "name",
         "description",
         "1",
@@ -69,11 +74,7 @@ public static SpanData generateFakeSpanData() {
         .setLinks(Collections.emptyList())
         .setTotalRecordedLinks(0)
         .setTotalRecordedEvents(0)
-        .setInstrumentationScopeInfo(
-            InstrumentationScopeInfo.builder("testLib")
-                .setVersion("1.0")
-                .setSchemaUrl("http://url")
-                .build())
+        .setInstrumentationScopeInfo(SCOPE_INFO)
         .build();
   }
 
@@ -81,11 +82,7 @@ public static SpanData generateFakeSpanData() {
   public static LogRecordData generateFakeLogRecordData() {
     return TestLogRecordData.builder()
         .setResource(Resource.getDefault())
-        .setInstrumentationScopeInfo(
-            InstrumentationScopeInfo.builder("testLib")
-                .setVersion("1.0")
-                .setSchemaUrl("http://url")
-                .build())
+        .setInstrumentationScopeInfo(SCOPE_INFO)
         .setBody("log body")
         .setAttributes(Attributes.builder().put("key", "value").build())
         .setSeverity(Severity.INFO)
diff --git a/exporters/prometheus/src/main/java/io/opentelemetry/exporter/prometheus/PrometheusHttpServer.java b/exporters/prometheus/src/main/java/io/opentelemetry/exporter/prometheus/PrometheusHttpServer.java
index 78609ee7549..d07bfb8b3ae 100644
--- a/exporters/prometheus/src/main/java/io/opentelemetry/exporter/prometheus/PrometheusHttpServer.java
+++ b/exporters/prometheus/src/main/java/io/opentelemetry/exporter/prometheus/PrometheusHttpServer.java
@@ -26,7 +26,8 @@
 import java.io.UncheckedIOException;
 import java.net.InetSocketAddress;
 import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.ThreadPoolExecutor;
 import java.util.concurrent.TimeUnit;
 import java.util.function.Predicate;
 import javax.annotation.Nullable;
@@ -82,7 +83,13 @@ public static PrometheusHttpServerBuilder builder() {
     // sequentially.
     if (memoryMode == MemoryMode.REUSABLE_DATA) {
       executor =
-          Executors.newSingleThreadExecutor(new DaemonThreadFactory("prometheus-http-server"));
+          new ThreadPoolExecutor(
+              1,
+              1,
+              0L,
+              TimeUnit.MILLISECONDS,
+              new LinkedBlockingQueue<>(),
+              new DaemonThreadFactory("prometheus-http-server"));
     }
     try {
       this.httpServer =
diff --git a/exporters/prometheus/src/main/java/io/opentelemetry/exporter/prometheus/PrometheusHttpServerBuilder.java b/exporters/prometheus/src/main/java/io/opentelemetry/exporter/prometheus/PrometheusHttpServerBuilder.java
index c1138a6ea31..b43f7e089e1 100644
--- a/exporters/prometheus/src/main/java/io/opentelemetry/exporter/prometheus/PrometheusHttpServerBuilder.java
+++ b/exporters/prometheus/src/main/java/io/opentelemetry/exporter/prometheus/PrometheusHttpServerBuilder.java
@@ -24,7 +24,7 @@ public final class PrometheusHttpServerBuilder {
 
   static final int DEFAULT_PORT = 9464;
   private static final String DEFAULT_HOST = "0.0.0.0";
-  private static final MemoryMode DEFAULT_MEMORY_MODE = MemoryMode.IMMUTABLE_DATA;
+  private static final MemoryMode DEFAULT_MEMORY_MODE = MemoryMode.REUSABLE_DATA;
 
   private String host = DEFAULT_HOST;
   private int port = DEFAULT_PORT;
@@ -46,6 +46,7 @@ public final class PrometheusHttpServerBuilder {
     this.otelScopeEnabled = builder.otelScopeEnabled;
     this.allowedResourceAttributesFilter = builder.allowedResourceAttributesFilter;
     this.executor = builder.executor;
+    this.memoryMode = builder.memoryMode;
     this.defaultAggregationSelector = builder.defaultAggregationSelector;
   }
 
@@ -150,6 +151,11 @@ public PrometheusHttpServerBuilder setDefaultAggregationSelector(
    * registered with a {@link io.opentelemetry.sdk.metrics.SdkMeterProvider}.
    */
   public PrometheusHttpServer build() {
+    if (memoryMode == MemoryMode.REUSABLE_DATA && executor != null) {
+      throw new IllegalArgumentException(
+          "MemoryMode REUSEABLE_DATA cannot be used with custom executor, "
+              + "since data may be corrupted if reading metrics concurrently");
+    }
     return new PrometheusHttpServer(
         new PrometheusHttpServerBuilder(this), // copy to prevent modification
         host,
diff --git a/exporters/prometheus/src/test/java/io/opentelemetry/exporter/prometheus/PrometheusHttpServerTest.java b/exporters/prometheus/src/test/java/io/opentelemetry/exporter/prometheus/PrometheusHttpServerTest.java
index 1ee412eff03..57726a47f63 100644
--- a/exporters/prometheus/src/test/java/io/opentelemetry/exporter/prometheus/PrometheusHttpServerTest.java
+++ b/exporters/prometheus/src/test/java/io/opentelemetry/exporter/prometheus/PrometheusHttpServerTest.java
@@ -427,6 +427,8 @@ void customExecutor() throws IOException {
         PrometheusHttpServer.builder()
             .setHost("localhost")
             .setPort(port)
+            // Memory mode must be IMMUTABLE_DATA to set custom executor
+            .setMemoryMode(MemoryMode.IMMUTABLE_DATA)
             .setExecutor(scheduledExecutor)
             .build()) {
       assertThat(server)
@@ -520,7 +522,7 @@ void toBuilder() {
     builder.setAllowedResourceAttributesFilter(resourceAttributesFilter);
 
     ExecutorService executor = Executors.newSingleThreadExecutor();
-    builder.setExecutor(executor);
+    builder.setExecutor(executor).setMemoryMode(MemoryMode.IMMUTABLE_DATA);
 
     PrometheusRegistry prometheusRegistry = new PrometheusRegistry();
     builder.setPrometheusRegistry(prometheusRegistry);
diff --git a/exporters/prometheus/src/test/java/io/opentelemetry/exporter/prometheus/internal/PrometheusMetricReaderProviderTest.java b/exporters/prometheus/src/test/java/io/opentelemetry/exporter/prometheus/internal/PrometheusMetricReaderProviderTest.java
index e1fc42382e5..7945514af96 100644
--- a/exporters/prometheus/src/test/java/io/opentelemetry/exporter/prometheus/internal/PrometheusMetricReaderProviderTest.java
+++ b/exporters/prometheus/src/test/java/io/opentelemetry/exporter/prometheus/internal/PrometheusMetricReaderProviderTest.java
@@ -62,7 +62,7 @@ void createMetricReader_Default() throws IOException {
                 assertThat(server.getAddress().getHostName()).isEqualTo("0:0:0:0:0:0:0:0");
                 assertThat(server.getAddress().getPort()).isEqualTo(9464);
               });
-      assertThat(metricReader.getMemoryMode()).isEqualTo(MemoryMode.IMMUTABLE_DATA);
+      assertThat(metricReader.getMemoryMode()).isEqualTo(MemoryMode.REUSABLE_DATA);
       assertThat(metricReader.getDefaultAggregation(InstrumentType.HISTOGRAM))
           .isEqualTo(Aggregation.defaultAggregation());
     }
@@ -81,7 +81,7 @@ void createMetricReader_WithConfiguration() throws IOException {
     Map<String, String> config = new HashMap<>();
     config.put("otel.exporter.prometheus.host", "localhost");
     config.put("otel.exporter.prometheus.port", String.valueOf(port));
-    config.put("otel.java.experimental.exporter.memory_mode", "reusable_data");
+    config.put("otel.java.exporter.memory_mode", "immutable_data");
     config.put(
         "otel.java.experimental.exporter.prometheus.metrics.default.histogram.aggregation",
         "BASE2_EXPONENTIAL_BUCKET_HISTOGRAM");
@@ -99,7 +99,7 @@ void createMetricReader_WithConfiguration() throws IOException {
                 assertThat(server.getAddress().getHostName()).isEqualTo("localhost");
                 assertThat(server.getAddress().getPort()).isEqualTo(port);
               });
-      assertThat(metricReader.getMemoryMode()).isEqualTo(MemoryMode.REUSABLE_DATA);
+      assertThat(metricReader.getMemoryMode()).isEqualTo(MemoryMode.IMMUTABLE_DATA);
       assertThat(metricReader.getDefaultAggregation(InstrumentType.HISTOGRAM))
           .isEqualTo(Aggregation.base2ExponentialBucketHistogram());
     }