Merge branch 'master' into documentation-updates
diff --git a/.github/workflows/log4cxx.yml b/.github/workflows/log4cxx.yml
index d7b821e..ac725c0 100644
--- a/.github/workflows/log4cxx.yml
+++ b/.github/workflows/log4cxx.yml
@@ -45,11 +45,8 @@
steps:
- uses: actions/checkout@v2
-
- - uses: lukka/set-shell-env@v1.1
with:
- CXX: ${{ matrix.cxx }}
- CC: ${{ matrix.cc }}
+ path: main
- name: 'Configure Dependencies - Ubuntu'
if: matrix.name == 'ubuntu18-gcc' || matrix.name == 'ubuntu18-clang'
@@ -64,29 +61,49 @@
if: matrix.name == 'windows-2019' || matrix.name == 'windows-2016'
uses: actions/cache@v2
with:
- path: ${{ runner.workspace }}/vcpkg
+ path: vcpkg
key: ${{ runner.os }}-${{ matrix.name }}-cache
- - name: 'Configure Dependencies - Windows'
- if: matrix.name == 'windows-2019' || matrix.name == 'windows-2016'
- uses: lukka/run-vcpkg@v5
- id: runvcpkg
+ - name: 'Checkout VCPKG - Windows'
+ if: (matrix.name == 'windows-2019' || matrix.name == 'windows-2016') && steps.restore-vcpkg-cache.outputs.cache-hit != 'true'
+ uses: actions/checkout@v2
with:
- vcpkgArguments: apr apr-util
- vcpkgDirectory: ${{ runner.workspace }}/vcpkg/
- vcpkgGitCommitId: ffa7fd27cfa29f206d1fd2ccfc722cad4aaeef3d
- vcpkgTriplet: x64-windows
+ repository: microsoft/vcpkg
+ path: vcpkg
+ ref: ec6fe06e8da05a8157dc8581fa96b36b571c1bd5
- - name: 'run cmake'
- uses: lukka/run-cmake@v3
- with:
- cmakeListsOrSettingsJson: CMakeListsTxtAdvanced
- buildDirectory: ${{ runner.workspace }}/build
- useVcpkgToolchainFile: true
- cmakeAppendedArgs: '-DLOG4CXX_TEST_PROGRAM_PATH=C:\msys64\usr\bin'
+ - name: 'Configure Dependencies - Windows'
+ if: (matrix.name == 'windows-2019' || matrix.name == 'windows-2016') && steps.restore-vcpkg-cache.outputs.cache-hit != 'true'
+ id: runvcpkg
+ shell: pwsh
+ run: |
+ cd vcpkg
+ ./bootstrap-vcpkg.bat
+ ./vcpkg install apr apr-util --triplet=x64-windows
+
+ - name: 'run cmake - win'
+ if: (matrix.name == 'windows-2019' || matrix.name == 'windows-2016')
+ shell: pwsh
+ run: |
+ $THISDIR=Get-Location
+ cd main
+ mkdir build
+ cd build
+ cmake -DLOG4CXX_TEST_PROGRAM_PATH=C:\msys64\usr\bin "-DCMAKE_TOOLCHAIN_FILE=$THISDIR/vcpkg/scripts/buildsystems/vcpkg.cmake" -DCMAKE_CXX_COMPILER=${{ matrix.cxx }} -DCMAKE_C_COMPILER=${{ matrix.cc }} ..
+ cmake --build .
+
+ - name: 'run cmake - *nix'
+ if: matrix.name != 'windows-2019'
+ run: |
+ cd main
+ mkdir build
+ cd build
+ cmake -DCMAKE_CXX_COMPILER=${{ matrix.cxx }} -DCMAKE_C_COMPILER=${{ matrix.cc }} ..
+ cmake --build .
- name: run unit tests
shell: pwsh
run: |
- cd ${{ runner.workspace }}/build
+ cd main
+ cd build
ctest -C Debug --output-on-failure -V
diff --git a/src/main/cpp/syslogappender.cpp b/src/main/cpp/syslogappender.cpp
index f330e44..18e6478 100644
--- a/src/main/cpp/syslogappender.cpp
+++ b/src/main/cpp/syslogappender.cpp
@@ -22,10 +22,12 @@
#include <log4cxx/spi/loggingevent.h>
#include <log4cxx/level.h>
#include <log4cxx/helpers/transcoder.h>
+#include <log4cxx/helpers/optionconverter.h>
#if !defined(LOG4CXX)
#define LOG4CXX 1
#endif
#include <log4cxx/private/log4cxx_private.h>
+#include <apr_strings.h>
#if LOG4CXX_HAVE_SYSLOG
#include <syslog.h>
@@ -64,7 +66,7 @@
IMPLEMENT_LOG4CXX_OBJECT(SyslogAppender)
SyslogAppender::SyslogAppender()
- : syslogFacility(LOG_USER), facilityPrinting(false), sw(0)
+ : syslogFacility(LOG_USER), facilityPrinting(false), sw(0), maxMessageLength(1024)
{
this->initSyslogFacilityStr();
@@ -72,7 +74,7 @@
SyslogAppender::SyslogAppender(const LayoutPtr& layout1,
int syslogFacility1)
- : syslogFacility(syslogFacility1), facilityPrinting(false), sw(0)
+ : syslogFacility(syslogFacility1), facilityPrinting(false), sw(0), maxMessageLength(1024)
{
this->layout = layout1;
this->initSyslogFacilityStr();
@@ -80,7 +82,7 @@
SyslogAppender::SyslogAppender(const LayoutPtr& layout1,
const LogString& syslogHost1, int syslogFacility1)
- : syslogFacility(syslogFacility1), facilityPrinting(false), sw(0)
+ : syslogFacility(syslogFacility1), facilityPrinting(false), sw(0), maxMessageLength(1024)
{
this->layout = layout1;
this->initSyslogFacilityStr();
@@ -306,20 +308,55 @@
}
LogString msg;
+ std::string encoded;
layout->format(msg, event, p);
+ Transcoder::encode(msg, encoded);
+
+ // Split up the message if it is over maxMessageLength in size.
+ // According to RFC 3164, the max message length is 1024, however
+ // newer systems(such as syslog-ng) can go up to 8k in size for their
+ // messages. We will append (x/y) at the end of each message
+ // to indicate how far through the message we are
+ std::vector<LogString> packets;
+ if( msg.size() > maxMessageLength ){
+ LogString::iterator start = msg.begin();
+ while( start != msg.end() ){
+ LogString::iterator end = start + maxMessageLength - 12;
+ if( end > msg.end() ){
+ end = msg.end();
+ }
+ LogString newMsg = LogString( start, end );
+ packets.push_back( newMsg );
+ start = end;
+ }
+
+ int current = 1;
+ for( std::vector<LogString>::iterator it = packets.begin();
+ it != packets.end();
+ it++, current++ ){
+ char buf[12];
+ apr_snprintf( buf, sizeof(buf), "(%d/%d)", current, packets.size() );
+ LOG4CXX_DECODE_CHAR(str, buf);
+ it->append( str );
+ }
+ }else{
+ packets.push_back( msg );
+ }
+
// On the local host, we can directly use the system function 'syslog'
// if it is available
#if LOG4CXX_HAVE_SYSLOG
if (sw == 0)
{
- std::string sbuf;
- Transcoder::encode(msg, sbuf);
-
- // use of "%s" to avoid a security hole
- ::syslog(syslogFacility | event->getLevel()->getSyslogEquivalent(),
- "%s", sbuf.c_str());
+ for( std::vector<LogString>::iterator it = packets.begin();
+ it != packets.end();
+ it++ ){
+ // use of "%s" to avoid a security hole
+ ::syslog(syslogFacility | event->getLevel()->getSyslogEquivalent(),
+ "%s", it->c_str());
+ }
return;
}
@@ -334,17 +371,21 @@
return;
}
- LogString sbuf(1, 0x3C /* '<' */);
- StringHelper::toString((syslogFacility | event->getLevel()->getSyslogEquivalent()), p, sbuf);
- sbuf.append(1, (logchar) 0x3E /* '>' */);
+ for( std::vector<LogString>::iterator it = packets.begin();
+ it != packets.end();
+ it++ ){
+ LogString sbuf(1, 0x3C /* '<' */);
+ StringHelper::toString((syslogFacility | event->getLevel()->getSyslogEquivalent()), p, sbuf);
+ sbuf.append(1, (logchar) 0x3E /* '>' */);
- if (facilityPrinting)
- {
- sbuf.append(facilityStr);
+ if (facilityPrinting)
+ {
+ sbuf.append(facilityStr);
+ }
+
+ sbuf.append(*it);
+ sw->write(sbuf);
}
-
- sbuf.append(msg);
- sw->write(sbuf);
}
void SyslogAppender::activateOptions(Pool&)
@@ -361,6 +402,10 @@
{
setFacility(value);
}
+ else if (StringHelper::equalsIgnoreCase(option, LOG4CXX_STR("MAXMESSAGELENGTH"), LOG4CXX_STR("maxmessagelength")))
+ {
+ setMaxMessageLength(OptionConverter::toInt(value, 1024));
+ }
else
{
AppenderSkeleton::setOption(option, value);
diff --git a/src/main/include/log4cxx/net/syslogappender.h b/src/main/include/log4cxx/net/syslogappender.h
index 5acf92c..689fd2c 100644
--- a/src/main/include/log4cxx/net/syslogappender.h
+++ b/src/main/include/log4cxx/net/syslogappender.h
@@ -30,7 +30,19 @@
{
namespace net
{
-/** Use SyslogAppender to send log messages to a remote syslog daemon.*/
+/**
+ * Use SyslogAppender to send log messages to a remote syslog daemon.
+ *
+ * Note that by default, this appender will split up messages that are
+ * more than 1024 bytes long, for compatability with BSD syslog(see
+ * RFC 3164). Modern syslog implementations(e.g. syslog-ng) can accept
+ * messages much larger, and may have a default of 8k. You may modify
+ * the default size of the messages by setting the MaxMessageLength option.
+ *
+ * When the message is too large for the current MaxMessageLength,
+ * the packet number and total # will be appended to the end of the
+ * message like this: (5/10)
+ */
class LOG4CXX_EXPORT SyslogAppender : public AppenderSkeleton
{
public:
@@ -136,6 +148,16 @@
return facilityPrinting;
}
+ inline void setMaxMessageLength(int maxMessageLength1)
+ {
+ maxMessageLength = maxMessageLength1;
+ }
+
+ inline int getMaxMessageLength() const
+ {
+ return maxMessageLength;
+ }
+
protected:
void initSyslogFacilityStr();
@@ -145,6 +167,7 @@
helpers::SyslogWriter* sw;
LogString syslogHost;
int syslogHostPort;
+ int maxMessageLength;
private:
SyslogAppender(const SyslogAppender&);
SyslogAppender& operator=(const SyslogAppender&);