diff --git a/configure.ac b/configure.ac index 348708fde1..8bd37a2347 100644 --- a/configure.ac +++ b/configure.ac @@ -920,6 +920,7 @@ AC_OUTPUT([doc/version.ent src/lib/cc/tests/session_unittests_config.h src/lib/log/tests/console_test.sh src/lib/log/tests/destination_test.sh + src/lib/log/tests/init_logger_test.sh src/lib/log/tests/local_file_test.sh src/lib/log/tests/severity_test.sh src/lib/log/tests/tempdir.h @@ -949,9 +950,10 @@ AC_OUTPUT([doc/version.ent chmod +x src/bin/msgq/tests/msgq_test chmod +x src/lib/dns/gen-rdatacode.py chmod +x src/lib/dns/tests/testdata/gen-wiredata.py - chmod +x src/lib/log/tests/local_file_test.sh chmod +x src/lib/log/tests/console_test.sh chmod +x src/lib/log/tests/destination_test.sh + chmod +x src/lib/log/tests/init_logger_test.sh + chmod +x src/lib/log/tests/local_file_test.sh chmod +x src/lib/log/tests/severity_test.sh chmod +x src/lib/util/python/mkpywrapper.py chmod +x src/lib/python/isc/log/tests/log_console.py diff --git a/src/bin/resolver/Makefile.am b/src/bin/resolver/Makefile.am index bce8307515..2cbf140bd6 100644 --- a/src/bin/resolver/Makefile.am +++ b/src/bin/resolver/Makefile.am @@ -59,6 +59,7 @@ nodist_b10_resolver_SOURCES = resolver_messages.cc resolver_messages.h b10_resolver_LDADD = $(top_builddir)/src/lib/dns/libdns++.la b10_resolver_LDADD += $(top_builddir)/src/lib/config/libcfgclient.la b10_resolver_LDADD += $(top_builddir)/src/lib/cc/libcc.la +b10_resolver_LDADD += $(top_builddir)/src/lib/util/libutil.la b10_resolver_LDADD += $(top_builddir)/src/lib/exceptions/libexceptions.la b10_resolver_LDADD += $(top_builddir)/src/lib/asiodns/libasiodns.la b10_resolver_LDADD += $(top_builddir)/src/lib/asiolink/libasiolink.la @@ -67,6 +68,7 @@ b10_resolver_LDADD += $(top_builddir)/src/lib/log/liblog.la b10_resolver_LDADD += $(top_builddir)/src/lib/server_common/libserver_common.la b10_resolver_LDADD += $(top_builddir)/src/lib/cache/libcache.la b10_resolver_LDADD += $(top_builddir)/src/lib/nsas/libnsas.la +b10_resolver_LDADD += $(top_builddir)/src/lib/acl/libacl.la b10_resolver_LDADD += $(top_builddir)/src/lib/resolve/libresolve.la b10_resolver_LDADD += $(top_builddir)/src/bin/auth/change_user.o b10_resolver_LDFLAGS = -pthread diff --git a/src/lib/log/README b/src/lib/log/README index d854dce0ba..cd7cd72e25 100644 --- a/src/lib/log/README +++ b/src/lib/log/README @@ -410,6 +410,44 @@ logger "pkt-auth".) As the loggers are independent and the severity levels independent, fine-tuning of what and what is not recorded can be achieved. +Logging Initialization +====================== +In all cases, if an attempt is made to use a logging method before the logging +has been initialized, the program will terminate with a LoggingNotInitialized +call. + +C++ +--- +Logging Initialization is carried out by calling initLogger(). There are two +variants to the call, one for use by production programs and one for use by +unit tests. + +Variant #1, Used by Production Programs +--------------------------------------- + void initLogger(const std::string& root, + isc::log::Severity severity = isc::log::INFO, + int dbglevel = 0, const char* file = NULL); + +This is the call that should be used by production programs: + +root +Name of the program (e.g. "b10-auth"). This is also the name of the root +logger and is used when configuring logging. + +severity +Default severity that the program will start logging with. Although this may +be overridden when the program obtains its configuration from the configuration +database, this is the severity that it used until then. (This may be set by +a command-line parameter.) + +dbglevel +The debug level used if "severity" is set to isc::log::DEBUG. + +file +The name of a local message file. This will be read and its defintitions used +to replace the compiled-in text of the messages. + + Notes ===== @@ -419,3 +457,47 @@ in both the message compiler and the server; in the server it is used when the server starts up (or when triggered by a command) to read in a message file to overwrite the internal dictionary. Writing it in C++ means there is only one piece of code that does this functionality. + + +Variant #2, Used by Unit Tests +------------------------------ + void initLogger() + +This is the call that should be used by unit tests. In this variant, all the +options are supplied by environment variables. (It should not be used for +production programs to avoid the chance that the program operation is affected +by inadvertantly-defined environment variables.) + +The environment variables are: + +B10_LOGGER_ROOT +Sets the "root" for the unit test. If not defined, the name "bind10" is used. + +B10_LOGGER_SEVERITY +The severity to set for the root logger in the unit test. Valid values are +"DEBUG", "INFO", "WARN", "ERROR", "FATAL" and "NONE". If not defined, "INFO" +is used. + +B10_LOGGER_DBGLEVEL +If B10_LOGGER_SEVERITY is set to "DEBUG", the debug level. This can be a +number between 0 and 99, and defaults to 0. + +B10_LOGGER_LOCALMSG +If defined, points to a local message file. The default is not to use a local +message file. + +B10_LOGGER_DESTINATION +The location to which log message are written. This can be one of: + + stdout Message are written to stdout + stderr Messages are written to stderr + syslog[:facility] Messages are written to syslog. If the optional + "facility" is used, the messages are written using + that facility. (This defaults to "local7" if not + specified) + Anything else Interpreted as the name of a file to which output + is appended. If the file does not exist, a new one + is opened. + +In the case of "stdout", "stderr" and "syslog", they must be written exactly +as is - no leading or trailing spaces, and in lower-case. diff --git a/src/lib/log/logger_support.cc b/src/lib/log/logger_support.cc index 73323a03f7..eac2fbbe8b 100644 --- a/src/lib/log/logger_support.cc +++ b/src/lib/log/logger_support.cc @@ -31,7 +31,9 @@ #include #include +#include #include +#include using namespace std; @@ -40,6 +42,68 @@ namespace { // Flag to hold logging initialization state. bool logging_init_state = false; + +// Set logging destination according to the setting of B10_LOGGER_DESTINATION. +// (See header for initLogger() for more details.) +void +setDestination(const char* root, const isc::log::Severity severity, + const int dbglevel) { + + using namespace isc::log; + + // Constants: + static const string STDOUT = "stdout"; + static const string STDERR = "stderr"; + static const string SYSLOG = "syslog"; + static const string SYSLOG_COLON = "syslog:"; + + + const char* destination = getenv("B10_LOGGER_DESTINATION"); + if (destination != NULL) { + + // Destination is present, adjust root logger destination to it. + LoggerSpecification spec(root, severity, dbglevel); + OutputOption option; + + const string dest = destination; + if (dest == STDOUT) { + option.destination = OutputOption::DEST_CONSOLE; + option.stream = OutputOption::STR_STDOUT; + + } else if (dest == STDERR) { + option.destination = OutputOption::DEST_CONSOLE; + option.stream = OutputOption::STR_STDERR; + + } else if (dest == SYSLOG) { + option.destination = OutputOption::DEST_SYSLOG; + option.facility = "local0"; + + } else if (dest.find(SYSLOG_COLON) == 0) { + option.destination = OutputOption::DEST_SYSLOG; + // Must take account of the string actually being "syslog:". + if (dest == SYSLOG_COLON) { + cerr << "**ERROR** value for B10_LOGGER_DESTINATION of " << + SYSLOG_COLON << " is invalid, " << SYSLOG << + " will be used instead\n"; + option.facility = "local0"; + } else { + // Everything else is the facility name + option.facility = dest.substr(SYSLOG_COLON.size()); + } + + } else { + // Not a recognised destination, assume a file. + option.destination = OutputOption::DEST_FILE; + option.filename = dest; + } + + // ... and set it. + spec.addOutputOption(option); + LoggerManager manager; + manager.process(spec); + } +} + } // Anonymous namespace namespace isc { @@ -115,11 +179,14 @@ void initLogger(isc::log::Severity severity, int dbglevel) { } } - /// Set the local message file + // Set the local message file const char* localfile = getenv("B10_LOGGER_LOCALMSG"); // Initialize logging initLogger(root, severity, dbglevel, localfile); + + // Now set the destination + setDestination(root, severity, dbglevel); } } // namespace log diff --git a/src/lib/log/logger_support.h b/src/lib/log/logger_support.h index 4bc8acc195..cf83abcb32 100644 --- a/src/lib/log/logger_support.h +++ b/src/lib/log/logger_support.h @@ -68,26 +68,37 @@ void initLogger(const std::string& root, /// Performs run-time initialization of the logger via the setting of /// environment variables. These are: /// -/// B10_LOGGER_ROOT +/// - B10_LOGGER_ROOT\n /// Name of the root logger. If not given, the string "bind10" will be used. /// -/// B10_LOGGER_SEVERITY +/// - B10_LOGGER_SEVERITY\n /// Severity of messages that will be logged. This must be one of the strings /// "DEBUG", "INFO", "WARN", "ERROR", "FATAL" or "NONE". (Must be upper case /// and must not contain leading or trailing spaces.) If not specified (or if /// specified but incorrect), the default passed as argument to this function /// (currently INFO) will be used. /// -/// B10_LOGGER_DBGLEVEL +/// - B10_LOGGER_DBGLEVEL\n /// Ignored if the level is not DEBUG, this should be a number between 0 and /// 99 indicating the logging severity. The default is 0. If outside these /// limits or if not a number, The value passed to this function (default /// of 0) is used. /// -/// B10_LOGGER_LOCALMSG +/// - B10_LOGGER_LOCALMSG\n /// If defined, the path specification of a file that contains message /// definitions replacing ones in the default dictionary. /// +/// - B10_LOGGER_DESTINATION\n +/// If defined, the destination of the logging output. This can be one of: +/// - \c stdout Send output to stdout. +/// - \c stderr Send output to stderr +/// - \c syslog Send output to syslog using the facility local0. +/// - \c syslog:xxx Send output to syslog, using the facility xxx. ("xxx" +/// should be one of the syslog facilities such as "local0".) There must +/// be a colon between "syslog" and "xxx +/// - \c other Anything else is interpreted as the name of a file to which +/// output is appended. If the file does not exist, it is created. +/// /// Any errors in the settings cause messages to be output to stderr. /// /// This function is aimed at test programs, allowing the default settings to diff --git a/src/lib/log/tests/Makefile.am b/src/lib/log/tests/Makefile.am index cd2ae2920f..6159d6303a 100644 --- a/src/lib/log/tests/Makefile.am +++ b/src/lib/log/tests/Makefile.am @@ -52,12 +52,23 @@ logger_example_LDFLAGS = $(AM_LDFLAGS) $(LOG4CPLUS_LDFLAGS) logger_example_LDADD = $(top_builddir)/src/lib/log/liblog.la logger_example_LDADD += $(top_builddir)/src/lib/util/libutil.la +check_PROGRAMS += init_logger_test +init_logger_test_SOURCES = init_logger_test.cc +init_logger_test_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES) +init_logger_test_LDFLAGS = $(AM_LDFLAGS) $(LOG4CPLUS_LDFLAGS) +init_logger_test_LDADD = $(top_builddir)/src/lib/log/liblog.la +init_logger_test_LDADD += $(top_builddir)/src/lib/util/libutil.la + noinst_PROGRAMS = $(TESTS) -# Additional test using the shell -PYTESTS = console_test.sh local_file_test.sh severity_test.sh +# Additional test using the shell. These are principally tests +# where the global logging environment is affected, and where the +# output needs to be compared with stored output (where "cut" and +# "diff" are useful utilities). + check-local: $(SHELL) $(abs_builddir)/console_test.sh $(SHELL) $(abs_builddir)/destination_test.sh + $(SHELL) $(abs_builddir)/init_logger_test.sh $(SHELL) $(abs_builddir)/local_file_test.sh $(SHELL) $(abs_builddir)/severity_test.sh diff --git a/src/lib/log/tests/init_logger_test.cc b/src/lib/log/tests/init_logger_test.cc new file mode 100644 index 0000000000..3cf52024fc --- /dev/null +++ b/src/lib/log/tests/init_logger_test.cc @@ -0,0 +1,41 @@ +// Copyright (C) 2011 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 +#include +#include + +using namespace isc::log; + +/// \brief Test InitLogger +/// +/// A test program that initializes using initLogger(), then outputs several +/// messages at different severities. An external script sets the environment +/// variables and checks that they have the desired effect. + +int +main(int, char**) { + initLogger(); + Logger logger("log"); + + LOG_DEBUG(logger, 0, LOG_BAD_DESTINATION).arg("debug-0"); + LOG_DEBUG(logger, 50, LOG_BAD_DESTINATION).arg("debug-50"); + LOG_DEBUG(logger, 99, LOG_BAD_DESTINATION).arg("debug-99"); + LOG_INFO(logger, LOG_BAD_SEVERITY).arg("info"); + LOG_WARN(logger, LOG_BAD_STREAM).arg("warn"); + LOG_ERROR(logger, LOG_DUPLICATE_MESSAGE_ID).arg("error"); + LOG_FATAL(logger, LOG_NO_MESSAGE_ID).arg("fatal"); + + return (0); +} diff --git a/src/lib/log/tests/init_logger_test.sh.in b/src/lib/log/tests/init_logger_test.sh.in new file mode 100755 index 0000000000..6e199a43f7 --- /dev/null +++ b/src/lib/log/tests/init_logger_test.sh.in @@ -0,0 +1,115 @@ +#!/bin/sh +# Copyright (C) 2011 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. + +# \brief Severity test +# +# Checks that the logger will limit the output of messages less severy than +# the severity/debug setting. + +testname="initLogger test" +echo $testname + +failcount=0 +tempfile=@abs_builddir@/init_logger_test_tempfile_$$ +destfile=@abs_builddir@/init_logger_test_destfile_$$ + +passfail() { + if [ $1 -eq 0 ]; then + echo " pass" + else + echo " FAIL" + failcount=`expr $failcount + $1` + fi +} + +echo "1. Checking that B10_LOGGER_SEVERITY/B10_LOGGER_DBGLEVEL work" + +echo -n " - severity=DEBUG, dbglevel=99: " +cat > $tempfile << . +DEBUG [bind10.log] LOG_BAD_DESTINATION unrecognized log destination: debug-0 +DEBUG [bind10.log] LOG_BAD_DESTINATION unrecognized log destination: debug-50 +DEBUG [bind10.log] LOG_BAD_DESTINATION unrecognized log destination: debug-99 +INFO [bind10.log] LOG_BAD_SEVERITY unrecognized log severity: info +WARN [bind10.log] LOG_BAD_STREAM bad log console output stream: warn +ERROR [bind10.log] LOG_DUPLICATE_MESSAGE_ID duplicate message ID (error) in compiled code +FATAL [bind10.log] LOG_NO_MESSAGE_ID line fatal: message definition line found without a message ID +. +rm -f $destfile +B10_LOGGER_SEVERITY=DEBUG B10_LOGGER_DBGLEVEL=99 ./init_logger_test 2> $destfile +cut -d' ' -f3- $destfile | diff $tempfile - +passfail $? + +echo -n " - severity=DEBUG, dbglevel=50: " +cat > $tempfile << . +DEBUG [bind10.log] LOG_BAD_DESTINATION unrecognized log destination: debug-0 +DEBUG [bind10.log] LOG_BAD_DESTINATION unrecognized log destination: debug-50 +INFO [bind10.log] LOG_BAD_SEVERITY unrecognized log severity: info +WARN [bind10.log] LOG_BAD_STREAM bad log console output stream: warn +ERROR [bind10.log] LOG_DUPLICATE_MESSAGE_ID duplicate message ID (error) in compiled code +FATAL [bind10.log] LOG_NO_MESSAGE_ID line fatal: message definition line found without a message ID +. +rm -f $destfile +B10_LOGGER_SEVERITY=DEBUG B10_LOGGER_DBGLEVEL=50 ./init_logger_test 2> $destfile +cut -d' ' -f3- $destfile | diff $tempfile - +passfail $? + +echo -n " - severity=WARN: " +cat > $tempfile << . +WARN [bind10.log] LOG_BAD_STREAM bad log console output stream: warn +ERROR [bind10.log] LOG_DUPLICATE_MESSAGE_ID duplicate message ID (error) in compiled code +FATAL [bind10.log] LOG_NO_MESSAGE_ID line fatal: message definition line found without a message ID +. +rm -f $destfile +B10_LOGGER_SEVERITY=WARN ./init_logger_test 2> $destfile +cut -d' ' -f3- $destfile | diff $tempfile - +passfail $? + +echo "2. Checking that B10_LOGGER_DESTINATION works" + +echo -n " - stdout: " +cat > $tempfile << . +FATAL [bind10.log] LOG_NO_MESSAGE_ID line fatal: message definition line found without a message ID +. +rm -f $destfile +B10_LOGGER_SEVERITY=FATAL B10_LOGGER_DESTINATION=stdout ./init_logger_test 1> $destfile +cut -d' ' -f3- $destfile | diff $tempfile - +passfail $? + +echo -n " - stderr: " +rm -f $destfile +B10_LOGGER_SEVERITY=FATAL B10_LOGGER_DESTINATION=stderr ./init_logger_test 2> $destfile +cut -d' ' -f3- $destfile | diff $tempfile - +passfail $? + +echo -n " - file: " +rm -f $destfile +B10_LOGGER_SEVERITY=FATAL B10_LOGGER_DESTINATION=$destfile ./init_logger_test +cut -d' ' -f3- $destfile | diff $tempfile - +passfail $? + +# Note: can't automatically test syslog output. + +if [ $failcount -eq 0 ]; then + echo "PASS: $testname" +elif [ $failcount -eq 1 ]; then + echo "FAIL: $testname - 1 test failed" +else + echo "FAIL: $testname - $failcount tests failed" +fi + +# Tidy up. +rm -f $tempfile $destfile + +exit $failcount diff --git a/src/lib/log/tests/severity_test.sh.in b/src/lib/log/tests/severity_test.sh.in index 124f36af5d..a5827ded98 100755 --- a/src/lib/log/tests/severity_test.sh.in +++ b/src/lib/log/tests/severity_test.sh.in @@ -33,7 +33,7 @@ passfail() { fi } -echo -n "1. runInitTest default parameters:" +echo -n "1. Default parameters:" cat > $tempfile << . FATAL [example] LOG_WRITE_ERROR error writing to test1: 42 ERROR [example] LOG_READING_LOCAL_FILE reading local message file dummy/file