mirror of
https://gitlab.isc.org/isc-projects/kea
synced 2025-09-02 15:05:16 +00:00
[master] Merge branch 'trac2445'
This commit is contained in:
@@ -1376,6 +1376,7 @@ AC_OUTPUT([doc/version.ent
|
|||||||
src/lib/log/tests/console_test.sh
|
src/lib/log/tests/console_test.sh
|
||||||
src/lib/log/tests/destination_test.sh
|
src/lib/log/tests/destination_test.sh
|
||||||
src/lib/log/tests/init_logger_test.sh
|
src/lib/log/tests/init_logger_test.sh
|
||||||
|
src/lib/log/tests/buffer_logger_test.sh
|
||||||
src/lib/log/tests/local_file_test.sh
|
src/lib/log/tests/local_file_test.sh
|
||||||
src/lib/log/tests/logger_lock_test.sh
|
src/lib/log/tests/logger_lock_test.sh
|
||||||
src/lib/log/tests/severity_test.sh
|
src/lib/log/tests/severity_test.sh
|
||||||
|
@@ -147,7 +147,7 @@ main(int argc, char* argv[]) {
|
|||||||
// Initialize logging. If verbose, we'll use maximum verbosity.
|
// Initialize logging. If verbose, we'll use maximum verbosity.
|
||||||
isc::log::initLogger(AUTH_NAME,
|
isc::log::initLogger(AUTH_NAME,
|
||||||
(verbose ? isc::log::DEBUG : isc::log::INFO),
|
(verbose ? isc::log::DEBUG : isc::log::INFO),
|
||||||
isc::log::MAX_DEBUG_LEVEL, NULL);
|
isc::log::MAX_DEBUG_LEVEL, NULL, true);
|
||||||
|
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
@@ -256,7 +256,9 @@ main(int argc, char* argv[]) {
|
|||||||
|
|
||||||
// If we haven't registered callback for data sources, this will be just
|
// If we haven't registered callback for data sources, this will be just
|
||||||
// no-op.
|
// no-op.
|
||||||
|
if (config_session != NULL) {
|
||||||
config_session->removeRemoteConfig("data_sources");
|
config_session->removeRemoteConfig("data_sources");
|
||||||
|
}
|
||||||
|
|
||||||
delete xfrin_session;
|
delete xfrin_session;
|
||||||
delete config_session;
|
delete config_session;
|
||||||
|
@@ -76,7 +76,7 @@ import isc.bind10.socket_cache
|
|||||||
import libutil_io_python
|
import libutil_io_python
|
||||||
import tempfile
|
import tempfile
|
||||||
|
|
||||||
isc.log.init("b10-boss")
|
isc.log.init("b10-boss", buffer=True)
|
||||||
logger = isc.log.Logger("boss")
|
logger = isc.log.Logger("boss")
|
||||||
|
|
||||||
# Pending system-wide debug level definitions, the ones we
|
# Pending system-wide debug level definitions, the ones we
|
||||||
|
@@ -27,7 +27,7 @@ import glob
|
|||||||
import os.path
|
import os.path
|
||||||
import imp
|
import imp
|
||||||
import isc.log
|
import isc.log
|
||||||
isc.log.init("b10-cfgmgr")
|
isc.log.init("b10-cfgmgr", buffer=True)
|
||||||
from isc.config.cfgmgr import ConfigManager, ConfigManagerDataReadError, logger
|
from isc.config.cfgmgr import ConfigManager, ConfigManagerDataReadError, logger
|
||||||
from isc.log_messages.cfgmgr_messages import *
|
from isc.log_messages.cfgmgr_messages import *
|
||||||
|
|
||||||
|
@@ -49,7 +49,7 @@ from hashlib import sha1
|
|||||||
from isc.util import socketserver_mixin
|
from isc.util import socketserver_mixin
|
||||||
from isc.log_messages.cmdctl_messages import *
|
from isc.log_messages.cmdctl_messages import *
|
||||||
|
|
||||||
isc.log.init("b10-cmdctl")
|
isc.log.init("b10-cmdctl", buffer=True)
|
||||||
logger = isc.log.Logger("cmdctl")
|
logger = isc.log.Logger("cmdctl")
|
||||||
|
|
||||||
# Debug level for communication with BIND10
|
# Debug level for communication with BIND10
|
||||||
|
@@ -45,7 +45,7 @@ import os.path
|
|||||||
import signal
|
import signal
|
||||||
import socket
|
import socket
|
||||||
|
|
||||||
isc.log.init("b10-ddns")
|
isc.log.init("b10-ddns", buffer=True)
|
||||||
logger = isc.log.Logger("ddns")
|
logger = isc.log.Logger("ddns")
|
||||||
TRACE_BASIC = logger.DBGLVL_TRACE_BASIC
|
TRACE_BASIC = logger.DBGLVL_TRACE_BASIC
|
||||||
|
|
||||||
|
@@ -17,6 +17,7 @@
|
|||||||
#include <dhcp4/ctrl_dhcp4_srv.h>
|
#include <dhcp4/ctrl_dhcp4_srv.h>
|
||||||
#include <dhcp4/dhcp4_log.h>
|
#include <dhcp4/dhcp4_log.h>
|
||||||
#include <log/logger_support.h>
|
#include <log/logger_support.h>
|
||||||
|
#include <log/logger_manager.h>
|
||||||
|
|
||||||
#include <boost/lexical_cast.hpp>
|
#include <boost/lexical_cast.hpp>
|
||||||
|
|
||||||
@@ -93,9 +94,10 @@ main(int argc, char* argv[]) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Initialize logging. If verbose, we'll use maximum verbosity.
|
// Initialize logging. If verbose, we'll use maximum verbosity.
|
||||||
|
// If standalone is enabled, do not buffer initial log messages
|
||||||
isc::log::initLogger(DHCP4_NAME,
|
isc::log::initLogger(DHCP4_NAME,
|
||||||
(verbose_mode ? isc::log::DEBUG : isc::log::INFO),
|
(verbose_mode ? isc::log::DEBUG : isc::log::INFO),
|
||||||
isc::log::MAX_DEBUG_LEVEL, NULL);
|
isc::log::MAX_DEBUG_LEVEL, NULL, !stand_alone);
|
||||||
LOG_INFO(dhcp4_logger, DHCP4_STARTING);
|
LOG_INFO(dhcp4_logger, DHCP4_STARTING);
|
||||||
LOG_DEBUG(dhcp4_logger, DBG_DHCP4_START, DHCP4_START_INFO)
|
LOG_DEBUG(dhcp4_logger, DBG_DHCP4_START, DHCP4_START_INFO)
|
||||||
.arg(getpid()).arg(port_number).arg(verbose_mode ? "yes" : "no")
|
.arg(getpid()).arg(port_number).arg(verbose_mode ? "yes" : "no")
|
||||||
@@ -112,6 +114,10 @@ main(int argc, char* argv[]) {
|
|||||||
LOG_ERROR(dhcp4_logger, DHCP4_SESSION_FAIL).arg(ex.what());
|
LOG_ERROR(dhcp4_logger, DHCP4_SESSION_FAIL).arg(ex.what());
|
||||||
// Let's continue. It is useful to have the ability to run
|
// Let's continue. It is useful to have the ability to run
|
||||||
// DHCP server in stand-alone mode, e.g. for testing
|
// DHCP server in stand-alone mode, e.g. for testing
|
||||||
|
// We do need to make sure logging is no longer buffered
|
||||||
|
// since then it would not print until dhcp6 is stopped
|
||||||
|
isc::log::LoggerManager log_manager;
|
||||||
|
log_manager.process();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
LOG_DEBUG(dhcp4_logger, DBG_DHCP4_START, DHCP4_STANDALONE);
|
LOG_DEBUG(dhcp4_logger, DBG_DHCP4_START, DHCP4_STANDALONE);
|
||||||
|
@@ -17,6 +17,7 @@
|
|||||||
#include <dhcp6/ctrl_dhcp6_srv.h>
|
#include <dhcp6/ctrl_dhcp6_srv.h>
|
||||||
#include <dhcp6/dhcp6_log.h>
|
#include <dhcp6/dhcp6_log.h>
|
||||||
#include <log/logger_support.h>
|
#include <log/logger_support.h>
|
||||||
|
#include <log/logger_manager.h>
|
||||||
|
|
||||||
#include <boost/lexical_cast.hpp>
|
#include <boost/lexical_cast.hpp>
|
||||||
|
|
||||||
@@ -103,9 +104,10 @@ main(int argc, char* argv[]) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Initialize logging. If verbose, we'll use maximum verbosity.
|
// Initialize logging. If verbose, we'll use maximum verbosity.
|
||||||
|
// If standalone is enabled, do not buffer initial log messages
|
||||||
isc::log::initLogger(DHCP6_NAME,
|
isc::log::initLogger(DHCP6_NAME,
|
||||||
(verbose_mode ? isc::log::DEBUG : isc::log::INFO),
|
(verbose_mode ? isc::log::DEBUG : isc::log::INFO),
|
||||||
isc::log::MAX_DEBUG_LEVEL, NULL);
|
isc::log::MAX_DEBUG_LEVEL, NULL, !stand_alone);
|
||||||
LOG_INFO(dhcp6_logger, DHCP6_STARTING);
|
LOG_INFO(dhcp6_logger, DHCP6_STARTING);
|
||||||
LOG_DEBUG(dhcp6_logger, DBG_DHCP6_START, DHCP6_START_INFO)
|
LOG_DEBUG(dhcp6_logger, DBG_DHCP6_START, DHCP6_START_INFO)
|
||||||
.arg(getpid()).arg(port_number).arg(verbose_mode ? "yes" : "no")
|
.arg(getpid()).arg(port_number).arg(verbose_mode ? "yes" : "no")
|
||||||
@@ -121,6 +123,10 @@ main(int argc, char* argv[]) {
|
|||||||
LOG_ERROR(dhcp6_logger, DHCP6_SESSION_FAIL).arg(ex.what());
|
LOG_ERROR(dhcp6_logger, DHCP6_SESSION_FAIL).arg(ex.what());
|
||||||
// Let's continue. It is useful to have the ability to run
|
// Let's continue. It is useful to have the ability to run
|
||||||
// DHCP server in stand-alone mode, e.g. for testing
|
// DHCP server in stand-alone mode, e.g. for testing
|
||||||
|
// We do need to make sure logging is no longer buffered
|
||||||
|
// since then it would not print until dhcp6 is stopped
|
||||||
|
isc::log::LoggerManager log_manager;
|
||||||
|
log_manager.process();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
LOG_DEBUG(dhcp6_logger, DBG_DHCP6_START, DHCP6_STANDALONE);
|
LOG_DEBUG(dhcp6_logger, DBG_DHCP6_START, DHCP6_STANDALONE);
|
||||||
|
@@ -143,7 +143,7 @@ main(int argc, char* argv[]) {
|
|||||||
// temporary initLogger() code. If verbose, we'll use maximum verbosity.
|
// temporary initLogger() code. If verbose, we'll use maximum verbosity.
|
||||||
isc::log::initLogger(RESOLVER_NAME,
|
isc::log::initLogger(RESOLVER_NAME,
|
||||||
(verbose ? isc::log::DEBUG : isc::log::INFO),
|
(verbose ? isc::log::DEBUG : isc::log::INFO),
|
||||||
isc::log::MAX_DEBUG_LEVEL, NULL);
|
isc::log::MAX_DEBUG_LEVEL, NULL, true);
|
||||||
|
|
||||||
// Print the starting message
|
// Print the starting message
|
||||||
string cmdline = argv[0];
|
string cmdline = argv[0];
|
||||||
|
@@ -31,7 +31,7 @@ import isc.util.process
|
|||||||
import isc.log
|
import isc.log
|
||||||
from isc.log_messages.stats_messages import *
|
from isc.log_messages.stats_messages import *
|
||||||
|
|
||||||
isc.log.init("b10-stats")
|
isc.log.init("b10-stats", buffer=True)
|
||||||
logger = isc.log.Logger("stats")
|
logger = isc.log.Logger("stats")
|
||||||
|
|
||||||
# Some constants for debug levels.
|
# Some constants for debug levels.
|
||||||
@@ -682,7 +682,7 @@ if __name__ == "__main__":
|
|||||||
help="enable maximum debug logging")
|
help="enable maximum debug logging")
|
||||||
(options, args) = parser.parse_args()
|
(options, args) = parser.parse_args()
|
||||||
if options.verbose:
|
if options.verbose:
|
||||||
isc.log.init("b10-stats", "DEBUG", 99)
|
isc.log.init("b10-stats", "DEBUG", 99, buffer=True)
|
||||||
stats = Stats()
|
stats = Stats()
|
||||||
stats.start()
|
stats.start()
|
||||||
except OptionValueError as ove:
|
except OptionValueError as ove:
|
||||||
|
@@ -39,7 +39,7 @@ import isc.util.process
|
|||||||
import isc.log
|
import isc.log
|
||||||
from isc.log_messages.stats_httpd_messages import *
|
from isc.log_messages.stats_httpd_messages import *
|
||||||
|
|
||||||
isc.log.init("b10-stats-httpd")
|
isc.log.init("b10-stats-httpd", buffer=True)
|
||||||
logger = isc.log.Logger("stats-httpd")
|
logger = isc.log.Logger("stats-httpd")
|
||||||
|
|
||||||
# Some constants for debug levels.
|
# Some constants for debug levels.
|
||||||
@@ -609,7 +609,7 @@ if __name__ == "__main__":
|
|||||||
help="enable maximum debug logging")
|
help="enable maximum debug logging")
|
||||||
(options, args) = parser.parse_args()
|
(options, args) = parser.parse_args()
|
||||||
if options.verbose:
|
if options.verbose:
|
||||||
isc.log.init("b10-stats-httpd", "DEBUG", 99)
|
isc.log.init("b10-stats-httpd", "DEBUG", 99, buffer=True)
|
||||||
stats_httpd = StatsHttpd()
|
stats_httpd = StatsHttpd()
|
||||||
stats_httpd.start()
|
stats_httpd.start()
|
||||||
except OptionValueError as ove:
|
except OptionValueError as ove:
|
||||||
|
@@ -36,7 +36,7 @@ from isc.xfrin.diff import Diff
|
|||||||
from isc.server_common.auth_command import auth_loadzone_command
|
from isc.server_common.auth_command import auth_loadzone_command
|
||||||
from isc.log_messages.xfrin_messages import *
|
from isc.log_messages.xfrin_messages import *
|
||||||
|
|
||||||
isc.log.init("b10-xfrin")
|
isc.log.init("b10-xfrin", buffer=True)
|
||||||
logger = isc.log.Logger("xfrin")
|
logger = isc.log.Logger("xfrin")
|
||||||
|
|
||||||
# Pending system-wide debug level definitions, the ones we
|
# Pending system-wide debug level definitions, the ones we
|
||||||
|
@@ -38,7 +38,7 @@ import isc.server_common.tsig_keyring
|
|||||||
|
|
||||||
from isc.log_messages.xfrout_messages import *
|
from isc.log_messages.xfrout_messages import *
|
||||||
|
|
||||||
isc.log.init("b10-xfrout")
|
isc.log.init("b10-xfrout", buffer=True)
|
||||||
logger = isc.log.Logger("xfrout")
|
logger = isc.log.Logger("xfrout")
|
||||||
|
|
||||||
# Pending system-wide debug level definitions, the ones we
|
# Pending system-wide debug level definitions, the ones we
|
||||||
|
@@ -42,7 +42,7 @@ from isc.log_messages.zonemgr_messages import *
|
|||||||
from isc.notify import notify_out
|
from isc.notify import notify_out
|
||||||
|
|
||||||
# Initialize logging for called modules.
|
# Initialize logging for called modules.
|
||||||
isc.log.init("b10-zonemgr")
|
isc.log.init("b10-zonemgr", buffer=True)
|
||||||
logger = isc.log.Logger("zonemgr")
|
logger = isc.log.Logger("zonemgr")
|
||||||
|
|
||||||
# Pending system-wide debug level definitions, the ones we
|
# Pending system-wide debug level definitions, the ones we
|
||||||
|
@@ -31,6 +31,7 @@ libb10_log_la_SOURCES += message_initializer.cc message_initializer.h
|
|||||||
libb10_log_la_SOURCES += message_reader.cc message_reader.h
|
libb10_log_la_SOURCES += message_reader.cc message_reader.h
|
||||||
libb10_log_la_SOURCES += message_types.h
|
libb10_log_la_SOURCES += message_types.h
|
||||||
libb10_log_la_SOURCES += output_option.cc output_option.h
|
libb10_log_la_SOURCES += output_option.cc output_option.h
|
||||||
|
libb10_log_la_SOURCES += buffer_appender_impl.cc buffer_appender_impl.h
|
||||||
|
|
||||||
EXTRA_DIST = README
|
EXTRA_DIST = README
|
||||||
EXTRA_DIST += logimpl_messages.mes
|
EXTRA_DIST += logimpl_messages.mes
|
||||||
|
@@ -338,7 +338,8 @@ Variant #1, Used by Production Programs
|
|||||||
---------------------------------------
|
---------------------------------------
|
||||||
void isc::log::initLogger(const std::string& root,
|
void isc::log::initLogger(const std::string& root,
|
||||||
isc::log::Severity severity = isc::log::INFO,
|
isc::log::Severity severity = isc::log::INFO,
|
||||||
int dbglevel = 0, const char* file = NULL);
|
int dbglevel = 0, const char* file = NULL,
|
||||||
|
bool buffer = false);
|
||||||
|
|
||||||
This is the call that should be used by production programs:
|
This is the call that should be used by production programs:
|
||||||
|
|
||||||
@@ -359,6 +360,17 @@ file
|
|||||||
The name of a local message file. This will be read and its definitions used
|
The name of a local message file. This will be read and its definitions used
|
||||||
to replace the compiled-in text of the messages.
|
to replace the compiled-in text of the messages.
|
||||||
|
|
||||||
|
buffer
|
||||||
|
If set to true, initial log messages will be internally buffered, until the
|
||||||
|
first time a logger specification is processed. This way the program can
|
||||||
|
use logging before even processing its logging configuration. As soon as any
|
||||||
|
specification is processed (even an empty one), the buffered log messages will
|
||||||
|
be flushed according to the specification. Note that if this option is used,
|
||||||
|
the program SHOULD call one of the LoggerManager's process() calls (if you
|
||||||
|
are using the built-in logging configuration handling in ModuleCCSession,
|
||||||
|
this is automatically handled). If the program exits before this is done,
|
||||||
|
all log messages are dumped in a raw format to stdout (so that no messages
|
||||||
|
get lost).
|
||||||
|
|
||||||
Variant #2, Used by Unit Tests
|
Variant #2, Used by Unit Tests
|
||||||
------------------------------
|
------------------------------
|
||||||
|
96
src/lib/log/buffer_appender_impl.cc
Normal file
96
src/lib/log/buffer_appender_impl.cc
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
// Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC")
|
||||||
|
//
|
||||||
|
// Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
// purpose with or without fee is hereby granted, provided that the above
|
||||||
|
// copyright notice and this permission notice appear in all copies.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
|
||||||
|
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||||
|
// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||||
|
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||||
|
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
||||||
|
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||||
|
// PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
|
||||||
|
#include <log/buffer_appender_impl.h>
|
||||||
|
|
||||||
|
#include <log4cplus/loglevel.h>
|
||||||
|
#include <boost/scoped_ptr.hpp>
|
||||||
|
#include <cstdio>
|
||||||
|
|
||||||
|
namespace isc {
|
||||||
|
namespace log {
|
||||||
|
namespace internal {
|
||||||
|
|
||||||
|
BufferAppender::~BufferAppender() {
|
||||||
|
// If there is anything left in the buffer,
|
||||||
|
// it means no reconfig has been done, and
|
||||||
|
// we can assume the logging system was either
|
||||||
|
// never setup, or broke while doing so.
|
||||||
|
// So dump all that is left to stdout
|
||||||
|
try {
|
||||||
|
flushStdout();
|
||||||
|
} catch (...) {
|
||||||
|
// Ok if we can't even seem to dump to stdout, never mind.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
BufferAppender::flushStdout() {
|
||||||
|
// This does not show a bit of information normal log messages
|
||||||
|
// do, so perhaps we should try and setup a new logger here
|
||||||
|
// However, as this is called from a destructor, it may not
|
||||||
|
// be a good idea; as we can't reliably know whether in what
|
||||||
|
// state the logger instance is now (or what the specific logger's
|
||||||
|
// settings were).
|
||||||
|
LogEventList::const_iterator it;
|
||||||
|
for (it = stored_.begin(); it != stored_.end(); ++it) {
|
||||||
|
const std::string level(it->first);
|
||||||
|
LogEventPtr event(it->second);
|
||||||
|
std::printf("%s [%s]: %s\n", level.c_str(),
|
||||||
|
event->getLoggerName().c_str(),
|
||||||
|
event->getMessage().c_str());
|
||||||
|
}
|
||||||
|
stored_.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
BufferAppender::flush() {
|
||||||
|
LogEventList stored_copy;
|
||||||
|
stored_.swap(stored_copy);
|
||||||
|
|
||||||
|
LogEventList::const_iterator it;
|
||||||
|
for (it = stored_copy.begin(); it != stored_copy.end(); ++it) {
|
||||||
|
LogEventPtr event(it->second);
|
||||||
|
log4cplus::Logger logger =
|
||||||
|
log4cplus::Logger::getInstance(event->getLoggerName());
|
||||||
|
|
||||||
|
logger.log(event->getLogLevel(), event->getMessage());
|
||||||
|
}
|
||||||
|
flushed_ = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t
|
||||||
|
BufferAppender::getBufferSize() const {
|
||||||
|
return (stored_.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
BufferAppender::append(const log4cplus::spi::InternalLoggingEvent& event) {
|
||||||
|
if (flushed_) {
|
||||||
|
isc_throw(LogBufferAddAfterFlush,
|
||||||
|
"Internal log buffer has been flushed already");
|
||||||
|
}
|
||||||
|
// get a clone, and put the pointer in a shared_ptr in the list
|
||||||
|
std::auto_ptr<log4cplus::spi::InternalLoggingEvent> event_aptr =
|
||||||
|
event.clone();
|
||||||
|
// Also store the string representation of the log level, to be
|
||||||
|
// used in flushStdout if necessary
|
||||||
|
stored_.push_back(LevelAndEvent(
|
||||||
|
log4cplus::LogLevelManager().toString(event.getLogLevel()),
|
||||||
|
LogEventPtr(event_aptr.release())));
|
||||||
|
}
|
||||||
|
|
||||||
|
} // end namespace internal
|
||||||
|
} // end namespace log
|
||||||
|
} // end namespace isc
|
118
src/lib/log/buffer_appender_impl.h
Normal file
118
src/lib/log/buffer_appender_impl.h
Normal file
@@ -0,0 +1,118 @@
|
|||||||
|
// Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC")
|
||||||
|
//
|
||||||
|
// Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
// purpose with or without fee is hereby granted, provided that the above
|
||||||
|
// copyright notice and this permission notice appear in all copies.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
|
||||||
|
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||||
|
// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||||
|
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||||
|
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
||||||
|
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||||
|
// PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
|
||||||
|
#ifndef LOG_BUFFER_H
|
||||||
|
#define LOG_BUFFER_H
|
||||||
|
|
||||||
|
#include <exceptions/exceptions.h>
|
||||||
|
|
||||||
|
#include <log4cplus/logger.h>
|
||||||
|
#include <log4cplus/spi/loggingevent.h>
|
||||||
|
#include <boost/shared_ptr.hpp>
|
||||||
|
|
||||||
|
namespace isc {
|
||||||
|
namespace log {
|
||||||
|
namespace internal {
|
||||||
|
|
||||||
|
/// \brief Buffer add after flush
|
||||||
|
///
|
||||||
|
/// This exception is thrown if the log buffer's add() method
|
||||||
|
/// is called after the log buffer has been flushed; the buffer
|
||||||
|
/// is only supposed to be used once (until the first time a
|
||||||
|
/// logger specification is processed)
|
||||||
|
class LogBufferAddAfterFlush : public isc::Exception {
|
||||||
|
public:
|
||||||
|
LogBufferAddAfterFlush(const char* file, size_t line, const char* what) :
|
||||||
|
isc::Exception(file, line, what)
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Convenience typedef for a pointer to a log event
|
||||||
|
typedef boost::shared_ptr<log4cplus::spi::InternalLoggingEvent> LogEventPtr;
|
||||||
|
|
||||||
|
/// Convenience typedef for a pair string/logeventptr, the string representing
|
||||||
|
/// the logger level, as returned by LogLevelManager::toString() at the
|
||||||
|
/// time of initial logging
|
||||||
|
typedef std::pair<std::string, LogEventPtr> LevelAndEvent;
|
||||||
|
|
||||||
|
/// Convenience typedef for a vector of LevelAndEvent instances
|
||||||
|
typedef std::vector<LevelAndEvent> LogEventList;
|
||||||
|
|
||||||
|
/// \brief Buffering Logger Appender
|
||||||
|
///
|
||||||
|
/// This class can be set as an Appender for log4cplus loggers,
|
||||||
|
/// and is used to store logging events; it simply keeps any
|
||||||
|
/// event that is passed to \c append(), and will replay them to the
|
||||||
|
/// logger that they were originally created for when \c flush() is
|
||||||
|
/// called.
|
||||||
|
///
|
||||||
|
/// The idea is that initially, a program may want to do some logging,
|
||||||
|
/// but does not know where to yet (for instance because it has yet to
|
||||||
|
/// read and parse its configuration). Any log messages before this time
|
||||||
|
/// would normally go to some default (say, stdout), and be lost in the
|
||||||
|
/// real logging destination. By buffering them (and flushing them once
|
||||||
|
/// the logger has been configured), these log messages are kept in a
|
||||||
|
/// consistent place, and are not lost.
|
||||||
|
///
|
||||||
|
/// Given this goal, this class has an extra check; it will raise
|
||||||
|
/// an exception if \c append() is called after flush().
|
||||||
|
///
|
||||||
|
/// If the BufferAppender instance is destroyed before being flushed,
|
||||||
|
/// it will dump any event it has left to stdout.
|
||||||
|
class BufferAppender : public log4cplus::Appender {
|
||||||
|
public:
|
||||||
|
/// \brief Constructor
|
||||||
|
///
|
||||||
|
/// Constructs a BufferAppender that buffers log evens
|
||||||
|
BufferAppender() : flushed_(false) {}
|
||||||
|
|
||||||
|
/// \brief Destructor
|
||||||
|
///
|
||||||
|
/// Any remaining events are flushed to stdout (there should
|
||||||
|
/// only be any events remaining if flush() was never called)
|
||||||
|
virtual ~BufferAppender();
|
||||||
|
|
||||||
|
/// \brief Close the appender
|
||||||
|
///
|
||||||
|
/// This class has no specialized handling for this method
|
||||||
|
virtual void close() {}
|
||||||
|
|
||||||
|
/// \brief Flush the internal buffer
|
||||||
|
///
|
||||||
|
/// Events that have been stored (after calls to \c append()
|
||||||
|
/// are replayed to the logger. Should only be called after
|
||||||
|
/// new appenders have been set to the logger.
|
||||||
|
void flush();
|
||||||
|
|
||||||
|
/// \brief Returns the number of stored logging events
|
||||||
|
///
|
||||||
|
/// Mainly useful for testing
|
||||||
|
size_t getBufferSize() const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void append(const log4cplus::spi::InternalLoggingEvent& event);
|
||||||
|
private:
|
||||||
|
/// \brief Helper for the destructor, flush events to stdout
|
||||||
|
void flushStdout();
|
||||||
|
|
||||||
|
LogEventList stored_;
|
||||||
|
bool flushed_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // end namespace internal
|
||||||
|
} // end namespace log
|
||||||
|
} // end namespace isc
|
||||||
|
|
||||||
|
#endif // LOG_BUFFER_H
|
||||||
|
|
@@ -94,7 +94,7 @@ LoggerManager::processEnd() {
|
|||||||
|
|
||||||
void
|
void
|
||||||
LoggerManager::init(const std::string& root, isc::log::Severity severity,
|
LoggerManager::init(const std::string& root, isc::log::Severity severity,
|
||||||
int dbglevel, const char* file)
|
int dbglevel, const char* file, bool buffer)
|
||||||
{
|
{
|
||||||
// Load in the messages declared in the program and registered by
|
// Load in the messages declared in the program and registered by
|
||||||
// statically-declared MessageInitializer objects.
|
// statically-declared MessageInitializer objects.
|
||||||
@@ -114,7 +114,9 @@ LoggerManager::init(const std::string& root, isc::log::Severity severity,
|
|||||||
|
|
||||||
// Initialize the implementation logging. After this point, some basic
|
// Initialize the implementation logging. After this point, some basic
|
||||||
// logging has been set up and messages can be logged.
|
// logging has been set up and messages can be logged.
|
||||||
LoggerManagerImpl::init(severity, dbglevel);
|
// However, they will not appear until a logging specification has been
|
||||||
|
// processed (or the program exits), see TODO
|
||||||
|
LoggerManagerImpl::init(severity, dbglevel, buffer);
|
||||||
setLoggingInitialized();
|
setLoggingInitialized();
|
||||||
|
|
||||||
// Check if there were any duplicate message IDs in the default dictionary
|
// Check if there were any duplicate message IDs in the default dictionary
|
||||||
|
@@ -76,6 +76,21 @@ public:
|
|||||||
processEnd();
|
processEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// \brief Process 'empty' specification
|
||||||
|
///
|
||||||
|
/// This will disable any existing output options, and set
|
||||||
|
/// the logging to go to the built-in default (stdout).
|
||||||
|
/// If the logger has been initialized with buffering enabled,
|
||||||
|
/// all log messages up to now shall be printed to stdout.
|
||||||
|
///
|
||||||
|
/// This is mainly useful in scenarios where buffering is needed,
|
||||||
|
/// but it turns out there are no logging specifications to
|
||||||
|
/// handle.
|
||||||
|
void process() {
|
||||||
|
processInit();
|
||||||
|
processEnd();
|
||||||
|
}
|
||||||
|
|
||||||
/// \brief Run-Time Initialization
|
/// \brief Run-Time Initialization
|
||||||
///
|
///
|
||||||
/// Performs run-time initialization of the logger system, in particular
|
/// Performs run-time initialization of the logger system, in particular
|
||||||
@@ -91,13 +106,18 @@ public:
|
|||||||
/// \param dbglevel Debug severity (ignored if "severity" is not "DEBUG")
|
/// \param dbglevel Debug severity (ignored if "severity" is not "DEBUG")
|
||||||
/// \param file Name of the local message file. This must be NULL if there
|
/// \param file Name of the local message file. This must be NULL if there
|
||||||
/// is no local message file.
|
/// is no local message file.
|
||||||
|
/// \param buffer If true, all log messages will be buffered until one of
|
||||||
|
/// the \c process() methods is called. If false, initial logging
|
||||||
|
/// shall go to the default output (i.e. stdout)
|
||||||
static void init(const std::string& root,
|
static void init(const std::string& root,
|
||||||
isc::log::Severity severity = isc::log::INFO,
|
isc::log::Severity severity = isc::log::INFO,
|
||||||
int dbglevel = 0, const char* file = NULL);
|
int dbglevel = 0, const char* file = NULL,
|
||||||
|
bool buffer = false);
|
||||||
|
|
||||||
/// \brief Reset logging
|
/// \brief Reset logging
|
||||||
///
|
///
|
||||||
/// Resets logging to whatever was set in the call to init().
|
/// Resets logging to whatever was set in the call to init(), expect for
|
||||||
|
/// the buffer option.
|
||||||
static void reset();
|
static void reset();
|
||||||
|
|
||||||
/// \brief Read local message file
|
/// \brief Read local message file
|
||||||
|
@@ -23,12 +23,14 @@
|
|||||||
#include <log4cplus/syslogappender.h>
|
#include <log4cplus/syslogappender.h>
|
||||||
|
|
||||||
#include <log/logger.h>
|
#include <log/logger.h>
|
||||||
|
#include <log/logger_support.h>
|
||||||
#include <log/logger_level_impl.h>
|
#include <log/logger_level_impl.h>
|
||||||
#include <log/logger_manager.h>
|
#include <log/logger_manager.h>
|
||||||
#include <log/logger_manager_impl.h>
|
#include <log/logger_manager_impl.h>
|
||||||
#include <log/log_messages.h>
|
#include <log/log_messages.h>
|
||||||
#include <log/logger_name.h>
|
#include <log/logger_name.h>
|
||||||
#include <log/logger_specification.h>
|
#include <log/logger_specification.h>
|
||||||
|
#include <log/buffer_appender_impl.h>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
@@ -40,19 +42,24 @@ namespace log {
|
|||||||
// passed back to the parent) and resets the root logger to logging
|
// passed back to the parent) and resets the root logger to logging
|
||||||
// informational messages. (This last is not a log4cplus default, so we have to
|
// informational messages. (This last is not a log4cplus default, so we have to
|
||||||
// explicitly reset the logging severity.)
|
// explicitly reset the logging severity.)
|
||||||
|
|
||||||
void
|
void
|
||||||
LoggerManagerImpl::processInit() {
|
LoggerManagerImpl::processInit() {
|
||||||
|
storeBufferAppenders();
|
||||||
|
|
||||||
log4cplus::Logger::getDefaultHierarchy().resetConfiguration();
|
log4cplus::Logger::getDefaultHierarchy().resetConfiguration();
|
||||||
initRootLogger();
|
initRootLogger();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Flush the BufferAppenders at the end of processing a new specification
|
||||||
|
void
|
||||||
|
LoggerManagerImpl::processEnd() {
|
||||||
|
flushBufferAppenders();
|
||||||
|
}
|
||||||
|
|
||||||
// Process logging specification. Set up the common states then dispatch to
|
// Process logging specification. Set up the common states then dispatch to
|
||||||
// add output specifications.
|
// add output specifications.
|
||||||
|
|
||||||
void
|
void
|
||||||
LoggerManagerImpl::processSpecification(const LoggerSpecification& spec) {
|
LoggerManagerImpl::processSpecification(const LoggerSpecification& spec) {
|
||||||
|
|
||||||
log4cplus::Logger logger = log4cplus::Logger::getInstance(
|
log4cplus::Logger logger = log4cplus::Logger::getInstance(
|
||||||
expandLoggerName(spec.getName()));
|
expandLoggerName(spec.getName()));
|
||||||
|
|
||||||
@@ -65,8 +72,7 @@ LoggerManagerImpl::processSpecification(const LoggerSpecification& spec) {
|
|||||||
|
|
||||||
// Output options given?
|
// Output options given?
|
||||||
if (spec.optionCount() > 0) {
|
if (spec.optionCount() > 0) {
|
||||||
|
// Replace all appenders for this logger.
|
||||||
// Yes, so replace all appenders for this logger.
|
|
||||||
logger.removeAllAppenders();
|
logger.removeAllAppenders();
|
||||||
|
|
||||||
// Now process output specifications.
|
// Now process output specifications.
|
||||||
@@ -134,6 +140,16 @@ LoggerManagerImpl::createFileAppender(log4cplus::Logger& logger,
|
|||||||
logger.addAppender(fileapp);
|
logger.addAppender(fileapp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
LoggerManagerImpl::createBufferAppender(log4cplus::Logger& logger) {
|
||||||
|
log4cplus::SharedAppenderPtr bufferapp(new internal::BufferAppender());
|
||||||
|
bufferapp->setName("buffer");
|
||||||
|
logger.addAppender(bufferapp);
|
||||||
|
// Since we do not know at what level the loggers will end up
|
||||||
|
// running, set it to the highest for now
|
||||||
|
logger.setLogLevel(log4cplus::TRACE_LOG_LEVEL);
|
||||||
|
}
|
||||||
|
|
||||||
// Syslog appender.
|
// Syslog appender.
|
||||||
void
|
void
|
||||||
LoggerManagerImpl::createSyslogAppender(log4cplus::Logger& logger,
|
LoggerManagerImpl::createSyslogAppender(log4cplus::Logger& logger,
|
||||||
@@ -147,10 +163,10 @@ LoggerManagerImpl::createSyslogAppender(log4cplus::Logger& logger,
|
|||||||
|
|
||||||
|
|
||||||
// One-time initialization of the log4cplus system
|
// One-time initialization of the log4cplus system
|
||||||
|
|
||||||
void
|
void
|
||||||
LoggerManagerImpl::init(isc::log::Severity severity, int dbglevel) {
|
LoggerManagerImpl::init(isc::log::Severity severity, int dbglevel,
|
||||||
|
bool buffer)
|
||||||
|
{
|
||||||
// Set up basic configurator. This attaches a ConsoleAppender to the
|
// Set up basic configurator. This attaches a ConsoleAppender to the
|
||||||
// root logger with suitable output. This is used until we we have
|
// root logger with suitable output. This is used until we we have
|
||||||
// actually read the logging configuration, in which case the output
|
// actually read the logging configuration, in which case the output
|
||||||
@@ -161,22 +177,22 @@ LoggerManagerImpl::init(isc::log::Severity severity, int dbglevel) {
|
|||||||
// Add the additional debug levels
|
// Add the additional debug levels
|
||||||
LoggerLevelImpl::init();
|
LoggerLevelImpl::init();
|
||||||
|
|
||||||
reset(severity, dbglevel);
|
initRootLogger(severity, dbglevel, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset logging to default configuration. This closes all appenders
|
// Reset logging to default configuration. This closes all appenders
|
||||||
// and resets the root logger to output INFO messages to the console.
|
// and resets the root logger to output INFO messages to the console.
|
||||||
// It is principally used in testing.
|
// It is principally used in testing.
|
||||||
void
|
void
|
||||||
LoggerManagerImpl::reset(isc::log::Severity severity, int dbglevel) {
|
LoggerManagerImpl::reset(isc::log::Severity severity, int dbglevel)
|
||||||
|
{
|
||||||
// Initialize the root logger
|
// Initialize the root logger
|
||||||
initRootLogger(severity, dbglevel);
|
initRootLogger(severity, dbglevel);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize the root logger
|
// Initialize the root logger
|
||||||
void LoggerManagerImpl::initRootLogger(isc::log::Severity severity,
|
void LoggerManagerImpl::initRootLogger(isc::log::Severity severity,
|
||||||
int dbglevel)
|
int dbglevel, bool buffer)
|
||||||
{
|
{
|
||||||
log4cplus::Logger::getDefaultHierarchy().resetConfiguration();
|
log4cplus::Logger::getDefaultHierarchy().resetConfiguration();
|
||||||
|
|
||||||
@@ -191,13 +207,13 @@ void LoggerManagerImpl::initRootLogger(isc::log::Severity severity,
|
|||||||
b10root.setLogLevel(LoggerLevelImpl::convertFromBindLevel(
|
b10root.setLogLevel(LoggerLevelImpl::convertFromBindLevel(
|
||||||
Level(severity, dbglevel)));
|
Level(severity, dbglevel)));
|
||||||
|
|
||||||
// Set the BIND 10 root to use a console logger.
|
if (buffer) {
|
||||||
|
createBufferAppender(b10root);
|
||||||
|
} else {
|
||||||
OutputOption opt;
|
OutputOption opt;
|
||||||
createConsoleAppender(b10root, opt);
|
createConsoleAppender(b10root, opt);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// Set the the "console" layout for the given appenders. This layout includes
|
|
||||||
// a date/time and the name of the logger.
|
|
||||||
|
|
||||||
void LoggerManagerImpl::setConsoleAppenderLayout(
|
void LoggerManagerImpl::setConsoleAppenderLayout(
|
||||||
log4cplus::SharedAppenderPtr& appender)
|
log4cplus::SharedAppenderPtr& appender)
|
||||||
@@ -225,5 +241,31 @@ void LoggerManagerImpl::setSyslogAppenderLayout(
|
|||||||
appender->setLayout(layout);
|
appender->setLayout(layout);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LoggerManagerImpl::storeBufferAppenders() {
|
||||||
|
// Walk through all loggers, and find any buffer appenders there
|
||||||
|
log4cplus::LoggerList loggers = log4cplus::Logger::getCurrentLoggers();
|
||||||
|
log4cplus::LoggerList::iterator it;
|
||||||
|
for (it = loggers.begin(); it != loggers.end(); ++it) {
|
||||||
|
log4cplus::SharedAppenderPtr buffer_appender =
|
||||||
|
it->getAppender("buffer");
|
||||||
|
if (buffer_appender) {
|
||||||
|
buffer_appender_store_.push_back(buffer_appender);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void LoggerManagerImpl::flushBufferAppenders() {
|
||||||
|
std::vector<log4cplus::SharedAppenderPtr> copy;
|
||||||
|
buffer_appender_store_.swap(copy);
|
||||||
|
|
||||||
|
std::vector<log4cplus::SharedAppenderPtr>::iterator it;
|
||||||
|
for (it = copy.begin(); it != copy.end(); ++it) {
|
||||||
|
internal::BufferAppender* app =
|
||||||
|
dynamic_cast<internal::BufferAppender*>(it->get());
|
||||||
|
assert(app != NULL);
|
||||||
|
app->flush();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace log
|
} // namespace log
|
||||||
} // namespace isc
|
} // namespace isc
|
||||||
|
@@ -51,15 +51,14 @@ class LoggerManagerImpl {
|
|||||||
public:
|
public:
|
||||||
|
|
||||||
/// \brief Constructor
|
/// \brief Constructor
|
||||||
LoggerManagerImpl()
|
LoggerManagerImpl() {}
|
||||||
{}
|
|
||||||
|
|
||||||
/// \brief Initialize Processing
|
/// \brief Initialize Processing
|
||||||
///
|
///
|
||||||
/// This resets the hierachy of loggers back to their defaults. This means
|
/// This resets the hierachy of loggers back to their defaults. This means
|
||||||
/// that all non-root loggers (if they exist) are set to NOT_SET, and the
|
/// that all non-root loggers (if they exist) are set to NOT_SET, and the
|
||||||
/// root logger reset to logging informational messages.
|
/// root logger reset to logging informational messages.
|
||||||
static void processInit();
|
void processInit();
|
||||||
|
|
||||||
/// \brief Process Specification
|
/// \brief Process Specification
|
||||||
///
|
///
|
||||||
@@ -71,8 +70,7 @@ public:
|
|||||||
/// \brief End Processing
|
/// \brief End Processing
|
||||||
///
|
///
|
||||||
/// Terminates the processing of the logging specifications.
|
/// Terminates the processing of the logging specifications.
|
||||||
static void processEnd()
|
void processEnd();
|
||||||
{}
|
|
||||||
|
|
||||||
/// \brief Implementation-specific initialization
|
/// \brief Implementation-specific initialization
|
||||||
///
|
///
|
||||||
@@ -87,8 +85,11 @@ public:
|
|||||||
///
|
///
|
||||||
/// \param severity Severity to be associated with this logger
|
/// \param severity Severity to be associated with this logger
|
||||||
/// \param dbglevel Debug level associated with the root logger
|
/// \param dbglevel Debug level associated with the root logger
|
||||||
|
/// \param buffer If true, all log messages will be buffered until one of
|
||||||
|
/// the \c process() methods is called. If false, initial logging
|
||||||
|
/// shall go to the default output (i.e. stdout)
|
||||||
static void init(isc::log::Severity severity = isc::log::INFO,
|
static void init(isc::log::Severity severity = isc::log::INFO,
|
||||||
int dbglevel = 0);
|
int dbglevel = 0, bool buffer = false);
|
||||||
|
|
||||||
/// \brief Reset logging
|
/// \brief Reset logging
|
||||||
///
|
///
|
||||||
@@ -132,15 +133,27 @@ private:
|
|||||||
static void createSyslogAppender(log4cplus::Logger& logger,
|
static void createSyslogAppender(log4cplus::Logger& logger,
|
||||||
const OutputOption& opt);
|
const OutputOption& opt);
|
||||||
|
|
||||||
|
/// \brief Create buffered appender
|
||||||
|
///
|
||||||
|
/// Appends an object to the logger that will store the log events sent
|
||||||
|
/// to the logger. These log messages are replayed to the logger in
|
||||||
|
/// processEnd().
|
||||||
|
///
|
||||||
|
/// \param logger Log4cplus logger to which the appender must be attached.
|
||||||
|
static void createBufferAppender(log4cplus::Logger& logger);
|
||||||
|
|
||||||
/// \brief Set default layout and severity for root logger
|
/// \brief Set default layout and severity for root logger
|
||||||
///
|
///
|
||||||
/// Initializes the root logger to BIND 10 defaults - console output and
|
/// Initializes the root logger to BIND 10 defaults - console or buffered
|
||||||
/// the passed severity/debug level.
|
/// output and the passed severity/debug level.
|
||||||
///
|
///
|
||||||
/// \param severity Severity of messages that the logger should output.
|
/// \param severity Severity of messages that the logger should output.
|
||||||
/// \param dbglevel Debug level if severity = DEBUG
|
/// \param dbglevel Debug level if severity = DEBUG
|
||||||
|
/// \param buffer If true, all log messages will be buffered until one of
|
||||||
|
/// the \c process() methods is called. If false, initial logging
|
||||||
|
/// shall go to the default output (i.e. stdout)
|
||||||
static void initRootLogger(isc::log::Severity severity = isc::log::INFO,
|
static void initRootLogger(isc::log::Severity severity = isc::log::INFO,
|
||||||
int dbglevel = 0);
|
int dbglevel = 0, bool buffer = false);
|
||||||
|
|
||||||
/// \brief Set layout for console appender
|
/// \brief Set layout for console appender
|
||||||
///
|
///
|
||||||
@@ -161,6 +174,25 @@ private:
|
|||||||
///
|
///
|
||||||
/// \param appender Appender for which this pattern is to be set.
|
/// \param appender Appender for which this pattern is to be set.
|
||||||
static void setSyslogAppenderLayout(log4cplus::SharedAppenderPtr& appender);
|
static void setSyslogAppenderLayout(log4cplus::SharedAppenderPtr& appender);
|
||||||
|
|
||||||
|
/// \brief Store all buffer appenders
|
||||||
|
///
|
||||||
|
/// When processing a new specification, this method can be used
|
||||||
|
/// to keep a list of the buffer appenders; the caller can then
|
||||||
|
/// process the specification, and call \c flushBufferAppenders()
|
||||||
|
/// to flush and clear the list
|
||||||
|
void storeBufferAppenders();
|
||||||
|
|
||||||
|
/// \brief Flush the stored buffer appenders
|
||||||
|
///
|
||||||
|
/// This flushes the list of buffer appenders stored in
|
||||||
|
/// \c storeBufferAppenders(), and clears it
|
||||||
|
void flushBufferAppenders();
|
||||||
|
|
||||||
|
/// Only used between processInit() and processEnd(), to temporarily
|
||||||
|
/// store the buffer appenders in order to flush them after
|
||||||
|
/// processSpecification() calls have been completed
|
||||||
|
std::vector<log4cplus::SharedAppenderPtr> buffer_appender_store_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace log
|
} // namespace log
|
||||||
|
@@ -46,8 +46,8 @@ setLoggingInitialized(bool state) {
|
|||||||
|
|
||||||
void
|
void
|
||||||
initLogger(const string& root, isc::log::Severity severity, int dbglevel,
|
initLogger(const string& root, isc::log::Severity severity, int dbglevel,
|
||||||
const char* file) {
|
const char* file, bool buffer) {
|
||||||
LoggerManager::init(root, severity, dbglevel, file);
|
LoggerManager::init(root, severity, dbglevel, file, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace log
|
} // namespace log
|
||||||
|
@@ -61,9 +61,13 @@ void setLoggingInitialized(bool state = true);
|
|||||||
/// \param severity Severity at which to log
|
/// \param severity Severity at which to log
|
||||||
/// \param dbglevel Debug severity (ignored if "severity" is not "DEBUG")
|
/// \param dbglevel Debug severity (ignored if "severity" is not "DEBUG")
|
||||||
/// \param file Name of the local message file.
|
/// \param file Name of the local message file.
|
||||||
|
/// \param buffer If true, all log messages will be buffered until one of
|
||||||
|
/// the \c process() methods is called. If false, initial logging
|
||||||
|
/// shall go to the default output (i.e. stdout)
|
||||||
void initLogger(const std::string& root,
|
void initLogger(const std::string& root,
|
||||||
isc::log::Severity severity = isc::log::INFO,
|
isc::log::Severity severity = isc::log::INFO,
|
||||||
int dbglevel = 0, const char* file = NULL);
|
int dbglevel = 0, const char* file = NULL,
|
||||||
|
bool buffer = false);
|
||||||
|
|
||||||
} // namespace log
|
} // namespace log
|
||||||
} // namespace isc
|
} // namespace isc
|
||||||
|
@@ -37,6 +37,15 @@ init_logger_test_LDADD += $(top_builddir)/src/lib/util/libb10-util.la
|
|||||||
init_logger_test_LDADD += $(top_builddir)/src/lib/exceptions/libb10-exceptions.la
|
init_logger_test_LDADD += $(top_builddir)/src/lib/exceptions/libb10-exceptions.la
|
||||||
init_logger_test_LDADD += $(AM_LDADD) $(LOG4CPLUS_LIBS)
|
init_logger_test_LDADD += $(AM_LDADD) $(LOG4CPLUS_LIBS)
|
||||||
|
|
||||||
|
noinst_PROGRAMS += buffer_logger_test
|
||||||
|
buffer_logger_test_SOURCES = buffer_logger_test.cc
|
||||||
|
buffer_logger_test_CPPFLAGS = $(AM_CPPFLAGS)
|
||||||
|
buffer_logger_test_LDFLAGS = $(AM_LDFLAGS)
|
||||||
|
buffer_logger_test_LDADD = $(top_builddir)/src/lib/log/libb10-log.la
|
||||||
|
buffer_logger_test_LDADD += $(top_builddir)/src/lib/util/libb10-util.la
|
||||||
|
buffer_logger_test_LDADD += $(top_builddir)/src/lib/exceptions/libb10-exceptions.la
|
||||||
|
buffer_logger_test_LDADD += $(AM_LDADD) $(LOG4CPLUS_LIBS)
|
||||||
|
|
||||||
noinst_PROGRAMS += logger_lock_test
|
noinst_PROGRAMS += logger_lock_test
|
||||||
logger_lock_test_SOURCES = logger_lock_test.cc
|
logger_lock_test_SOURCES = logger_lock_test.cc
|
||||||
nodist_logger_lock_test_SOURCES = log_test_messages.cc log_test_messages.h
|
nodist_logger_lock_test_SOURCES = log_test_messages.cc log_test_messages.h
|
||||||
@@ -82,11 +91,13 @@ run_unittests_SOURCES += logger_specification_unittest.cc
|
|||||||
run_unittests_SOURCES += message_dictionary_unittest.cc
|
run_unittests_SOURCES += message_dictionary_unittest.cc
|
||||||
run_unittests_SOURCES += message_reader_unittest.cc
|
run_unittests_SOURCES += message_reader_unittest.cc
|
||||||
run_unittests_SOURCES += output_option_unittest.cc
|
run_unittests_SOURCES += output_option_unittest.cc
|
||||||
|
run_unittests_SOURCES += buffer_appender_unittest.cc
|
||||||
nodist_run_unittests_SOURCES = log_test_messages.cc log_test_messages.h
|
nodist_run_unittests_SOURCES = log_test_messages.cc log_test_messages.h
|
||||||
|
|
||||||
run_unittests_CPPFLAGS = $(AM_CPPFLAGS)
|
run_unittests_CPPFLAGS = $(AM_CPPFLAGS)
|
||||||
run_unittests_CXXFLAGS = $(AM_CXXFLAGS)
|
run_unittests_CXXFLAGS = $(AM_CXXFLAGS)
|
||||||
run_unittests_LDADD = $(AM_LDADD)
|
run_unittests_LDADD = $(AM_LDADD)
|
||||||
|
run_unittests_LDADD += $(LOG4CPLUS_LIBS)
|
||||||
run_unittests_LDFLAGS = $(AM_LDFLAGS)
|
run_unittests_LDFLAGS = $(AM_LDFLAGS)
|
||||||
|
|
||||||
# logging initialization tests. These are put in separate programs to
|
# logging initialization tests. These are put in separate programs to
|
||||||
@@ -124,6 +135,7 @@ check-local:
|
|||||||
$(SHELL) $(abs_builddir)/console_test.sh
|
$(SHELL) $(abs_builddir)/console_test.sh
|
||||||
$(SHELL) $(abs_builddir)/destination_test.sh
|
$(SHELL) $(abs_builddir)/destination_test.sh
|
||||||
$(SHELL) $(abs_builddir)/init_logger_test.sh
|
$(SHELL) $(abs_builddir)/init_logger_test.sh
|
||||||
|
$(SHELL) $(abs_builddir)/buffer_logger_test.sh
|
||||||
$(SHELL) $(abs_builddir)/local_file_test.sh
|
$(SHELL) $(abs_builddir)/local_file_test.sh
|
||||||
$(SHELL) $(abs_builddir)/logger_lock_test.sh
|
$(SHELL) $(abs_builddir)/logger_lock_test.sh
|
||||||
$(SHELL) $(abs_builddir)/severity_test.sh
|
$(SHELL) $(abs_builddir)/severity_test.sh
|
||||||
@@ -131,6 +143,7 @@ check-local:
|
|||||||
noinst_SCRIPTS = console_test.sh
|
noinst_SCRIPTS = console_test.sh
|
||||||
noinst_SCRIPTS += destination_test.sh
|
noinst_SCRIPTS += destination_test.sh
|
||||||
noinst_SCRIPTS += init_logger_test.sh
|
noinst_SCRIPTS += init_logger_test.sh
|
||||||
|
noinst_SCRIPTS += buffer_logger_test.sh
|
||||||
noinst_SCRIPTS += local_file_test.sh
|
noinst_SCRIPTS += local_file_test.sh
|
||||||
noinst_SCRIPTS += logger_lock_test.sh
|
noinst_SCRIPTS += logger_lock_test.sh
|
||||||
noinst_SCRIPTS += severity_test.sh
|
noinst_SCRIPTS += severity_test.sh
|
||||||
|
146
src/lib/log/tests/buffer_appender_unittest.cc
Normal file
146
src/lib/log/tests/buffer_appender_unittest.cc
Normal file
@@ -0,0 +1,146 @@
|
|||||||
|
// Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC")
|
||||||
|
//
|
||||||
|
// Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
// purpose with or without fee is hereby granted, provided that the above
|
||||||
|
// copyright notice and this permission notice appear in all copies.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
|
||||||
|
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||||
|
// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||||
|
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||||
|
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
||||||
|
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||||
|
// PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
|
#include <log/macros.h>
|
||||||
|
#include <log/logger_support.h>
|
||||||
|
#include <log/log_messages.h>
|
||||||
|
#include <log/buffer_appender_impl.h>
|
||||||
|
|
||||||
|
#include <log4cplus/loggingmacros.h>
|
||||||
|
#include <log4cplus/logger.h>
|
||||||
|
#include <log4cplus/nullappender.h>
|
||||||
|
#include <log4cplus/spi/loggingevent.h>
|
||||||
|
|
||||||
|
using namespace isc::log;
|
||||||
|
using namespace isc::log::internal;
|
||||||
|
|
||||||
|
namespace isc {
|
||||||
|
namespace log {
|
||||||
|
|
||||||
|
/// \brief Specialized test class
|
||||||
|
///
|
||||||
|
/// In order to test append() somewhat directly, this
|
||||||
|
/// class implements one more method (addEvent)
|
||||||
|
class TestBufferAppender : public BufferAppender {
|
||||||
|
public:
|
||||||
|
void addEvent(const log4cplus::spi::InternalLoggingEvent& event) {
|
||||||
|
append(event);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class BufferAppenderTest : public ::testing::Test {
|
||||||
|
protected:
|
||||||
|
BufferAppenderTest() : buffer_appender1(new TestBufferAppender()),
|
||||||
|
appender1(buffer_appender1),
|
||||||
|
buffer_appender2(new TestBufferAppender()),
|
||||||
|
appender2(buffer_appender2),
|
||||||
|
logger(log4cplus::Logger::getInstance("buffer"))
|
||||||
|
{
|
||||||
|
logger.setLogLevel(log4cplus::TRACE_LOG_LEVEL);
|
||||||
|
}
|
||||||
|
|
||||||
|
~BufferAppenderTest() {
|
||||||
|
// If any log messages are left, we don't care, get rid of them,
|
||||||
|
// by flushing them to a null appender
|
||||||
|
// Given the 'messages should not get lost' approach of the logging
|
||||||
|
// system, not flushing them to a null appender would cause them
|
||||||
|
// to be dumped to stdout as the test is destroyed, making
|
||||||
|
// unnecessarily messy test output.
|
||||||
|
log4cplus::SharedAppenderPtr null_appender(
|
||||||
|
new log4cplus::NullAppender());
|
||||||
|
logger.removeAllAppenders();
|
||||||
|
logger.addAppender(null_appender);
|
||||||
|
buffer_appender1->flush();
|
||||||
|
buffer_appender2->flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
TestBufferAppender* buffer_appender1;
|
||||||
|
log4cplus::SharedAppenderPtr appender1;
|
||||||
|
TestBufferAppender* buffer_appender2;
|
||||||
|
log4cplus::SharedAppenderPtr appender2;
|
||||||
|
log4cplus::Logger logger;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Test that log events are indeed stored, and that they are
|
||||||
|
// flushed to the new appenders of their logger
|
||||||
|
TEST_F(BufferAppenderTest, flush) {
|
||||||
|
ASSERT_EQ(0, buffer_appender1->getBufferSize());
|
||||||
|
ASSERT_EQ(0, buffer_appender2->getBufferSize());
|
||||||
|
|
||||||
|
// Create a Logger, log a few messages with the first appender
|
||||||
|
logger.addAppender(appender1);
|
||||||
|
LOG4CPLUS_INFO(logger, "Foo");
|
||||||
|
ASSERT_EQ(1, buffer_appender1->getBufferSize());
|
||||||
|
LOG4CPLUS_INFO(logger, "Foo");
|
||||||
|
ASSERT_EQ(2, buffer_appender1->getBufferSize());
|
||||||
|
LOG4CPLUS_INFO(logger, "Foo");
|
||||||
|
ASSERT_EQ(3, buffer_appender1->getBufferSize());
|
||||||
|
|
||||||
|
// Second buffer should still be empty
|
||||||
|
ASSERT_EQ(0, buffer_appender2->getBufferSize());
|
||||||
|
|
||||||
|
// Replace the appender by the second one, and call flush;
|
||||||
|
// this should cause all events to be moved to the second buffer
|
||||||
|
logger.removeAllAppenders();
|
||||||
|
logger.addAppender(appender2);
|
||||||
|
buffer_appender1->flush();
|
||||||
|
ASSERT_EQ(0, buffer_appender1->getBufferSize());
|
||||||
|
ASSERT_EQ(3, buffer_appender2->getBufferSize());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Once flushed, logging new messages with the same buffer should fail
|
||||||
|
TEST_F(BufferAppenderTest, addAfterFlush) {
|
||||||
|
logger.addAppender(appender1);
|
||||||
|
buffer_appender1->flush();
|
||||||
|
EXPECT_THROW(LOG4CPLUS_INFO(logger, "Foo"), LogBufferAddAfterFlush);
|
||||||
|
// It should not have been added
|
||||||
|
ASSERT_EQ(0, buffer_appender1->getBufferSize());
|
||||||
|
|
||||||
|
// But logging should work again as long as a different buffer is used
|
||||||
|
logger.removeAllAppenders();
|
||||||
|
logger.addAppender(appender2);
|
||||||
|
LOG4CPLUS_INFO(logger, "Foo");
|
||||||
|
ASSERT_EQ(1, buffer_appender2->getBufferSize());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(BufferAppenderTest, addDirectly) {
|
||||||
|
// A few direct calls
|
||||||
|
log4cplus::spi::InternalLoggingEvent event("buffer",
|
||||||
|
log4cplus::INFO_LOG_LEVEL,
|
||||||
|
"Bar", "file", 123);
|
||||||
|
buffer_appender1->addEvent(event);
|
||||||
|
ASSERT_EQ(1, buffer_appender1->getBufferSize());
|
||||||
|
|
||||||
|
// Do one from a smaller scope to make sure destruction doesn't harm
|
||||||
|
{
|
||||||
|
log4cplus::spi::InternalLoggingEvent event2("buffer",
|
||||||
|
log4cplus::INFO_LOG_LEVEL,
|
||||||
|
"Bar", "file", 123);
|
||||||
|
buffer_appender1->addEvent(event2);
|
||||||
|
}
|
||||||
|
ASSERT_EQ(2, buffer_appender1->getBufferSize());
|
||||||
|
|
||||||
|
// And flush them to the next
|
||||||
|
logger.removeAllAppenders();
|
||||||
|
logger.addAppender(appender2);
|
||||||
|
buffer_appender1->flush();
|
||||||
|
ASSERT_EQ(0, buffer_appender1->getBufferSize());
|
||||||
|
ASSERT_EQ(2, buffer_appender2->getBufferSize());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
71
src/lib/log/tests/buffer_logger_test.cc
Normal file
71
src/lib/log/tests/buffer_logger_test.cc
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
// Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC")
|
||||||
|
//
|
||||||
|
// Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
// purpose with or without fee is hereby granted, provided that the above
|
||||||
|
// copyright notice and this permission notice appear in all copies.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
|
||||||
|
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||||
|
// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||||
|
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||||
|
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
||||||
|
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||||
|
// PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
|
||||||
|
#include <log/macros.h>
|
||||||
|
#include <log/logger_support.h>
|
||||||
|
#include <log/logger_manager.h>
|
||||||
|
#include <log/log_messages.h>
|
||||||
|
#include <util/interprocess_sync_null.h>
|
||||||
|
|
||||||
|
using namespace isc::log;
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
void usage() {
|
||||||
|
std::cout << "Usage: buffer_logger_test [-n]" << std::endl;
|
||||||
|
}
|
||||||
|
} // end unnamed namespace
|
||||||
|
|
||||||
|
/// \brief Test InitLogger
|
||||||
|
///
|
||||||
|
/// A program used in testing the logger that initializes logging with
|
||||||
|
/// buffering enabled, so that initial log messages are not immediately
|
||||||
|
/// logged, but are not lost (they should be logged the moment process()
|
||||||
|
/// is called.
|
||||||
|
///
|
||||||
|
/// If -n is given as an argument, process() is never called. In this
|
||||||
|
/// case, upon exit, all leftover log messages should be printed to
|
||||||
|
/// stdout, but without normal logging additions (such as time and
|
||||||
|
/// logger name)
|
||||||
|
int
|
||||||
|
main(int argc, char** argv) {
|
||||||
|
bool do_process = true;
|
||||||
|
int opt;
|
||||||
|
while ((opt = getopt(argc, argv, "n")) != -1) {
|
||||||
|
switch (opt) {
|
||||||
|
case 'n':
|
||||||
|
do_process = false;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
usage();
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note, level is INFO, so DEBUG should normally not show
|
||||||
|
// up. Unless process is never called (at which point it
|
||||||
|
// will end up in the dump at the end).
|
||||||
|
initLogger("buffertest", isc::log::INFO, 0, NULL, true);
|
||||||
|
Logger logger("log");
|
||||||
|
// No need for file interprocess locking in this test
|
||||||
|
logger.setInterprocessSync(new isc::util::InterprocessSyncNull("logger"));
|
||||||
|
LOG_INFO(logger, LOG_BAD_SEVERITY).arg("info");
|
||||||
|
LOG_DEBUG(logger, 50, LOG_BAD_DESTINATION).arg("debug-50");
|
||||||
|
LOG_INFO(logger, LOG_BAD_SEVERITY).arg("info");
|
||||||
|
// process should cause them to be logged
|
||||||
|
if (do_process) {
|
||||||
|
LoggerManager logger_manager;
|
||||||
|
logger_manager.process();
|
||||||
|
}
|
||||||
|
return (0);
|
||||||
|
}
|
61
src/lib/log/tests/buffer_logger_test.sh.in
Executable file
61
src/lib/log/tests/buffer_logger_test.sh.in
Executable file
@@ -0,0 +1,61 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC")
|
||||||
|
#
|
||||||
|
# Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
# purpose with or without fee is hereby granted, provided that the above
|
||||||
|
# copyright notice and this permission notice appear in all copies.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
|
||||||
|
# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||||
|
# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||||
|
# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||||
|
# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
||||||
|
# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||||
|
# PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
|
||||||
|
# Checks that the initLogger() call uses for unit tests respects the setting of
|
||||||
|
# the buffer value
|
||||||
|
#
|
||||||
|
|
||||||
|
testname="bufferLogger test"
|
||||||
|
echo $testname
|
||||||
|
|
||||||
|
failcount=0
|
||||||
|
tempfile=@abs_builddir@/buffer_logger_test_tempfile_$$
|
||||||
|
|
||||||
|
passfail() {
|
||||||
|
if [ $1 -eq 0 ]; then
|
||||||
|
echo " pass"
|
||||||
|
else
|
||||||
|
echo " FAIL"
|
||||||
|
failcount=`expr $failcount + $1`
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
echo "1. Checking that buffer initialization works"
|
||||||
|
|
||||||
|
echo -n " - Buffer including process() call: "
|
||||||
|
cat > $tempfile << .
|
||||||
|
INFO [buffertest.log] LOG_BAD_SEVERITY unrecognized log severity: info
|
||||||
|
INFO [buffertest.log] LOG_BAD_SEVERITY unrecognized log severity: info
|
||||||
|
.
|
||||||
|
./buffer_logger_test 2>&1 | \
|
||||||
|
sed -e 's/\[\([a-z0-9\.]\{1,\}\)\/\([0-9]\{1,\}\)\]/[\1]/' | \
|
||||||
|
cut -d' ' -f3- | diff $tempfile -
|
||||||
|
passfail $?
|
||||||
|
|
||||||
|
echo -n " - Buffer excluding process() call: "
|
||||||
|
cat > $tempfile << .
|
||||||
|
INFO [buffertest.log]: LOG_BAD_SEVERITY unrecognized log severity: info
|
||||||
|
DEBUG [buffertest.log]: LOG_BAD_DESTINATION unrecognized log destination: debug-50
|
||||||
|
INFO [buffertest.log]: LOG_BAD_SEVERITY unrecognized log severity: info
|
||||||
|
.
|
||||||
|
./buffer_logger_test -n 2>&1 | diff $tempfile -
|
||||||
|
passfail $?
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Tidy up.
|
||||||
|
rm -f $tempfile
|
||||||
|
|
||||||
|
exit $failcount
|
@@ -34,7 +34,7 @@ import bind10_config
|
|||||||
import isc.log
|
import isc.log
|
||||||
from isc.log_messages.cfgmgr_messages import *
|
from isc.log_messages.cfgmgr_messages import *
|
||||||
|
|
||||||
logger = isc.log.Logger("cfgmgr")
|
logger = isc.log.Logger("cfgmgr", buffer=True)
|
||||||
|
|
||||||
class ConfigManagerDataReadError(Exception):
|
class ConfigManagerDataReadError(Exception):
|
||||||
"""This exception is thrown when there is an error while reading
|
"""This exception is thrown when there is an error while reading
|
||||||
@@ -224,8 +224,13 @@ class ConfigManager:
|
|||||||
|
|
||||||
def check_logging_config(self, config):
|
def check_logging_config(self, config):
|
||||||
if self.log_module_name in config:
|
if self.log_module_name in config:
|
||||||
|
# If there is logging config, apply it.
|
||||||
ccsession.default_logconfig_handler(config[self.log_module_name],
|
ccsession.default_logconfig_handler(config[self.log_module_name],
|
||||||
self.log_config_data)
|
self.log_config_data)
|
||||||
|
else:
|
||||||
|
# If there is no logging config, we still need to trigger the
|
||||||
|
# handler, so make it use defaults (and flush any buffered logs)
|
||||||
|
ccsession.default_logconfig_handler({}, self.log_config_data)
|
||||||
|
|
||||||
def notify_boss(self):
|
def notify_boss(self):
|
||||||
"""Notifies the Boss module that the Config Manager is running"""
|
"""Notifies the Boss module that the Config Manager is running"""
|
||||||
@@ -313,11 +318,11 @@ class ConfigManager:
|
|||||||
self.config = ConfigManagerData.read_from_file(self.data_path,
|
self.config = ConfigManagerData.read_from_file(self.data_path,
|
||||||
self.\
|
self.\
|
||||||
database_filename)
|
database_filename)
|
||||||
self.check_logging_config(self.config.data);
|
|
||||||
except ConfigManagerDataEmpty:
|
except ConfigManagerDataEmpty:
|
||||||
# ok, just start with an empty config
|
# ok, just start with an empty config
|
||||||
self.config = ConfigManagerData(self.data_path,
|
self.config = ConfigManagerData(self.data_path,
|
||||||
self.database_filename)
|
self.database_filename)
|
||||||
|
self.check_logging_config(self.config.data);
|
||||||
|
|
||||||
def write_config(self):
|
def write_config(self):
|
||||||
"""Write the current configuration to the file specificied at init()"""
|
"""Write the current configuration to the file specificied at init()"""
|
||||||
|
@@ -166,17 +166,23 @@ reset(PyObject*, PyObject*) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
PyObject*
|
PyObject*
|
||||||
init(PyObject*, PyObject* args) {
|
init(PyObject*, PyObject* args, PyObject* arg_keywords) {
|
||||||
const char* root;
|
const char* root;
|
||||||
const char* file(NULL);
|
const char* file(NULL);
|
||||||
const char* severity("INFO");
|
const char* severity("INFO");
|
||||||
|
bool buffer = false;
|
||||||
int dbglevel(0);
|
int dbglevel(0);
|
||||||
if (!PyArg_ParseTuple(args, "s|siz", &root, &severity, &dbglevel, &file)) {
|
const char* const keywords[] = { "name", "severity", "debuglevel", "file",
|
||||||
|
"buffer", NULL };
|
||||||
|
if (!PyArg_ParseTupleAndKeywords(args, arg_keywords, "s|sizb",
|
||||||
|
const_cast<char**>(keywords), &root,
|
||||||
|
&severity, &dbglevel, &file, &buffer)) {
|
||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
LoggerManager::init(root, getSeverity(severity), dbglevel, file);
|
LoggerManager::init(root, getSeverity(severity), dbglevel, file,
|
||||||
|
buffer);
|
||||||
}
|
}
|
||||||
catch (const std::exception& e) {
|
catch (const std::exception& e) {
|
||||||
PyErr_SetString(PyExc_RuntimeError, e.what());
|
PyErr_SetString(PyExc_RuntimeError, e.what());
|
||||||
@@ -266,12 +272,19 @@ PyMethodDef methods[] = {
|
|||||||
"need to call it. It returns None if the message does not exist."},
|
"need to call it. It returns None if the message does not exist."},
|
||||||
{"reset", reset, METH_NOARGS,
|
{"reset", reset, METH_NOARGS,
|
||||||
"Reset all logging. For testing purposes only, do not use."},
|
"Reset all logging. For testing purposes only, do not use."},
|
||||||
{"init", init, METH_VARARGS,
|
{"init", reinterpret_cast<PyCFunction>(init), METH_VARARGS | METH_KEYWORDS,
|
||||||
"Run-time initialization. You need to call this before you do any "
|
"Run-time initialization. You need to call this before you do any "
|
||||||
"logging, to configure the root logger name. You may also provide "
|
"logging, to configure the root logger name. You may also provide "
|
||||||
"logging severity (one of 'DEBUG', 'INFO', 'WARN', 'ERROR' or "
|
"Arguments:\n"
|
||||||
"'FATAL'), a debug level (integer in the range 0-99) and a file name "
|
"name: root logger name\n"
|
||||||
"of a dictionary with message text translations."},
|
"severity (optional): one of 'DEBUG', 'INFO', 'WARN', 'ERROR' or "
|
||||||
|
"'FATAL'\n"
|
||||||
|
"debuglevel (optional): a debug level (integer in the range 0-99) "
|
||||||
|
"file (optional): a file name of a dictionary with message text "
|
||||||
|
"translations\n"
|
||||||
|
"buffer (optional), boolean, when True, causes all log messages "
|
||||||
|
"to be stored internally until log_config_update is called, at "
|
||||||
|
"which point they shall be logged."},
|
||||||
{"resetUnitTestRootLogger", resetUnitTestRootLogger, METH_VARARGS,
|
{"resetUnitTestRootLogger", resetUnitTestRootLogger, METH_VARARGS,
|
||||||
"Resets the configuration of the root logger to that set by the "
|
"Resets the configuration of the root logger to that set by the "
|
||||||
"B10_XXX environment variables. It is aimed at unit tests, where "
|
"B10_XXX environment variables. It is aimed at unit tests, where "
|
||||||
|
@@ -56,6 +56,28 @@ class Manager(unittest.TestCase):
|
|||||||
# ignore errors like missing file?
|
# ignore errors like missing file?
|
||||||
isc.log.init("root", "INFO", 0, "/no/such/file");
|
isc.log.init("root", "INFO", 0, "/no/such/file");
|
||||||
|
|
||||||
|
def test_init_keywords(self):
|
||||||
|
isc.log.init(name="root", severity="DEBUG", debuglevel=50, file=None,
|
||||||
|
buffer=True)
|
||||||
|
# unknown keyword
|
||||||
|
self.assertRaises(TypeError, isc.log.init, name="root", foo="bar")
|
||||||
|
# Replace the values for each keyword by a wrong type, one by one
|
||||||
|
self.assertRaises(TypeError, isc.log.init, name=1,
|
||||||
|
severity="DEBUG", debuglevel=50, file=None,
|
||||||
|
buffer=True)
|
||||||
|
self.assertRaises(TypeError, isc.log.init, name="root",
|
||||||
|
severity=2, debuglevel=50, file=None,
|
||||||
|
buffer=True)
|
||||||
|
self.assertRaises(TypeError, isc.log.init, name="root",
|
||||||
|
severity="DEBUG", debuglevel="50", file=None,
|
||||||
|
buffer=True)
|
||||||
|
self.assertRaises(TypeError, isc.log.init, name="root",
|
||||||
|
severity="DEBUG", debuglevel=50, file=1,
|
||||||
|
buffer=True)
|
||||||
|
self.assertRaises(TypeError, isc.log.init, name="root",
|
||||||
|
severity="DEBUG", debuglevel=50, file=None,
|
||||||
|
buffer=None)
|
||||||
|
|
||||||
def test_log_config_update(self):
|
def test_log_config_update(self):
|
||||||
log_spec = json.dumps(isc.config.module_spec_from_file(path_search('logging.spec', bind10_config.PLUGIN_PATHS)).get_full_spec())
|
log_spec = json.dumps(isc.config.module_spec_from_file(path_search('logging.spec', bind10_config.PLUGIN_PATHS)).get_full_spec())
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user