Skip to content

Commit

Permalink
Document a way to avoid SIOF when extending log4cxx (#395)
Browse files Browse the repository at this point in the history
* SIOF can only be avoided by using a DSO/DLL

* Promote Extending page before Qt page in index

* Link filtering to the flow chart
  • Loading branch information
swebb2066 authored Jul 26, 2024
1 parent 3010779 commit 2a4b764
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 14 deletions.
14 changes: 9 additions & 5 deletions src/examples/cpp/custom-appender.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@
#include <log4cxx/helpers/stringhelper.h>
#include <log4cxx/xml/domconfigurator.h>

namespace LOG4CXX_NS {
using namespace LOG4CXX_NS;

namespace com::foo {

class NullWriterAppender : public AppenderSkeleton {
public:
Expand All @@ -47,8 +49,12 @@ class NullWriterAppender : public AppenderSkeleton {
}

void setOption(const LogString& option, const LogString& value) override {
if (helpers::StringHelper::equalsIgnoreCase(option,
LOG4CXX_STR("SOMEVALUE"), LOG4CXX_STR("somevalue"))){
if (helpers::StringHelper::equalsIgnoreCase
( option
, LOG4CXX_STR("SOMEVALUE")
, LOG4CXX_STR("somevalue")
))
{
// Do something with the 'value' here.
}
}
Expand All @@ -60,8 +66,6 @@ IMPLEMENT_LOG4CXX_OBJECT(NullWriterAppender)

int main( int argc, char** argv )
{
using namespace log4cxx;

xml::DOMConfigurator::configure( "custom-appender.xml" );

LoggerPtr rootLogger = Logger::getRootLogger();
Expand Down
2 changes: 1 addition & 1 deletion src/site/markdown/1-usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@ See the following pages for usage information:
* @subpage concepts
* @subpage configuration-samples
* @subpage filters
* @subpage extending-log4cxx
* @subpage qt-support
* @subpage stacktrace-support
* @subpage extending-log4cxx
* @subpage threading
* @subpage multiprocess-logging
* @subpage environment-variables
Expand Down
28 changes: 23 additions & 5 deletions src/site/markdown/extending.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,9 @@ log4cxx.AppenderSkeleton so that we don't need to implement all of
the virtual methods that are defined in log4cxx.Appender:

~~~{.cpp}
namespace log4cxx {
using namespace log4cxx;
namespace com::foo {
class NullWriterAppender : public AppenderSkeleton {
};
Expand All @@ -44,7 +46,9 @@ Next, we need to add in a few macros in order to properly register
our new appender with Log4cxx:

~~~{.cpp}
namespace log4cxx {
using namespace log4cxx;
namespace com::foo {
class NullWriterAppender : public AppenderSkeleton {
public:
Expand All @@ -61,9 +65,21 @@ IMPLEMENT_LOG4CXX_OBJECT(NullWriterAppender)
}
~~~

These macros tell Log4cxx what the name of our class is, as well as giving
Log4cxx a way of instansiating our class. Without these macros, the custom
class will not work.
These macros allow Log4cxx to instantiate your class and provide log4cxx::cast.
The `DECLARE_LOG4CXX_OBJECT` macro adds method declarations and
the `IMPLEMENT_LOG4CXX_OBJECT` macro adds implementations.
The `IMPLEMENT_LOG4CXX_OBJECT` also adds a static reference value
which is initialized during program startup
by calling, for example, `NullWriterAppender::registerClass()`.

To avoid [Static Initialization Order Fiasco](https://en.cppreference.com/w/cpp/language/siof)
when configuring Log4cxx during static initialization
(as in [the recommended runtime configuration technique])
you should put your extension classes (and the `IMPLEMENT_LOG4CXX_OBJECT` macro)
in a dynamic library (DSO/DLL) that is loaded before loading the Log4cxx configuration.
Alternatively, you could call `NullWriterAppender::registerClass()`
before loading the configuration.
Multiple `registerClass()` calls do no harm.

Now, let's add some basic functionality to our class. As the name of
our class implies, we are going to do nothing with our appender here, as
Expand Down Expand Up @@ -149,3 +165,5 @@ This example shows how to extend Log4cxx with a new appender.

\example custom-appender.xml
This example shows how to use a new appender in a configuration file.

[the recommended runtime configuration technique]:quick-start.html#configuration
8 changes: 5 additions & 3 deletions src/site/markdown/filters.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,9 @@ hierarchy.
When dealing with large amounts of logging information, it can be useful
to filter on messages that we are interested in. This filtering only
takes places after determining that the level of the current logger would
log the message in the first place. When defining filters, note that
they can only be defined on a per-appender basis, they do not globally
affect anything.
log the message in the first place (as shown in detail by [the flow chart]).
Note that filters can only be applied on a per-appender basis,
they do not globally affect anything.

The filtering system is similar in concept to Linux iptables rules, in
that there is a chain of filters that can accept a log message, deny the
Expand Down Expand Up @@ -276,3 +276,5 @@ ignore each iteration of the loop.

\example ndc-example.cpp
This example shows how to add a context string to each logging message using the NDC.

[the flow chart]:log-flow.html

0 comments on commit 2a4b764

Please sign in to comment.