This is an automated email from the ASF dual-hosted git repository.
mmerli pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/pulsar.git
The following commit(s) were added to refs/heads/master by this push:
new 744d2b8ec2d [improve][broker] Log only non-default config values on
broker startup (#25545)
744d2b8ec2d is described below
commit 744d2b8ec2d870c27c2804f7fe370124eefba534
Author: Matteo Merli <[email protected]>
AuthorDate: Thu Apr 16 20:58:18 2026 -0700
[improve][broker] Log only non-default config values on broker startup
(#25545)
---
.../configuration/PulsarConfigurationLoader.java | 38 +++++++++++++++++
.../PulsarConfigurationLoaderTest.java | 48 ++++++++++++++++++++++
.../org/apache/pulsar/broker/PulsarService.java | 2 +-
3 files changed, 87 insertions(+), 1 deletion(-)
diff --git
a/pulsar-broker-common/src/main/java/org/apache/pulsar/common/configuration/PulsarConfigurationLoader.java
b/pulsar-broker-common/src/main/java/org/apache/pulsar/common/configuration/PulsarConfigurationLoader.java
index 076c692d3f6..16ea4b5132c 100644
---
a/pulsar-broker-common/src/main/java/org/apache/pulsar/common/configuration/PulsarConfigurationLoader.java
+++
b/pulsar-broker-common/src/main/java/org/apache/pulsar/common/configuration/PulsarConfigurationLoader.java
@@ -28,7 +28,9 @@ import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Modifier;
import java.util.Arrays;
import java.util.Map;
+import java.util.Objects;
import java.util.Properties;
+import java.util.TreeMap;
import lombok.CustomLog;
import org.apache.commons.lang3.StringUtils;
import org.apache.pulsar.broker.ServiceConfiguration;
@@ -224,4 +226,40 @@ public class PulsarConfigurationLoader {
public static ServiceConfiguration convertFrom(PulsarConfiguration conf)
throws RuntimeException {
return convertFrom(conf, true);
}
+
+ /**
+ * Returns the subset of configuration whose values differ from the
defaults of a freshly-instantiated
+ * configuration of the same class. Any entries in {@link
PulsarConfiguration#getProperties()} that are not
+ * declared fields are also included. Useful to log only the user-provided
overrides instead of the full
+ * configuration.
+ */
+ public static Map<String, Object>
runtimeConfigurationOverrides(PulsarConfiguration conf) {
+ try {
+ PulsarConfiguration defaults =
conf.getClass().getDeclaredConstructor().newInstance();
+ Map<String, Object> overrides = new TreeMap<>();
+ for (Field field : conf.getClass().getDeclaredFields()) {
+ if (Modifier.isStatic(field.getModifiers())) {
+ continue;
+ }
+ if (field.getDeclaredAnnotation(FieldContext.class) == null) {
+ continue;
+ }
+ field.setAccessible(true);
+ Object current = field.get(conf);
+ Object def = field.get(defaults);
+ if (!Objects.equals(current, def)) {
+ overrides.put(field.getName(), current);
+ }
+ }
+ Properties props = conf.getProperties();
+ if (props != null) {
+ for (String key : props.stringPropertyNames()) {
+ overrides.putIfAbsent(key, props.getProperty(key));
+ }
+ }
+ return overrides;
+ } catch (ReflectiveOperationException e) {
+ throw new RuntimeException("Failed to compute configuration
overrides", e);
+ }
+ }
}
diff --git
a/pulsar-broker-common/src/test/java/org/apache/pulsar/common/configuration/PulsarConfigurationLoaderTest.java
b/pulsar-broker-common/src/test/java/org/apache/pulsar/common/configuration/PulsarConfigurationLoaderTest.java
index 4cf84d7048d..6bf1fc1236b 100644
---
a/pulsar-broker-common/src/test/java/org/apache/pulsar/common/configuration/PulsarConfigurationLoaderTest.java
+++
b/pulsar-broker-common/src/test/java/org/apache/pulsar/common/configuration/PulsarConfigurationLoaderTest.java
@@ -19,11 +19,13 @@
package org.apache.pulsar.common.configuration;
import static
org.apache.pulsar.common.configuration.PulsarConfigurationLoader.isComplete;
+import static
org.apache.pulsar.common.configuration.PulsarConfigurationLoader.runtimeConfigurationOverrides;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertThrows;
import static org.testng.Assert.assertTrue;
+import com.google.common.collect.Sets;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
@@ -31,6 +33,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
+import java.util.Map;
import java.util.Optional;
import java.util.Properties;
import org.apache.bookkeeper.client.api.DigestType;
@@ -230,6 +233,51 @@ public class PulsarConfigurationLoaderTest {
assertThrows(IllegalArgumentException.class, () -> isComplete(new
TestInCompleteObjectMix()));
}
+ @Test
+ public void testRuntimeConfigurationOverrides() {
+ // A fresh configuration has no overrides.
+ assertTrue(runtimeConfigurationOverrides(new
ServiceConfiguration()).isEmpty());
+
+ ServiceConfiguration config = new ServiceConfiguration();
+
+ // String override.
+ config.setClusterName("my-cluster");
+ // int override.
+ config.setManagedLedgerDefaultEnsembleSize(5);
+ // long override.
+ config.setMetadataStoreSessionTimeoutMillis(60_000L);
+ // boolean override.
+ config.setBrokerDeleteInactiveTopicsEnabled(false);
+ // double override.
+ config.setManagedLedgerDefaultMarkDeleteRateLimit(5.0);
+ // enum override.
+ config.setManagedLedgerDigestType(DigestType.MAC);
+ // Optional<Integer> override.
+ config.setBrokerServicePort(Optional.of(7777));
+ // Set<String> override.
+ config.setSuperUserRoles(Sets.newHashSet("admin", "ops"));
+ // Setting a field to its default value: should NOT appear in
overrides.
+ config.setNumIOThreads(config.getNumIOThreads());
+ // Extra property not backed by a declared FieldContext field.
+ config.getProperties().setProperty("custom.plugin.option", "enabled");
+
+ Map<String, Object> overrides = runtimeConfigurationOverrides(config);
+
+ assertEquals(overrides.get("clusterName"), "my-cluster");
+ assertEquals(overrides.get("managedLedgerDefaultEnsembleSize"), 5);
+ assertEquals(overrides.get("metadataStoreSessionTimeoutMillis"),
60_000L);
+ assertEquals(overrides.get("brokerDeleteInactiveTopicsEnabled"),
false);
+ assertEquals(overrides.get("managedLedgerDefaultMarkDeleteRateLimit"),
5.0);
+ assertEquals(overrides.get("managedLedgerDigestType"), DigestType.MAC);
+ assertEquals(overrides.get("brokerServicePort"), Optional.of(7777));
+ assertEquals(overrides.get("superUserRoles"), Sets.newHashSet("admin",
"ops"));
+ assertEquals(overrides.get("custom.plugin.option"), "enabled");
+
+ // Unchanged fields must not appear.
+ assertFalse(overrides.containsKey("numIOThreads"));
+ assertFalse(overrides.containsKey("metadataStoreUrl"));
+ }
+
static class TestCompleteObject {
@FieldContext(required = true)
String required = "I am not null";
diff --git
a/pulsar-broker/src/main/java/org/apache/pulsar/broker/PulsarService.java
b/pulsar-broker/src/main/java/org/apache/pulsar/broker/PulsarService.java
index dabb5e0d084..aba81d8a771 100644
--- a/pulsar-broker/src/main/java/org/apache/pulsar/broker/PulsarService.java
+++ b/pulsar-broker/src/main/java/org/apache/pulsar/broker/PulsarService.java
@@ -1093,7 +1093,7 @@ public class PulsarService implements AutoCloseable,
ShutdownService {
.attr("bootstrapTimeSeconds", bootstrapTimeSeconds)
.attr("bootstrapMessage", bootstrapMessage)
.attr("cluster", config.getClusterName())
- .attr("config", config)
+ .attr("configOverrides",
PulsarConfigurationLoader.runtimeConfigurationOverrides(config))
.log("Messaging service is ready");
state = State.Started;