From 6477a7e28301b6d5d9746cf4bfb29ae4b748258d Mon Sep 17 00:00:00 2001
From: Valery Kharseko <vharseko@3a-systems.ru>
Date: Fri, 11 Sep 2026 12:44:36 +0000
Subject: [PATCH] [#911] Report the replication connections which used to be dropped in silence (#935)
---
opendj-server-legacy/src/main/java/org/opends/server/replication/service/ReplicationBroker.java | 63 +++++++++++++++++++++++++++----
1 files changed, 54 insertions(+), 9 deletions(-)
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/replication/service/ReplicationBroker.java b/opendj-server-legacy/src/main/java/org/opends/server/replication/service/ReplicationBroker.java
index adf6c7e..b99c5bb 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/replication/service/ReplicationBroker.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/replication/service/ReplicationBroker.java
@@ -1161,8 +1161,18 @@
catch (Exception e)
{
logger.traceException(e);
- errorMessage = WARN_EXCEPTION_STARTING_SESSION_PHASE.get(
- getServerId(), serverURL, getBaseDN(), stackTraceToSingleLineString(e));
+ /*
+ * The whole trace, on one line, for the server this broker is electing, which is
+ * what this message carried before it was reported for the others as well; the
+ * message alone for a server which was only contacted, whose report is not
+ * throttled. An SSLException lands here, is not paced by a connect timeout the way
+ * a refused connection is, and collectReplicationServersInfo() reruns over every
+ * URL on each reconnection: one bad certificate among several replication servers
+ * would otherwise write a full stack trace per flap cycle. The trace of those is in
+ * the trace log, which traceException() above wrote it to.
+ */
+ errorMessage = WARN_EXCEPTION_STARTING_SESSION_PHASE.get(getServerId(), serverURL, getBaseDN(),
+ keepSession ? stackTraceToSingleLineString(e) : getExceptionMessage(e));
}
finally
{
@@ -1172,16 +1182,51 @@
close(socket);
}
- if (!hasConnected && errorMessage != null && !connectionError)
+ if (!hasConnected && errorMessage != null)
{
- // There was no server waiting on this host:port
- // Log a notice and will try the next replicationServer in the list
- if (keepSession) // Log error message only for final connection
+ if (!connectionError)
{
- // log the error message only once to avoid overflowing the error log
- logger.error(errorMessage);
+ /*
+ * Report the cause for every replication server contacted, and not only for the
+ * elected one: none is ever elected when none of them answers, and this is then
+ * the only place naming why -- a refused connection, a rejected certificate, a
+ * wrong port -- next to the "unable to connect to any replication servers"
+ * summary which names none of them.
+ *
+ * connectionError is what bounds the volume, and it bounds it to one line per
+ * replication server and per attempt to connect this broker makes. It is set
+ * when an attempt reaches no replication server at all, and stays set until a
+ * session is established, so the 500 ms loop which retries a total outage
+ * reports its first pass only.
+ *
+ * It is not set while this broker is connected, so the unreachable servers of a
+ * topology which still serves this broker are reported again on each
+ * reconnection -- one line each, so a reconnection costs as many lines as there
+ * are servers it could not reach, where it used to cost none. That is the volume
+ * this reporting is worth: a broker reconnects when its session is lost, not on
+ * a schedule, and a server which cannot be reached over several reconnections is
+ * a server whose configuration or certificate needs looking at.
+ *
+ * The severity says what the failure cost this broker, not what the message is
+ * named: the elected server keeps the error it was reported with, and a server
+ * which was only contacted is a warning, so that a broker which does find a
+ * server to work with does not raise an error over the one it did not need.
+ * ERR_DS_DN_DOES_NOT_MATCH is the one message which reaches the second branch
+ * under an ERR_ name -- it is set without setting hasConnected -- and it is a
+ * permanent misconfiguration rather than a transient. It still goes out as an
+ * error for the server this broker is electing, which is the one it cannot work
+ * without, and where it is only contacted the broker has another server to work
+ * with. Before this, that path logged nothing above trace either way.
+ */
+ if (keepSession)
+ {
+ logger.error(errorMessage);
+ }
+ else
+ {
+ logger.warn(errorMessage);
+ }
}
-
logger.trace(errorMessage);
}
}
--
Gitblit v1.10.0