1

I'm newbie working with a logging system, but it's something very useful to add to your programs.

Summarizing my problem. I use the logging library log4cplus

I doing and easy example with two simple classes and the main program.

That's my error log:

  • log4cplus:ERROR No appenders could be found for logger (main).
  • log4cplus:ERROR Please initialize the log4cplus system properly.
  • Segmentation fault: 11

The problem is i don't know how to solve the problem with the appender.

That's basic code of my example. Class1.h

#include <iostream>

#include <log4cplus/configurator.h>
#include <log4cplus/logger.h>

using namespace std;
// Use the log4cplus namespace
using namespace log4cplus;

class one
{
    private:
        // Create the logger
        Logger logger;

    public:
        bool flag;
        int valor;

        one();  
        int multiplica(int a);  
};

Class1.cpp

one::one()
{
    logger.getInstance(LOG4CPLUS_TEXT("Clase One - constructor.")); 
}

int one::multiplica(int a)
{
    int sol = 0;

    sol = valor * a;

    // Imprimo un mesaje en el log.
    LOG4CPLUS_INFO(logger, "El resultado de la multiplicación es: xx");

    return sol;
}

Class2.h

#include <iostream>

#include <log4cplus/configurator.h>
#include <log4cplus/logger.h>

using namespace std;
// Use the log4cplus namespace
using namespace log4cplus;

class two
{
    private:
        // Create the logger
        Logger logger;

    public:
        bool flag;
        int valor;

        two();
        int suma(int a);    
};

Class.cpp

two::two()
{
    logger.getInstance(LOG4CPLUS_TEXT("Clase Two - DEconstructor.")); 
}

int two::suma(int a)
{
    int sol = 0;

    sol = valor + a;

    // Imprimo un mesaje en el log.
    LOG4CPLUS_INFO(logger, "El resultado de la suma es: YY ");

    return sol;
}

main.cpp

int main(int argc, char** argv)
{
    // Load the properties
    PropertyConfigurator::doConfigure("logClase.properties");
    Logger logger = Logger::getInstance(LOG4CPLUS_TEXT("main"));

    // Log with INFO level
    if (logger.isEnabledFor(INFO_LOG_LEVEL))
    {
        LOG4CPLUS_INFO(logger, "Application startup");
    }

        one uno;
        two dos;

        uno.valor = dos.valor = 4;
        uno.multiplica(7);
        dos.suma(7);

    // Log with INFO level
    if (logger.isEnabledFor(INFO_LOG_LEVEL))
    {
        LOG4CPLUS_INFO(logger, "Application shutdown");
    }

    return 0;
}

What i'm doing wrong ??? That's the correct way to work with the logging system ??

I use a simple properties file to save all the log messages in a file.

That's my logClase.properties file to configure de logger.

log4cplus.rootLogger=INFO, STDOUT, FILEAPPENDER
log4cplus.logger.main=INFO
log4cplus.logger.utils=FILEAPPENDER

log4cplus.appender.STDOUT=log4cplus::ConsoleAppender
log4cplus.appender.STDOUT.layout=log4cplus::PatternLayout
log4cplus.appender.STDOUT.layout.ConversionPattern=%d{%m/%d/%y %H:%M:%S} [%t] %-5p %c{2} %%%x%% - %m [%l]%n

log4cplus.appender.FILEAPPENDER=log4cplus::RollingFileAppender
log4cplus.appender.FILEAPPENDER.File=KlasseEx.log
log4cplus.appender.FILEAPPENDER.MaxFileSize=5MB
#log4cplus.appender.FILEAPPENDER.MaxFileSize=500KB
log4cplus.appender.FILEAPPENDER.MaxBackupIndex=1
log4cplus.appender.FILEAPPENDER.layout=log4cplus::PatternLayout
log4cplus.appender.FILEAPPENDER.layout.ConversionPattern=%d{%m/%d/%y %H:%M:%S} [%t] %-5p %c{2} %%%x%% - %m [%l]%n

I want to use FILEAPPENDER and the Console appender to throw messages in a file and into the console. I think that's not must be so difficult to do, it must be easy to do it.

wilx
  • 17,697
  • 6
  • 59
  • 114
