On 2008-09-16 12:06, [EMAIL PROTECTED] wrote:
From what I've seen out there... small biz to large enterprises is that for System Admins, they see deleting logfiles as part of a global task

As I've started implementing some projects with log4cxx logging I had decided to use the sized based rolling policy since it was an in-my-face solution, but what I really wanted was for my programs to work into the logrotate system like most of the other daemons on my Debian systems.

I've looked into how to do this a couple of times, but only half heartedly. This discussion and some recent tweaking of a mail service's log rotation (via logrotate) on one server motivated me to figure out how to make this work.

Attached is a sample program that compiles on a Debian Etch (4.1) system with the liblog4cxx9-dev (0.9.7-6) package [1]. It is self-contained, no external conf file required. Just compile it and it should write to the terminal and to a file named log4cxx-hup.log. Rename the file to eg log4cxx-hup.1.log, like a rotation program would, and it continues to write to the file. Send it a SIGHUP and FileAppender::activateOptions() closes and re-opens the file, thus writing again to log4cxx-hup.log. You can even pre-create the file and set the permissions you want, as long as they allow the program to write, and it should work.

While I appreciate the portability issues the built-in rotation schemas try to provide, I prefer this solution if it will reliably work within my current logging framework.

Please glance over the attached code. I would like to have a reasonably polished example to put on the wiki that is simple without hiding too many details (eg no using namespace xxx), shows best practice ideas (eg NDC without push/pop) and easy to copy and paste as a boilerplate for doing the same in someone's application. I haven't checked this against 0.10.0, so I don't know if any methods are deprecated or if better options in that version.


[1] 0.9.7? Yes. I know. Unsupported by log4cxx project. Unfortunately this appears to be the version that will be in Lenny as well, so without a person willing to be responsible for the backport, or more time dropping into my lap, this is the version I will probably be dealing with for a few more years.

--
Jacob Anawalt
Gecko Software, Inc.
[EMAIL PROTECTED]
435-752-8026
// 2008-Sep-19 21:30
// log4cxx example of working with an external process that rotates
// log files and sends SIGHUP to the logging app to tell it to close
// and reopen files.
// g++ -o log4cxx-hup log4cxx-hup.cpp -llog4cxx
//
#include <log4cxx/logger.h>
#include <log4cxx/basicconfigurator.h>
#include <log4cxx/patternlayout.h>
#include <log4cxx/fileappender.h>
#include <log4cxx/logmanager.h>
#include <log4cxx/ndc.h>

#include <signal.h> // sigaction

void 
activateOptionsOnFileAppenders(log4cxx::LoggerPtr logger)
{
        log4cxx::LoggerPtr root(log4cxx::Logger::getRootLogger());
        LOG4CXX_INFO(root,"logger name: " << logger->getName());
        log4cxx::NDC ndc(logger->getName());
        log4cxx::AppenderList appenders = logger->getAllAppenders();
        LOG4CXX_INFO(root,"Found " << appenders.size() << " appenders.");
        const log4cxx::AppenderList::iterator end = appenders.end();
        for(log4cxx::AppenderList::iterator itr = appenders.begin();
            itr != end; ++itr) {
                LOG4CXX_INFO(root,"appender name: " << (*itr)->getName());
                log4cxx::FileAppenderPtr f = *itr;
                if(f) {
                        LOG4CXX_INFO(root,"FileAppender::activateOptions()");
                        f->activateOptions();
                        // At this point the FileAppender's file has been
                        // closed and re-opened. If an external process had
                        // rotated to say log4cxx-hup.1.log, on UNIX we
                        // would have kept writing to that file until
                        // activateOptions, at which point we start writing
                        // to a new log4cxx-hup.log.
                }
                else {
                        LOG4CXX_INFO(root,"itr not a FileAppender");
                }
        }
}

void 
sighup_handler(int signum)
{
        log4cxx::LoggerPtr root(log4cxx::Logger::getRootLogger());
        LOG4CXX_WARN(root,"SIGHUP("<<signum<<") recieved.");
        // The root logger
        LOG4CXX_INFO(root,"Checking for file appenders on root logger.");
        activateOptionsOnFileAppenders(root);
        // And all other current loggers
        log4cxx::LoggerList loggers = log4cxx::LogManager::getCurrentLoggers();
        LOG4CXX_INFO(root,"Found " << loggers.size() << " additional loggers to 
check.");
        const log4cxx::LoggerList::iterator end = loggers.end();
        for(log4cxx::LoggerList::iterator itr = loggers.begin();
            itr != end; ++itr) {
                activateOptionsOnFileAppenders(*itr);
        }
}

int 
main(void)
{
        log4cxx::BasicConfigurator::configure();

        log4cxx::LayoutPtr l(new log4cxx::PatternLayout(
                "%d{%Y-%m-%d %H:%M:%S} %-5p %c %x - %m%n"));
        log4cxx::AppenderPtr a(new log4cxx::FileAppender(l,"log4cxx-hup.log"));
        a->setName("FILE");

        log4cxx::LoggerPtr logger(log4cxx::Logger::getLogger("MyApp"));
        logger->addAppender(a);

        struct sigaction newAction;
        sigemptyset(&newAction.sa_mask);
        newAction.sa_handler = sighup_handler;
        newAction.sa_flags = 0;
        int r = sigaction(SIGHUP,&newAction,NULL);

        while(true) {
                LOG4CXX_INFO(logger,"beep");
                sleep(15);
        }

        return EXIT_SUCCESS;
}

Reply via email to