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;

Reply via email to