Jorge Vega Sánchez
  • 7,430
  • 14
  • 55
  • 77
  • What version of log4cplus and build system and compiler are you using? Is it MinGW? Are you using log4cplus as DLL? I have recently fixed one problem in MinGW/DLL code that could be causing it. – wilx Sep 17 '12 at 20:12
  • OSX 10.8 and latest version of log4cplus. I compile my code with a makefile without errors. – Jorge Vega Sánchez Sep 17 '12 at 20:43
  • That is one platform that I have no way of testing. Please try to obtain a stack trace using a debugger. Also, just for sure, state the log4cplus version number, please. – wilx Sep 17 '12 at 21:03

2 Answers2

2

See for appenders in log4cplus documentation. You probably missing some step of intialitation of this logger - I mean you did not add appenders.

See http://www.codeproject.com/Articles/15955/logging-made-easy-in-your-c-applications

After:

Logger logger = Logger::getInstance(LOG4CPLUS_TEXT("main"));

Missing:

SharedAppenderPtr consoleAppender(new ConsoleAppender());
consoleAppender->setName("myAppenderName");
consoleAppender->setLayout(new log4cplus::TTCCLayout());
logger.addAppender(consoleAppender);
Alexis Wilke
  • 19,179
  • 10
  • 84
  • 156
PiotrNycz
  • 23,099
  • 7
  • 66
  • 112
  • 1
    He calls `PropertyConfigurator::doConfigure("logClase.properties");` so it should be initialized, unless something's wrong in the configuration file. – Alexis Wilke Oct 28 '15 at 10:48
0

PiotrNycz mentioned that you indeed needed to do more initialization steps for your log4cplus logging, particularly adding appenders. I want to elaborate more on that.

Documentation states that prior to version 2.0 initialization is to be done with:

log4cplus::initialize();

and deinitialization, by calling shutdown() on the Logger like so:

log4cplus::Logger::getRoot().shutdown();

, while after version 2.0, initialization is supposed to occur with instantiating the RAII class log4cplus::Initializer initializer; and deinitialization when that instance is destructed.

However I have version 2.0.0 and the prior method is what actually has worked for me. With the 2nd method I was getting the exact same error you did.

Then a minimal implementation of logging for a class could be like so:

const wchar_t* PATTERN = LOG_PATTERN; // optional - create an initial log status message
log4cplus::SharedAppenderPtr consoleApp(new log4cplus::ConsoleAppender());  // for console output
consoleApp->setLayout(std::unique_ptr<log4cplus::Layout>(new log4cplus::PatternLayout(PATTERN))); // again optional
log4cplus::Logger m_logger = log4cplus::Logger::getRoot();  // get root logger
m_logger.setLogLevel(log4cplus::ALL_LOG_LEVEL);     // set root logger log level

// finally add appenders
this->m_logger.addAppender(consoleApp); // at least one appender must be set in order for you to be able to actually log to the console or file or to an output device (multiple appender types exist).

Now, a custom MyLogger class should minimally contain a log4cplus::Logger, logging functions - like the following logError - and the initialization steps mentioned above done in its constructor. Also, it needs a member function GetLogger defined as such: log4cplus::Logger* GetLogger(const char* logger = DEFAULT_LOGGER); to acquire a MyLogger instance and use it as a member of a class for which you want to provide the logging facilities.

To log a specific message you also need a function like this in MyLogger:

template<typename... Args>
inline void logError(const char* stringOptionallyFormatted, Args&&... args)
{
    LOG4CPLUS_ERROR_FMT(m_logger, fmt, std::forward<Args>(args)...);
}

(Likewise for other log levels.)

Now instantiate a logger instance in some class's constructor (or in main):

MyLogger myLoggerInstance;
myLoggerInstance.GetLogger(L"File System Logger");

and log with:

myLoggerInstance.logError|Info|Debug("like today is %s No%d", "Sunday", 7 );

or:

logger.logDebug(L"no formatted string");


Additional notes:

  • I have found documenetation for log4cplus to be relatively poor. This (which is for log4j! - the java original) tutorial is the best one I have found. It explains the basics very well. Then the page I linked above as well.
  • Make sure you call log4cplus::initialize() first thing in main to prevent SIOF.
  • Typically you want one Logger member object per class you're interested in.
  • If you're working on a multithreaded application call log4cplus::threadCleanup(); as an additional de-initialization step after calling shutdown.
  • Only a trivial hello world app link wouldn't need an appender.
KeyC0de
  • 4,728
  • 8
  • 44
  • 68