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; }