This is an automated email from the ASF dual-hosted git repository.
swebb2066 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/logging-log4cxx.git
The following commit(s) were added to refs/heads/master by this push:
new aa67d22b Simplify socket appender sub-classing by enhancing
SocketAppenderSkeleton (#652)
aa67d22b is described below
commit aa67d22bb527ccb4d2dcd919e99a2d872d206305
Author: Stephen Webb <[email protected]>
AuthorDate: Sat May 9 11:49:06 2026 +1000
Simplify socket appender sub-classing by enhancing SocketAppenderSkeleton
(#652)
---
src/main/cpp/nteventlogappender.cpp | 2 +-
src/main/cpp/socketappenderskeleton.cpp | 155 ++++++++++++---------
src/main/cpp/visualstudio.natvis | 2 +-
src/main/cpp/xmlsocketappender.cpp | 83 ++++-------
.../include/log4cxx/net/socketappenderskeleton.h | 90 +++++++++---
src/main/include/log4cxx/net/xmlsocketappender.h | 76 ++++------
src/main/include/log4cxx/nt/nteventlogappender.h | 4 +-
.../log4cxx/private/socketappenderskeleton_priv.h | 25 +++-
src/test/cpp/net/socketappendertestcase.cpp | 1 +
9 files changed, 241 insertions(+), 197 deletions(-)
diff --git a/src/main/cpp/nteventlogappender.cpp
b/src/main/cpp/nteventlogappender.cpp
index 553d107c..fec9447a 100644
--- a/src/main/cpp/nteventlogappender.cpp
+++ b/src/main/cpp/nteventlogappender.cpp
@@ -223,7 +223,7 @@ void NTEventLogAppender::append(
LOG4CXX_APPEND_FORMAL_PARAMETERS )
LogString oss;
Pool tempPool;
- this->m_priv->layout->format(oss, event, tempPool);
+ this->m_priv->layout->format(oss, event);
wchar_t* msgs = Transcoder::wencode(oss, tempPool);
BOOL bSuccess = ::ReportEventW(
priv->hEventLog,
diff --git a/src/main/cpp/socketappenderskeleton.cpp
b/src/main/cpp/socketappenderskeleton.cpp
index 930a74f4..00ca2aae 100644
--- a/src/main/cpp/socketappenderskeleton.cpp
+++ b/src/main/cpp/socketappenderskeleton.cpp
@@ -18,14 +18,16 @@
#define __STDC_CONSTANT_MACROS
#include <log4cxx/net/socketappenderskeleton.h>
#include <log4cxx/helpers/loglog.h>
+#include <log4cxx/helpers/charsetencoder.h>
#include <log4cxx/helpers/optionconverter.h>
#include <log4cxx/helpers/stringhelper.h>
#include <log4cxx/spi/loggingevent.h>
#include <log4cxx/helpers/threadutility.h>
#include <log4cxx/helpers/transcoder.h>
#include <log4cxx/helpers/bytearrayoutputstream.h>
+#include <log4cxx/helpers/outputstreamwriter.h>
+#include <log4cxx/helpers/socketoutputstream.h>
#include <log4cxx/helpers/threadutility.h>
-#include <log4cxx/private/appenderskeleton_priv.h>
#include <log4cxx/private/socketappenderskeleton_priv.h>
#include <functional>
#include <chrono>
@@ -41,7 +43,11 @@ SocketAppenderSkeleton::SocketAppenderSkeleton(int
defaultPort, int reconnection
{
}
+#if LOG4CXX_ABI_VERSION <= 15
SocketAppenderSkeleton::SocketAppenderSkeleton(helpers::InetAddressPtr
address, int port, int reconnectionDelay)
+#else
+SocketAppenderSkeleton::SocketAppenderSkeleton(const helpers::InetAddressPtr&
address, int port, int reconnectionDelay)
+#endif
:
AppenderSkeleton(std::make_unique<SocketAppenderSkeletonPriv>(address, port,
reconnectionDelay))
{
}
@@ -62,8 +68,7 @@ SocketAppenderSkeleton::~SocketAppenderSkeleton()
void SocketAppenderSkeleton::activateOptions(
LOG4CXX_ACTIVATE_OPTIONS_FORMAL_PARAMETERS )
{
- Pool my_pool;
- connect(my_pool);
+ _priv->connect();
}
void SocketAppenderSkeleton::close()
@@ -72,38 +77,37 @@ void SocketAppenderSkeleton::close()
_priv->close();
}
-void SocketAppenderSkeleton::connect(Pool& p)
+void SocketAppenderSkeleton::SocketAppenderSkeletonPriv::connect()
{
- if (_priv->address == 0)
+ if (this->address == 0)
{
LogLog::error(LogString(LOG4CXX_STR("No remote host is set for
Appender named \"")) +
- _priv->name + LOG4CXX_STR("\"."));
+ this->name + LOG4CXX_STR("\"."));
}
else
{
- _priv->close();
+ this->close();
try
{
if (LogLog::isDebugEnabled())
{
LogString msg(LOG4CXX_STR("Connecting to [")
- + _priv->address->toString() +
LOG4CXX_STR(":"));
- StringHelper::toString(_priv->port, msg);
+ + this->address->toString() +
LOG4CXX_STR(":"));
+ StringHelper::toString(this->port, msg);
msg += LOG4CXX_STR("].");
LogLog::debug(msg);
}
- SocketPtr socket = Socket::create(_priv->address,
_priv->port);
- setSocket(socket, p);
+ this->setOutputSink(Socket::create(this->address,
this->port));
}
catch (SocketException& e)
{
LogString msg = LOG4CXX_STR("Could not connect to [")
- + _priv->address->toString() + LOG4CXX_STR(":");
- StringHelper::toString(_priv->port, msg);
+ + this->address->toString() + LOG4CXX_STR(":");
+ StringHelper::toString(this->port, msg);
msg += LOG4CXX_STR("].");
- fireConnector(); // fire the connector thread
+ this->fireConnector(); // fire the connector thread
LogLog::warn(msg, e);
}
}
@@ -133,95 +137,99 @@ void SocketAppenderSkeleton::setOption(const LogString&
option, const LogString&
}
}
+void SocketAppenderSkeleton::SocketAppenderSkeletonPriv::fireConnector()
+{
+ std::lock_guard<std::recursive_mutex> lock(this->mutex);
+ if (this->taskName.empty())
+ {
+ this->taskName = this->name + LOG4CXX_STR(":")
+ + this->address->toString() + LOG4CXX_STR(":");
+ StringHelper::toString(this->port, this->taskName);
+ }
+ auto taskManager = ThreadUtility::instancePtr();
+ if (!taskManager->value().hasPeriodicTask(this->taskName))
+ {
+ if (LogLog::isDebugEnabled())
+ {
+ LogString msg(LOG4CXX_STR("Waiting "));
+ StringHelper::toString(this->reconnectionDelay, msg);
+ msg += LOG4CXX_STR(" ms before retrying [")
+ + this->address->toString() + LOG4CXX_STR(":");
+ StringHelper::toString(this->port, msg);
+ msg += LOG4CXX_STR("].");
+ LogLog::debug(msg);
+ }
+ taskManager->value().addPeriodicTask(this->taskName
+ ,
std::bind(&SocketAppenderSkeleton::SocketAppenderSkeletonPriv::retryConnect,
this)
+ , std::chrono::milliseconds(this->reconnectionDelay)
+ );
+ }
+ this->taskManager = taskManager;
+}
+
+#if LOG4CXX_ABI_VERSION <= 15
void SocketAppenderSkeleton::fireConnector()
{
- std::lock_guard<std::recursive_mutex> lock(_priv->mutex);
- if (_priv->taskName.empty())
- {
- _priv->taskName = _priv->name + LOG4CXX_STR(":")
- + _priv->address->toString() + LOG4CXX_STR(":");
- StringHelper::toString(_priv->port, _priv->taskName);
- }
- auto taskManager = ThreadUtility::instancePtr();
- if (!taskManager->value().hasPeriodicTask(_priv->taskName))
- {
- if (LogLog::isDebugEnabled())
- {
- LogString msg(LOG4CXX_STR("Waiting "));
- StringHelper::toString(_priv->reconnectionDelay, msg);
- msg += LOG4CXX_STR(" ms before retrying [")
- + _priv->address->toString() + LOG4CXX_STR(":");
- StringHelper::toString(_priv->port, msg);
- msg += LOG4CXX_STR("].");
- LogLog::debug(msg);
- }
- taskManager->value().addPeriodicTask(_priv->taskName
- , std::bind(&SocketAppenderSkeleton::retryConnect, this)
- , std::chrono::milliseconds(_priv->reconnectionDelay)
- );
- }
- _priv->taskManager = taskManager;
+ _priv->fireConnector();
}
+#endif
-void SocketAppenderSkeleton::retryConnect()
+void SocketAppenderSkeleton::SocketAppenderSkeletonPriv::retryConnect()
{
- if (is_closed())
+ if (this->closed)
{
- if (auto pManager = _priv->taskManager.lock())
- pManager->value().removePeriodicTask(_priv->taskName);
+ if (auto pManager = this->taskManager.lock())
+ pManager->value().removePeriodicTask(this->taskName);
}
else
{
- Pool p;
- SocketPtr socket;
try
{
if (LogLog::isDebugEnabled())
{
LogString msg(LOG4CXX_STR("Attempting
connection to [")
- + _priv->address->toString() +
LOG4CXX_STR(":"));
- StringHelper::toString(_priv->port, msg);
+ + this->address->toString() +
LOG4CXX_STR(":"));
+ StringHelper::toString(this->port, msg);
msg += LOG4CXX_STR("].");
LogLog::debug(msg);
}
- socket = Socket::create(_priv->address, _priv->port);
- setSocket(socket, p);
+ this->setOutputSink(Socket::create(this->address,
this->port));
if (LogLog::isDebugEnabled())
{
LogString msg(LOG4CXX_STR("Connection
established to [")
- + _priv->address->toString() +
LOG4CXX_STR(":"));
- StringHelper::toString(_priv->port, msg);
+ + this->address->toString() +
LOG4CXX_STR(":"));
+ StringHelper::toString(this->port, msg);
msg += LOG4CXX_STR("].");
LogLog::debug(msg);
}
- if (auto pManager = _priv->taskManager.lock())
-
pManager->value().removePeriodicTask(_priv->taskName);
+ if (auto pManager = this->taskManager.lock())
+
pManager->value().removePeriodicTask(this->taskName);
return;
}
catch (ConnectException& e)
{
LogLog::warn(LOG4CXX_STR("Remote host ")
- + _priv->address->toString()
+ + this->address->toString()
+ LOG4CXX_STR(" refused connection."), e);
}
catch (IOException& e)
{
LogString msg(LOG4CXX_STR("Could not connect to [")
- + _priv->address->toString() +
LOG4CXX_STR(":"));
- StringHelper::toString(_priv->port, msg);
+ + this->address->toString() + LOG4CXX_STR(":"));
+ StringHelper::toString(this->port, msg);
msg += LOG4CXX_STR("].");
LogLog::warn(msg, e);
}
- if (_priv->reconnectionDelay > 0)
+ if (this->reconnectionDelay > 0)
{
if (LogLog::isDebugEnabled())
{
LogString msg(LOG4CXX_STR("Waiting "));
-
StringHelper::toString(_priv->reconnectionDelay, msg);
+ StringHelper::toString(this->reconnectionDelay,
msg);
msg += LOG4CXX_STR(" ms before retrying [")
- + _priv->address->toString() +
LOG4CXX_STR(":");
- StringHelper::toString(_priv->port, msg);
+ + this->address->toString() +
LOG4CXX_STR(":");
+ StringHelper::toString(this->port, msg);
msg += LOG4CXX_STR("].");
LogLog::debug(msg);
}
@@ -229,17 +237,30 @@ void SocketAppenderSkeleton::retryConnect()
}
}
+void SocketAppenderSkeleton::SocketAppenderSkeletonPriv::setOutputSink(const
SocketPtr& socket)
+{
+ OutputStreamPtr os = std::make_shared<SocketOutputStream>(socket);
+ auto charset = CharsetEncoder::getUTF8Encoder();
+ this->outputSink = std::make_shared<OutputStreamWriter>(os, charset);
+}
+
void SocketAppenderSkeleton::SocketAppenderSkeletonPriv::close()
{
if (this->taskName.empty())
;
else if (auto pManager = this->taskManager.lock())
pManager->value().removePeriodicTask(this->taskName);
-}
-
-bool SocketAppenderSkeleton::is_closed()
-{
- return _priv->closed;
+ if (this->outputSink)
+ {
+ try
+ {
+ this->outputSink->close();
+ this->outputSink.reset();
+ }
+ catch (std::exception&)
+ {
+ }
+ }
}
void SocketAppenderSkeleton::setRemoteHost(const LogString& host)
@@ -283,7 +304,7 @@ void SocketAppenderSkeleton::setReconnectionDelay(int
reconnectionDelay1)
{
pManager->value().removePeriodicTask(_priv->taskName);
pManager->value().addPeriodicTask(_priv->taskName
- , std::bind(&SocketAppenderSkeleton::retryConnect, this)
+ ,
std::bind(&SocketAppenderSkeleton::SocketAppenderSkeletonPriv::retryConnect,
_priv)
, std::chrono::milliseconds(_priv->reconnectionDelay)
);
}
diff --git a/src/main/cpp/visualstudio.natvis b/src/main/cpp/visualstudio.natvis
index 267f5056..f713e474 100644
--- a/src/main/cpp/visualstudio.natvis
+++ b/src/main/cpp/visualstudio.natvis
@@ -59,7 +59,7 @@
<Type Name="log4cxx::net::XMLSocketAppender">
<Expand>
<Item Name="m_priv">
-
static_cast<XMLSocketAppenderPriv*>(m_priv._Mypair._Myval2)
+
static_cast<SocketAppenderSkeletonPriv*>(m_priv._Mypair._Myval2)
</Item>
</Expand>
</Type>
diff --git a/src/main/cpp/xmlsocketappender.cpp
b/src/main/cpp/xmlsocketappender.cpp
index 7793626b..60a2860a 100644
--- a/src/main/cpp/xmlsocketappender.cpp
+++ b/src/main/cpp/xmlsocketappender.cpp
@@ -17,42 +17,32 @@
#include <log4cxx/net/xmlsocketappender.h>
#include <log4cxx/helpers/loglog.h>
-#include <log4cxx/helpers/outputstreamwriter.h>
-#include <log4cxx/helpers/charsetencoder.h>
-#include <log4cxx/helpers/optionconverter.h>
-#include <log4cxx/helpers/stringhelper.h>
#include <log4cxx/xml/xmllayout.h>
-#include <log4cxx/level.h>
-#include <log4cxx/helpers/transform.h>
-#include <log4cxx/helpers/transcoder.h>
-#include <log4cxx/helpers/socketoutputstream.h>
-#include <log4cxx/private/appenderskeleton_priv.h>
#include <log4cxx/private/socketappenderskeleton_priv.h>
using namespace LOG4CXX_NS;
-using namespace LOG4CXX_NS::helpers;
using namespace LOG4CXX_NS::net;
-using namespace LOG4CXX_NS::xml;
+#if LOG4CXX_ABI_VERSION <= 15
struct XMLSocketAppender::XMLSocketAppenderPriv : public
SocketAppenderSkeletonPriv
{
XMLSocketAppenderPriv(int defaultPort, int reconnectionDelay) :
SocketAppenderSkeletonPriv(defaultPort, reconnectionDelay) {}
- XMLSocketAppenderPriv(InetAddressPtr address, int defaultPort, int
reconnectionDelay) :
+ XMLSocketAppenderPriv(helpers::InetAddressPtr address, int defaultPort,
int reconnectionDelay) :
SocketAppenderSkeletonPriv( address, defaultPort,
reconnectionDelay ) {}
XMLSocketAppenderPriv(const LogString& host, int port, int delay) :
SocketAppenderSkeletonPriv( host, port, delay ) {}
- LOG4CXX_NS::helpers::WriterPtr writer;
+ LOG4CXX_NS::helpers::WriterPtr unused_writer;
- void close() override;
};
+#endif
IMPLEMENT_LOG4CXX_OBJECT(XMLSocketAppender)
-#define _priv static_cast<XMLSocketAppenderPriv*>(m_priv.get())
+#define _priv static_cast<SocketAppenderSkeletonPriv*>(m_priv.get())
// The default port number of remote logging server (4560)
int XMLSocketAppender::DEFAULT_PORT = 4560;
@@ -60,32 +50,36 @@ int XMLSocketAppender::DEFAULT_PORT = 4560;
// The default reconnection delay (30000 milliseconds or 30 seconds).
int XMLSocketAppender::DEFAULT_RECONNECTION_DELAY = 30000;
+#if LOG4CXX_ABI_VERSION <= 15
const int XMLSocketAppender::MAX_EVENT_LEN = 1024;
+#endif
XMLSocketAppender::XMLSocketAppender()
- :
SocketAppenderSkeleton(std::make_unique<XMLSocketAppenderPriv>(DEFAULT_PORT,
DEFAULT_RECONNECTION_DELAY))
+ :
SocketAppenderSkeleton(std::make_unique<SocketAppenderSkeletonPriv>(DEFAULT_PORT,
DEFAULT_RECONNECTION_DELAY))
{
- _priv->layout = std::make_shared<XMLLayout>();
+ _priv->layout = std::make_shared<xml::XMLLayout>();
}
-XMLSocketAppender::XMLSocketAppender(InetAddressPtr address1, int port1)
- :
SocketAppenderSkeleton(std::make_unique<XMLSocketAppenderPriv>(address1, port1,
DEFAULT_RECONNECTION_DELAY))
+#if LOG4CXX_ABI_VERSION <= 15
+XMLSocketAppender::XMLSocketAppender(helpers::InetAddressPtr address1, int
port1)
+#else
+XMLSocketAppender::XMLSocketAppender(const helpers::InetAddressPtr& address1,
int port1)
+#endif
+ :
SocketAppenderSkeleton(std::make_unique<SocketAppenderSkeletonPriv>(address1,
port1, DEFAULT_RECONNECTION_DELAY))
{
- _priv->layout = std::make_shared<XMLLayout>();
+ _priv->layout = std::make_shared<xml::XMLLayout>();
activateOptions();
}
XMLSocketAppender::XMLSocketAppender(const LogString& host, int port1)
- : SocketAppenderSkeleton(std::make_unique<XMLSocketAppenderPriv>(host,
port1, DEFAULT_RECONNECTION_DELAY))
+ :
SocketAppenderSkeleton(std::make_unique<SocketAppenderSkeletonPriv>(host,
port1, DEFAULT_RECONNECTION_DELAY))
{
- _priv->layout = std::make_shared<XMLLayout>();
+ _priv->layout = std::make_shared<xml::XMLLayout>();
activateOptions();
}
XMLSocketAppender::~XMLSocketAppender()
{
- if (_priv->setClosed())
- _priv->close();
}
@@ -99,57 +93,40 @@ int XMLSocketAppender::getDefaultPort() const
return DEFAULT_PORT;
}
-void XMLSocketAppender::setSocket(LOG4CXX_NS::helpers::SocketPtr& socket,
Pool& p)
+#if LOG4CXX_ABI_VERSION <= 15
+void XMLSocketAppender::setSocket(LOG4CXX_NS::helpers::SocketPtr& socket,
helpers::Pool& p)
{
- OutputStreamPtr os = std::make_shared<SocketOutputStream>(socket);
- CharsetEncoderPtr charset(CharsetEncoder::getUTF8Encoder());
- std::lock_guard<std::recursive_mutex> lock(_priv->mutex);
- _priv->writer = std::make_shared<OutputStreamWriter>(os, charset);
+ static auto silenceABIchecker =
std::make_unique<XMLSocketAppenderPriv>(DEFAULT_PORT,
DEFAULT_RECONNECTION_DELAY);
+ _priv->setOutputSink(socket);
}
-#if LOG4CXX_ABI_VERSION <= 15
-void XMLSocketAppender::cleanUp(Pool& p)
+
+void XMLSocketAppender::cleanUp(helpers::Pool& p)
{
_priv->close();
}
#endif
-void XMLSocketAppender::XMLSocketAppenderPriv::close()
-{
- SocketAppenderSkeletonPriv::close();
- if (this->writer)
- {
- try
- {
- this->writer->close();
- this->writer = nullptr;
- }
- catch (std::exception&)
- {
- }
- }
-}
-
void XMLSocketAppender::append( LOG4CXX_APPEND_FORMAL_PARAMETERS )
{
- if (_priv->writer)
+ if (_priv->outputSink)
{
LogString output;
_priv->layout->format(output, event);
try
{
- _priv->writer->write(output);
- _priv->writer->flush();
+ _priv->outputSink->write(output);
+ _priv->outputSink->flush();
}
catch (std::exception& e)
{
- _priv->writer = nullptr;
- LogLog::warn(LOG4CXX_STR("Detected problem with
connection: "), e);
+ _priv->outputSink.reset();
+ helpers::LogLog::warn(LOG4CXX_STR("Detected problem
with connection: "), e);
if (getReconnectionDelay() > 0)
{
- fireConnector();
+ _priv->fireConnector();
}
}
}
diff --git a/src/main/include/log4cxx/net/socketappenderskeleton.h
b/src/main/include/log4cxx/net/socketappenderskeleton.h
index afb0c530..c96f50ec 100644
--- a/src/main/include/log4cxx/net/socketappenderskeleton.h
+++ b/src/main/include/log4cxx/net/socketappenderskeleton.h
@@ -19,9 +19,11 @@
#define _LOG4CXX_NET_SOCKET_APPENDER_SKELETON_H
#include <log4cxx/appenderskeleton.h>
+#include <log4cxx/helpers/inetaddress.h>
+#if LOG4CXX_ABI_VERSION <= 15
#include <log4cxx/helpers/socket.h>
-#include <thread>
-#include <condition_variable>
+#endif
+
namespace LOG4CXX_NS
{
@@ -30,7 +32,53 @@ namespace net
{
/**
- * Abstract base class for SocketAppender and XMLSocketAppender
+Abstract base class that sends spi::LoggingEvent elements to a remote server.
+
+\anchor socket_appender_properties
+This appender has the following properties:
+
+- The event will be logged with the same time stamp,
+NDC, location info as if it were logged locally by
+the client.
+
+- Remote logging uses the TCP protocol,
+so if the server is reachable,
+log events will eventually arrive at the server.
+
+- If the remote server is down, the logging requests are simply dropped.
+However, if and when the server comes back up,
+then event transmission is resumed transparently.
+This transparent reconneciton is performed by a <em>connector</em>
+task which periodically attempts to connect to the server.
+
+- Logging events are automatically <em>buffered</em> by the
+native TCP implementation. This means that if the link to server
+is slow but still faster than the rate of (log) event production
+by the client, the client will not be affected by the slow
+network connection. However, if the network connection is slower
+then the rate of event production, then the client can only
+progress at the network rate. In particular, if the network link
+to the the server is down, the client will be blocked.
+On the other hand, if the network link is up, but the server
+is down, the client will not be blocked when making log requests
+but the log events will be lost due to server unavailability.
+
+- If the application hosting this appender exits before it is closed,
+either explicitly or subsequent to destruction,
+then there might be untransmitted data in the pipe which might be lost.
+
+To avoid lost data, it is usually sufficient to
+#close the appender either explicitly or by
+calling the LogManager#shutdown method
+before exiting the application.
+
+A periodic task will connect when the server becomes available.
+It does this by attempting to open a new connection every
+<code>reconnectionDelay</code> milliseconds.
+
+The periodic task stops trying whenever a connection is established.
+It will restart attempting to open a new connection to the server
+when a previously open connection is droppped.
*/
class LOG4CXX_EXPORT SocketAppenderSkeleton : public AppenderSkeleton
{
@@ -44,8 +92,11 @@ class LOG4CXX_EXPORT SocketAppenderSkeleton : public
AppenderSkeleton
/**
Connects to remote server at <code>address</code> and
<code>port</code>.
*/
+#if LOG4CXX_ABI_VERSION <= 15
SocketAppenderSkeleton(helpers::InetAddressPtr address, int
port, int reconnectionDelay);
-
+#else
+ SocketAppenderSkeleton(const helpers::InetAddressPtr& address,
int port, int reconnectionDelay);
+#endif
/**
Connects to remote server at <code>host</code> and
<code>port</code>.
*/
@@ -61,7 +112,7 @@ class LOG4CXX_EXPORT SocketAppenderSkeleton : public
AppenderSkeleton
void close() override;
-
+#if LOG4CXX_ABI_VERSION <= 15
/**
* This appender does not use a layout. Hence, this method
* returns <code>false</code>.
@@ -71,7 +122,7 @@ class LOG4CXX_EXPORT SocketAppenderSkeleton : public
AppenderSkeleton
{
return false;
}
-
+#endif
/**
* The <b>RemoteHost</b> option takes a string value which
should be
* the host name of the server where a
@@ -123,7 +174,12 @@ class LOG4CXX_EXPORT SocketAppenderSkeleton : public
AppenderSkeleton
*/
int getReconnectionDelay() const;
+#if LOG4CXX_ABI_VERSION <= 15
+ /**
+ @deprecated This method will be removed in a future version.
+ */
void fireConnector();
+#endif
/**
\copybrief AppenderSkeleton::setOption()
@@ -145,9 +201,15 @@ class LOG4CXX_EXPORT SocketAppenderSkeleton : public
AppenderSkeleton
protected:
SocketAppenderSkeleton(std::unique_ptr<SocketAppenderSkeletonPriv> priv);
- virtual void setSocket(LOG4CXX_NS::helpers::SocketPtr& socket,
LOG4CXX_NS::helpers::Pool& p) = 0;
-
#if LOG4CXX_ABI_VERSION <= 15
+ /**
+ @deprecated This method will be removed in a future version.
+ */
+ virtual void setSocket(helpers::SocketPtr& socket,
helpers::Pool& p) = 0;
+
+ /**
+ @deprecated This method will be removed in a future version.
+ */
virtual void cleanUp(LOG4CXX_NS::helpers::Pool& p) = 0;
#endif
virtual int getDefaultDelay() const = 0;
@@ -155,19 +217,7 @@ class LOG4CXX_EXPORT SocketAppenderSkeleton : public
AppenderSkeleton
virtual int getDefaultPort() const = 0;
private:
- void connect(LOG4CXX_NS::helpers::Pool& p);
- /**
- The Connector will reconnect when the server becomes
available
- again. It does this by attempting to open a new
connection every
- <code>reconnectionDelay</code> milliseconds.
-
- <p>It stops trying whenever a connection is established.
It will
- restart to try reconnect to the server when previously open
- connection is droppped.
- */
- void retryConnect();
- bool is_closed();
SocketAppenderSkeleton(const SocketAppenderSkeleton&);
SocketAppenderSkeleton& operator=(const
SocketAppenderSkeleton&);
diff --git a/src/main/include/log4cxx/net/xmlsocketappender.h
b/src/main/include/log4cxx/net/xmlsocketappender.h
index f22f036f..68c99bcd 100644
--- a/src/main/include/log4cxx/net/xmlsocketappender.h
+++ b/src/main/include/log4cxx/net/xmlsocketappender.h
@@ -19,7 +19,6 @@
#define _LOG4CXX_NET_XML_SOCKET_APPENDER_H
#include <log4cxx/net/socketappenderskeleton.h>
-#include <log4cxx/helpers/writer.h>
namespace LOG4CXX_NS
{
@@ -47,53 +46,7 @@ running on the same system as the application:
</log4j:configuration>
~~~
-<p>XMLSocketAppender has the following properties:
-
-- The event will be logged with the same time stamp,
-NDC, location info as if it were logged locally by
-the client.
-
-- Remote logging uses the TCP protocol. Consequently, if
-the server is reachable, then log events will eventually arrive
-at the server.
-
-- If the remote server is down, the logging requests are
-simply dropped. However, if and when the server comes back up,
-then event transmission is resumed transparently. This
-transparent reconneciton is performed by a <em>connector</em>
-thread which periodically attempts to connect to the server.
-
-- Logging events are automatically <em>buffered</em> by the
-native TCP implementation. This means that if the link to server
-is slow but still faster than the rate of (log) event production
-by the client, the client will not be affected by the slow
-network connection. However, if the network connection is slower
-then the rate of event production, then the client can only
-progress at the network rate. In particular, if the network link
-to the the server is down, the client will be blocked.
-@n @n On the other hand, if the network link is up, but the server
-is down, the client will not be blocked when making log requests
-but the log events will be lost due to server unavailability.
-
-- Even if an <code>XMLSocketAppender</code> is no longer
-attached to any logger, it will not be destroyed in
-the presence of a connector thread. A connector thread exists
-only if the connection to the server is down. To avoid this
-destruction problem, you should #close the the
-<code>XMLSocketAppender</code> explicitly. See also next item.
-@n @n Long lived applications which create/destroy many
-<code>XMLSocketAppender</code> instances should be aware of this
-destruction problem. Most other applications can safely
-ignore it.
-
-- If the application hosting the <code>XMLSocketAppender</code>
-exits before the <code>XMLSocketAppender</code> is closed either
-explicitly or subsequent to destruction, then there might
-be untransmitted data in the pipe which might be lost.
-@n @n To avoid lost data, it is usually sufficient to
-#close the <code>XMLSocketAppender</code> either explicitly or by
-calling the LogManager#shutdown method
-before exiting the application.
+See \ref socket_appender_properties "SocketAppenderSkeleton" for more
information on the behaviour this appender.
*/
class LOG4CXX_EXPORT XMLSocketAppender : public SocketAppenderSkeleton
@@ -109,10 +62,12 @@ class LOG4CXX_EXPORT XMLSocketAppender : public
SocketAppenderSkeleton
*/
static int DEFAULT_RECONNECTION_DELAY;
+#if LOG4CXX_ABI_VERSION <= 15
/**
Unused
*/
static const int MAX_EVENT_LEN;
+#endif
DECLARE_LOG4CXX_OBJECT(XMLSocketAppender)
BEGIN_LOG4CXX_CAST_MAP()
@@ -126,7 +81,11 @@ class LOG4CXX_EXPORT XMLSocketAppender : public
SocketAppenderSkeleton
/**
Connects to remote server at <code>address</code> and
<code>port</code>.
*/
+#if LOG4CXX_ABI_VERSION <= 15
XMLSocketAppender(helpers::InetAddressPtr address, int port);
+#else
+ XMLSocketAppender(const helpers::InetAddressPtr& address, int
port);
+#endif
/**
Connects to remote server at <code>host</code> and
<code>port</code>.
@@ -135,10 +94,27 @@ class LOG4CXX_EXPORT XMLSocketAppender : public
SocketAppenderSkeleton
using SocketAppenderSkeleton::activateOptions;
+#if 15 < LOG4CXX_ABI_VERSION
+ /**
+ * This appender has a default layout.
+ * @returns false
+ */
+ bool requiresLayout() const override
+ {
+ return false;
+ }
+#endif
+
protected:
+#if LOG4CXX_ABI_VERSION <= 15
+ /**
+ @deprecated This method will be removed in a future version.
+ */
void setSocket(LOG4CXX_NS::helpers::SocketPtr& socket,
helpers::Pool& p) override;
-#if LOG4CXX_ABI_VERSION <= 15
+ /**
+ @deprecated This method will be removed in a future version.
+ */
void cleanUp(helpers::Pool& p) override;
#endif
int getDefaultDelay() const override;
@@ -152,7 +128,9 @@ class LOG4CXX_EXPORT XMLSocketAppender : public
SocketAppenderSkeleton
XMLSocketAppender(const XMLSocketAppender&);
XMLSocketAppender& operator=(const XMLSocketAppender&);
+#if LOG4CXX_ABI_VERSION <= 15
struct XMLSocketAppenderPriv;
+#endif
}; // class XMLSocketAppender
LOG4CXX_PTR_DEF(XMLSocketAppender);
diff --git a/src/main/include/log4cxx/nt/nteventlogappender.h
b/src/main/include/log4cxx/nt/nteventlogappender.h
index 2ebbf969..d88154a7 100644
--- a/src/main/include/log4cxx/nt/nteventlogappender.h
+++ b/src/main/include/log4cxx/nt/nteventlogappender.h
@@ -69,8 +69,8 @@ class LOG4CXX_EXPORT NTEventLogAppender : public
AppenderSkeleton
void setOption(const LogString& option, const LogString& value)
override;
/**
- * The SocketAppender does not use a layout. Hence, this method
- * returns <code>false</code>.
+ * This appender does need a layout.
+ * returns <code>true</code>.
*
*/
bool requiresLayout() const override
diff --git a/src/main/include/log4cxx/private/socketappenderskeleton_priv.h
b/src/main/include/log4cxx/private/socketappenderskeleton_priv.h
index 4e31bb29..e92f0f4e 100644
--- a/src/main/include/log4cxx/private/socketappenderskeleton_priv.h
+++ b/src/main/include/log4cxx/private/socketappenderskeleton_priv.h
@@ -19,8 +19,9 @@
#include <log4cxx/net/socketappenderskeleton.h>
#include <log4cxx/private/appenderskeleton_priv.h>
-#include <log4cxx/helpers/inetaddress.h>
+#include <log4cxx/helpers/socket.h>
#include <log4cxx/helpers/threadutility.h>
+#include <log4cxx/helpers/writer.h>
namespace LOG4CXX_NS
{
@@ -38,7 +39,7 @@ struct SocketAppenderSkeleton::SocketAppenderSkeletonPriv :
public AppenderSkele
locationInfo(false)
{ }
- SocketAppenderSkeletonPriv(helpers::InetAddressPtr address, int
defaultPort, int reconnectionDelay) :
+ SocketAppenderSkeletonPriv(const helpers::InetAddressPtr& address, int
defaultPort, int reconnectionDelay) :
AppenderSkeletonPrivate(),
remoteHost(),
address(address),
@@ -56,8 +57,10 @@ struct SocketAppenderSkeleton::SocketAppenderSkeletonPriv :
public AppenderSkele
locationInfo(false)
{ }
- virtual ~SocketAppenderSkeletonPriv()
+ ~SocketAppenderSkeletonPriv()
{
+ if (this->setClosed())
+ this->close();
}
/**
@@ -73,7 +76,7 @@ struct SocketAppenderSkeleton::SocketAppenderSkeletonPriv :
public AppenderSkele
int port;
int reconnectionDelay;
bool locationInfo;
- virtual void close();
+ void close();
/**
Manages asynchronous reconnection attempts.
@@ -84,6 +87,20 @@ struct SocketAppenderSkeleton::SocketAppenderSkeletonPriv :
public AppenderSkele
The reconnection task name.
*/
LogString taskName;
+
+ /**
+ The sink for formatted logging events.
+ */
+ helpers::WriterPtr outputSink;
+
+ void connect();
+
+ void fireConnector();
+
+ void setOutputSink(const helpers::SocketPtr& socket);
+
+ void retryConnect();
+
};
} // namespace net
diff --git a/src/test/cpp/net/socketappendertestcase.cpp
b/src/test/cpp/net/socketappendertestcase.cpp
index 4a67661e..aed44689 100644
--- a/src/test/cpp/net/socketappendertestcase.cpp
+++ b/src/test/cpp/net/socketappendertestcase.cpp
@@ -25,6 +25,7 @@
#include <log4cxx/helpers/transcoder.h>
#include <log4cxx/private/aprsocket.h>
#include <apr_network_io.h>
+#include <thread>
namespace LOG4CXX_NS { namespace net {
using SocketAppender = XMLSocketAppender;