Question

I have written a wrapper library on log4cplus. My library has LogMessage function inside which i am calling log4cplus library function to store the log message.

eg. application.cpp

int main()
{
LogMessage(DEBUG_LEVEL, __FILE__, __LINE__, "This is main function");
return 0;
}

mylibrary.cpp

HRESULT
LogMessage(
__in    DWORD dwLogLevel,
__in    LPSTR lpszFileName,
__in    DWORD dwLineNumber,
__in    LPSTR lpszLogMessage
)
{
        //
        // Instantiating a console appender
        //
        SharedAppenderPtr _ConsoleAppender(new ConsoleAppender());
        _ConsoleAppender->setName(LOG4CPLUS_TEXT("AppenderName"));

        //
        // Creating a pattern to display log events
        //
        log4cplus::tstring pattern = LOG4CPLUS_TEXT("%L %F %r %d{%m/%d/%y %H:%M:%S}  %-5p %c - %m%n");

        //
        // Instantiating a layout object with PatternLayout
        //
        _Layout = std::auto_ptr<Layout>(new log4cplus::PatternLayout(pattern));

        //
        // Attaching the layout object to the appender object
        //
        _ConsoleAppender->setLayout(_Layout);

        //
        // Getting root logger and adding the Console Appender with root
        // logger
        //
        Logger::getRoot().addAppender(_ConsoleAppender);
        Logger::getRoot().setAdditivity(FALSE);

        //
        // Instantiating a logger
        //
        Logger _Logger = Logger::getInstance(LOG4CPLUS_TEXT("_Logger"));
        _Logger.addAppender(_ConsoleAppender);
        _Logger.setAdditivity(FALSE);

        //
        // Printing the log messages on the console
        //
        switch( dwLogLevel )
        {
        case DEBUG_LEVEL:
            {
                _Logger.log(DEBUG_LOG_LEVEL, lpszLogMessage, lpszFileName, dwLineNumber);
                break;
            } // DEBUG_LEVEL
        case INFO_LEVEL:
            {
                _Logger.log(INFO_LOG_LEVEL, lpszLogMessage, lpszFileName, dwLineNumber);
                break;
            } // INFO_LEVEL
        case WARN_LEVEL:
            {
                _Logger.log(WARN_LOG_LEVEL, lpszLogMessage, lpszFileName, dwLineNumber);
                break;
            } // WARN_LEVEL
        case ERROR_LEVEL:
            {
                _Logger.log(ERROR_LOG_LEVEL, lpszLogMessage, lpszFileName, dwLineNumber);
                break;
            } // ERROR_LEVEL
        case FATAL_LEVEL:
            {
                _Logger.log(FATAL_LOG_LEVEL, lpszLogMessage, lpszFileName, dwLineNumber);
                break;
            } // 
        default:
            {
                HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
                break;
            } // default
        } // switch

return hResult;
}

Now from my application i want to pass function name also.

eg. application.cpp

int main()
    {
    LogMessage(DEBUG_LEVEL, __FILE__, __LINE__, __FUNCTION__, "This is main function");
    return 0;
    }

How should i print this log message to the console screen? This below function only takes file and line number as an argument. And i want to print function name as well.

void log(LogLevel ll, const log4cplus::tstring& message,
                 const char* file=NULL, int line=-1) const;

UPDATE: Sorry i forgot to mention i have #define my LogMessage function with PrintLogMessage

#define  PrintLogMessage(dwLogLevel, lpszLogMessage) \
                                LogMessage(dwLogLevel, _FILE, __LINE__, lpszLogMessage)

So in application i am using i need to write only this line

application.cpp

int main()
{
    PrintLogMessage(DEBUG_LEVEL, "This is main function");
return 0;
}

And i want to write similar kind of

 #define  PrintLogMessage(dwLogLevel, lpszLogMessage) \
                                    LogMessage(dwLogLevel, _FILE, __LINE__, __FUNCTION__, lpszLogMessage)

for __FUNCTION__ functionality. I dont want user to write FILE, LINE, FUNCTION everytime.

Was it helpful?

Solution

Use this function from the Logger class instead:

void log (spi::InternalLoggingEvent const &) const;

Prepare the InternalLoggingEvent instance in advance. Use InternalLoggingEvent::setFunction() to set the function information on the event instance.

UPDATE

I have re-read your question and the code I think your are not using log4cplus the way it is intended.

First off, your LogMessage should not be creating appenders or attaching appenders to loggers each time it is invoked. Appenders and loggers should be set up at the start of your application.

Take a look loggingmacros.h and the macros there. You can avoid having to define your own macros or functions if you use the LOG4CPLUS_ERROR, LOG4CPLUS_INFO, etc. macros. See the tests/ directory for some examples of how to use these macros.

If you want to still avoid using the log4cplus provided macros, take a look at the source in loggingmacros.cxx:

void
macro_forced_log (log4cplus::Logger const & logger,
    log4cplus::LogLevel log_level, log4cplus::tstring const & msg,
    char const * filename, int line, char const * func)
{
    log4cplus::spi::InternalLoggingEvent & ev = internal::get_ptd ()->forced_log_ev;
    ev.setLoggingEvent (logger.getName (), log_level, msg, filename, line);
    ev.setFunction (func ? func : "");
    logger.forcedLog (ev);
}

This function is internally used by the various LOG4CPLUS_*() macros in loggingmacros.h. It shows you how to fill the InternalLoggingEvent instance and how to force its log. Use it as an example for your own LogMessage() function.

You would have to replace forcedLog() with log() to have it check the Logger threshold.

One implementation could look like this:

HRESULT
LogMessage(
    __in    DWORD dwLogLevel,
    __in    LPCSTR lpszFileName,
    __in    DWORD dwLineNumber,
    __in    LPCSTR lpszLogMessage,
    __in    LPCSTR lpszFunction)
{
    log4cplus::spi::InternalLoggingEvent ev;
    log4cplus::Logger logger (Logger::getRoot());
    ev.setLoggingEvent (logger.getName (), dwLogLevel, lpszLogMessage, lpszFileName,
        dwLineNumber);
    ev.setFunction (func ? lpszFunction : "");
    logger.forcedLog (ev); // or logger.log(ev)

    return S_OK;
}

#define PrintLogMessage(ll, msg) \
    LogMessage(ll, __FILE__, __LINE__, msg, LOG4CPLUS_MACRO_FUNCTION())

OTHER TIPS

If you can't modify the LogMessage function you could use this method:

int main()
{
   LogMessage(DEBUG_LEVEL, __FILE__, __LINE__, "This is "__FUNCTION__" function");
   // notice the missing commas ------------------------^------------^
}

Since there is no comma the compiler will concatenate the output of __FUNCTION__ and your message.

EDIT:

#define  PrintLogMessage(dwLogLevel, lpszLogMessage) \
LogMessage(dwLogLevel, _FILE, __LINE__, __FUNCTION__ lpszLogMessage)

or

#define  PrintLogMessage(dwLogLevel, lpszLogMessage) \
LogMessage(dwLogLevel, _FILE, __LINE__, lpszLogMessage __FUNCTION__)

or

#define  PrintLogMessage(dwLogLevel, lpszLogMessage) \
LogMessage(dwLogLevel, _FILE, __LINE__, lpszLogMessage __FUNCTION__ "function")

or

#define  PrintLogMessage(dwLogLevel, lpszLogMessage) \
LogMessage(dwLogLevel, _FILE, __LINE__, std::string(lpszLogMessage) + std::string(__FUNCTION__))
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top