Appender与日志系统的多类示例

时间:2012-09-17 18:07:29

标签: c++ logging append log4cplus

我是新手使用日志记录系统,但这对于添加到您的程序非常有用。

总结我的问题。我使用日志库 log4cplus

我用两个简单的类和主程序做了简单的例子。

这是我的错误日志:

  • log4cplus:ERROR找不到记录器(主)的追加器。
  • log4cplus:ERROR请正确初始化log4cplus系统。
  • 分段错误:11

问题是我不知道如何用appender解决问题。

这是我的例子的基本代码。 的 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;
}

我做错了什么? 这是使用日志系统的正确方法吗?

我使用一个简单的属性文件将所有日志消息保存在文件中。

这是我的 logClase.properties 文件,用于配置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

我想使用FILEAPPENDER和Console appender将消息放入文件并进入控制台。我认为这不一定非常困难,做起来一定很容易。

2 个答案:

答案 0 :(得分:2)

请参阅log4cplus文档中的appender。你可能错过了这个记录器的一些步骤 - 我的意思是你没有添加appender。

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

后:

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

缺失:

SharedAppenderPtr consoleAppender(new ConsoleAppender());
consoleAppender->setName("myAppenderName");
consoleAppender->setLayout(new log4cplus::TTCCLayout());
logger.addAppender(consoleAppender);

答案 1 :(得分:0)

PiotrNycz提到您确实需要为log4cplus日志记录执行更多的初始化步骤,尤其是添加追加程序。我想详细说明一下。

Documentation指出要在2.0版之前进行初始化:

log4cplus::initialize();

然后通过在shutdown()上调用Logger来取消初始化:

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

,在2.0版之后,应该通过实例化RAII类log4cplus::Initializer initializer;并在实例被销毁时取消初始化来进行初始化。

但是,我的版本为2.0.0,而先前的方法才是真正为我工作的方法。使用第二种方法时,我得到的错误与您完全相同。

然后,一个类的最小日志记录实现可能是这样的:

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).

现在,自定义MyLogger类应至少包含一个log4cplus::Logger,日志记录函数(如以下logError)以及上述初始化步骤在其构造函数中完成。另外,它需要这样定义的成员函数GetLoggerlog4cplus::Logger* GetLogger(const char* logger = DEFAULT_LOGGER);获取MyLogger实例并将其用作要为其提供日志记录功能的类的成员。

要记录特定消息,您还需要在MyLogger中使用以下功能:

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

(其他日志级别也是如此。)

现在在某个类的构造函数中(或在main中实例化记录器实例):

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

并使用以下命令登录:

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

或:

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


其他说明:

  • 我发现log4cplus的文档化相对较差。 This(适用于log4j!-Java原始版本)教程是我发现的最好的教程。它很好地解释了基础知识。然后也是我上面链接的页面。
  • 请确保首先致电log4cplus::initialize(),以防止发生SIOF。
  • 通常,每个感兴趣的类都需要一个Logger成员对象。
  • 如果您正在处理多线程应用程序,则在调用log4cplus::threadCleanup(); 之后,调用shutdown作为附加的反初始化步骤。
  • 只有一个简单的hello world应用link不需要附加器。