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