Skip to content

Commit

Permalink
Documentation improvements.
Browse files Browse the repository at this point in the history
- Add code examples Markdown document.
- Fix PDF build issue related to Travis CI test status icon.
- Include examples.md in final log4cplus.pdf.
  • Loading branch information
wilx committed Mar 22, 2016
1 parent b6dbd0c commit 65e4c32
Show file tree
Hide file tree
Showing 3 changed files with 328 additions and 4 deletions.
4 changes: 0 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,6 @@ configuration. It is modeled after the Java log4j API.

[log4cplus]: https://sourceforge.net/projects/log4cplus/

Branches | Travis-CI | AppVeyor-CI |
----------------|--------------- |-------------|-
master | [![Build Status](https://travis-ci.org/log4cplus/log4cplus.svg?branch=master)](https://travis-ci.org/log4cplus/log4cplus) | TBD |
-------------------------------------------------

Latest Project Information
==========================
Expand Down
327 changes: 327 additions & 0 deletions docs/examples.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,327 @@
# Code Examples

## Hello World

Here is a minimal [log4cplus] example for [log4cplus] version 2.0 and later:

~~~~{.cpp}
#include <log4cplus/logger.h>
#include <log4cplus/loggingmacros.h>
#include <log4cplus/configurator.h>
#include <log4cplus/initializer.h>
int
main()
{
// Initialization and deinitialization.
log4cplus::Initializer initializer;
log4cplus::BasicConfigurator config;
config.configure();
log4cplus::Logger logger = log4cplus::Logger::getInstance(
LOG4CPLUS_TEXT("main"));
LOG4CPLUS_WARN(logger, LOG4CPLUS_TEXT("Hello, World!"));
return 0;
}
~~~~

The above code prints `WARN - Hello, World!` on console. Let's dissect it:

~~~~{.cpp}
#include <log4cplus/logger.h>
~~~~

We need this header to get `Logger` class which represents a handle to named
logger.

~~~~{.cpp}
#include <log4cplus/loggingmacros.h>
~~~~

This header declares `LOG4CPLUS_WARN()` logging macro. Beside this one, it also
declares one for each standard logging level: FATAL, ERROR, WARN, INFO, DEBUG,
TRACE.

~~~~{.cpp}
#include <log4cplus/configurator.h>
~~~~

This header declares `BasicConfigurator` class.

~~~~{.cpp}
#include <log4cplus/initializer.h>
~~~~

This header declares `Initializer` class.

~~~~{.cpp}
log4cplus::Initializer initializer;
~~~~

Instantiating the `Initializer` class internally initializes [log4cplus].

The `Initializer` class also maintains a reference count. The class can be
instantiated multiple times. When this reference count reaches zero, after the
last instance of `Initializer` is destroyed, it shuts down [log4cplus]
internals. Currently, after [log4cplus] is deinitialized, it cannot be
re-initialized.

[log4cplus] tries to use some other methods of shutting down its
internals. However, that means that it **_cannot be used after `main()`
exits_**.

~~~~{.cpp}
log4cplus::BasicConfigurator config;
config.configure();
~~~~

These two lines configure _root logger_ with `ConsoleAppender` and simple
layout.

~~~~{.cpp}
log4cplus::Logger logger = log4cplus::Logger::getInstance(
LOG4CPLUS_TEXT("main"));
~~~~

Here we obtain logger handle to logger named _main_.

The `LOG4CPLUS_TEXT()` macro used above has the same function as the `TEXT()`
or `_T()` macros do on Windows: In case `UNICODE` preprocessor symbol is
defined, it prefixes the string literal that is passed as its parameter with
the `L` to make it wide character string literal.

~~~~{.cpp}
LOG4CPLUS_WARN(logger, LOG4CPLUS_TEXT("Hello, World!"));
~~~~

Here we invoke the `LOG4CPLUS_WARN()` macro to log the _Hello, World!_ message
into the _main_ logger. The logged message will be propagated from the _main_
logger towards the _root logger_ which has a `ConsoleAppender` attached to it
to print it on console.

Internally, this macro uses C++ string stream to format the _Hello, World!_
message. The consequence of this is that you can use all of the standard C++
streams manipulators.


## (De-)Initialization

### Initialization

In most cases, [log4cplus] is initialized before `main()` is executed. However,
depending on compiler, platform, run time libraries and how log4cplus is linked
to, it is possible it will not be initialized automatically. This is why
initializing [log4cplus] on top of `main()` is a good rule of thumb.

As the previous code example shows, initialization of [log4cplus] is done by
instantiation of `log4cplus::Initializer` class. This is true for [log4cplus]
versions 2.0 and later. In previous versions, instead of instantiating this
class (the header `log4cplus/initializer.h` and the class do not exist there),
call to function `log4cplus::initialize()` is used.

### Deinitialization

[log4cplus] tries to deinitialize itself and free all of its allocated
resources after `main()` exits. However, again, depending on compiler, platform
and run time libraries, it might not be possible. This is why proper
deinitialization is _necessary_.

In version 2.0 and later, it is done by the last instance of
`log4cplus::Initializer` class and its destructor. In previous versions,
calling `Logger::shutdown()` was the proper shutdown method.

## Logging macros

As we have mentioned earlier, `LOG4CPLUS_WARN()`, `LOG4CPLUS_ERROR()`, etc.,
macros use C++ string stream under the hood. The following example demonstrates
how is it possible to use it with the macros.

Beside these macros, there are two more groups of logging macros.
`LOG4CPLUS_*_STR()` can be used for logging messages that are just plain
strings that do not need any kind of formatting. There is also group of
`LOG4CPLUS_*_FMT()` macros which format logged message using `printf()`
formatting string.

~~~~{.cpp}
#include <log4cplus/logger.h>
#include <log4cplus/loggingmacros.h>
#include <log4cplus/configurator.h>
#include <log4cplus/initializer.h>
#include <iomanip>
int
main()
{
log4cplus::Initializer initializer;
log4cplus::BasicConfigurator config;
config.configure();
log4cplus::Logger logger = log4cplus::Logger::getInstance(
LOG4CPLUS_TEXT("main"));
LOG4CPLUS_INFO(logger,
LOG4CPLUS_TEXT("This is")
<< LOG4CPLUS_TEXT(" a reall")
<< LOG4CPLUS_TEXT("y long message.") << std::endl
<< LOG4CPLUS_TEXT("Just testing it out") << std::endl
<< LOG4CPLUS_TEXT("What do you think?"));
LOG4CPLUS_INFO(logger, LOG4CPLUS_TEXT("This is a bool: ") << true);
LOG4CPLUS_INFO(logger, LOG4CPLUS_TEXT("This is a char: ")
<< LOG4CPLUS_TEXT('x'));
LOG4CPLUS_INFO(logger, LOG4CPLUS_TEXT("This is a short: ")
<< static_cast<short>(-100));
LOG4CPLUS_INFO(logger, LOG4CPLUS_TEXT("This is a unsigned short: ")
<< static_cast<unsigned short>(100));
LOG4CPLUS_INFO(logger, LOG4CPLUS_TEXT("This is a int: ") << 1000);
LOG4CPLUS_INFO(logger, LOG4CPLUS_TEXT("This is a unsigned int: ") << 1000U);
LOG4CPLUS_INFO(logger, LOG4CPLUS_TEXT("This is a long(hex): ")
<< std::hex << 100000000L);
LOG4CPLUS_INFO(logger, LOG4CPLUS_TEXT("This is a unsigned long: ")
<< static_cast<unsigned long>(100000000U));
LOG4CPLUS_INFO(logger, LOG4CPLUS_TEXT("This is a float: ") << 1.2345f);
LOG4CPLUS_INFO(logger, LOG4CPLUS_TEXT("This is a double: ")
<< std::setprecision(15)
<< 1.2345234234);
LOG4CPLUS_INFO(logger, LOG4CPLUS_TEXT("This is a long double: ")
<< std::setprecision(15)
<< 123452342342.342L);
return 0;
}
~~~~

The code above should just print the expected:

~~~~
INFO - This is a really long message.
Just testing it out
What do you think?
INFO - This is a bool: 1
INFO - This is a char: x
INFO - This is a short: -100
INFO - This is a unsigned short: 100
INFO - This is a int: 1000
INFO - This is a unsigned int: 1000
INFO - This is a long(hex): 5f5e100
INFO - This is a unsigned long: 100000000
INFO - This is a float: 1.2345
INFO - This is a double: 1.2345234234
INFO - This is a long double: 123452342342.342
~~~~

Beside these macros, there are two more groups of logging macros.
`LOG4CPLUS_*_STR()` can be used for logging messages that are just plain
strings that do not need any kind of formatting. There is also group of
`LOG4CPLUS_*_FMT()` macros which format logged message using `printf()`
formatting string.


## Log level

This example shows how log messages can be filtered at run time by adjusting
the _log level threshold_ on `Logger` instance.

~~~~{.cpp}
#include <log4cplus/logger.h>
#include <log4cplus/loglevel.h>
#include <log4cplus/loggingmacros.h>
#include <log4cplus/configurator.h>
#include <log4cplus/initializer.h>
#include <iomanip>
void
printMessages(log4cplus::Logger const & logger)
{
// Print messages using all common log levels.
LOG4CPLUS_TRACE (logger, "printMessages()");
LOG4CPLUS_DEBUG (logger, "This is a DEBUG message");
LOG4CPLUS_INFO (logger, "This is a INFO message");
LOG4CPLUS_WARN (logger, "This is a WARN message");
LOG4CPLUS_ERROR (logger, "This is a ERROR message");
LOG4CPLUS_FATAL (logger, "This is a FATAL message");
}
void
thresholdTest(log4cplus::LogLevel ll)
{
log4cplus::Logger logger
= log4cplus::Logger::getInstance(LOG4CPLUS_TEXT("main"));
// Set log level threshold on logger.
logger.setLogLevel(ll);
// Print messages.
log4cplus::tcout
<< LOG4CPLUS_TEXT("*** calling printMessages() with ")
<< log4cplus::getLogLevelManager().toString(ll)
<< LOG4CPLUS_TEXT(" set: ***")
<< std::endl;
printMessages(logger);
log4cplus::tcout << std::endl;
}
int
main()
{
log4cplus::Initializer initializer;
log4cplus::BasicConfigurator config;
config.configure();
thresholdTest(log4cplus::TRACE_LOG_LEVEL);
thresholdTest(log4cplus::DEBUG_LOG_LEVEL);
thresholdTest(log4cplus::INFO_LOG_LEVEL);
thresholdTest(log4cplus::WARN_LOG_LEVEL);
thresholdTest(log4cplus::ERROR_LOG_LEVEL);
thresholdTest(log4cplus::FATAL_LOG_LEVEL);
return 0;
}
~~~~

The code prints fewer and fewer messages as the log level threshold is being
risen.

~~~~
*** calling printMessages() with TRACE set: ***
TRACE - printMessages()
DEBUG - This is a DEBUG message
INFO - This is a INFO message
WARN - This is a WARN message
ERROR - This is a ERROR message
FATAL - This is a FATAL message
*** calling printMessages() with DEBUG set: ***
DEBUG - This is a DEBUG message
INFO - This is a INFO message
WARN - This is a WARN message
ERROR - This is a ERROR message
FATAL - This is a FATAL message
*** calling printMessages() with INFO set: ***
INFO - This is a INFO message
WARN - This is a WARN message
ERROR - This is a ERROR message
FATAL - This is a FATAL message
*** calling printMessages() with WARN set: ***
WARN - This is a WARN message
ERROR - This is a ERROR message
FATAL - This is a FATAL message
*** calling printMessages() with ERROR set: ***
ERROR - This is a ERROR message
FATAL - This is a FATAL message
*** calling printMessages() with FATAL set: ***
FATAL - This is a FATAL message
~~~~

## More examples

See sources in `tests/` directory in [log4cplus] source distribution for more
examples of [log4cplus] usage.

[log4cplus]: https://sourceforge.net/projects/log4cplus/
1 change: 1 addition & 0 deletions scripts/build-pdf.pl
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

my @FILES =
( 'README.md'
, 'docs/examples.md'
, 'docs/unicode.txt'
, 'docs/release.txt'
, 'AUTHORS'
Expand Down

0 comments on commit 65e4c32

Please sign in to comment.