Commit e39dbc26 authored by Stephen Morris's avatar Stephen Morris
Browse files

Merge branch 'trac1071'

parents 2e847339 88c4d5e2
267. [func] stephen
Add environment variable to allow redirection of logging output during
unit tests.
(Trac #1071, git 05164f9d61006869233b498d248486b4307ea8b6)
266. [func] Multiple developers
Convert various error messages, debugging and other output
to the new logging interface, including for b10-resolver,
......
......@@ -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
......
......@@ -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
......
......@@ -142,13 +142,19 @@ Points to note:
the error originated from the logging library and the "WRITE_ERROR"
indicates that there was a problem in a write operation.
* The replacement tokens are the strings "%1", "%2" etc. When a message
is logged, these are replaced with the arguments passed to the logging
call: %1 refers to the first argument, %2 to the second etc. Within the
message text, the placeholders can appear in any order and placeholders
can be repeated.
* Remaining lines indicate an explanation for the preceding message. These
* The rest of the line - from the first non-space character to the
last non- space character - is taken exactly for the text
of the message. There are no restrictions on what characters may
be in this text, other than they be printable. (This means that
both single-quote (') and double-quote (") characters are allowed.)
The message text may include replacement tokens (the strings "%1",
"%2" etc.). When a message is logged, these are replaced with the
arguments passed to the logging call: %1 refers to the first argument,
%2 to the second etc. Within the message text, the placeholders
can appear in any order and placeholders can be repeated. Otherwise,
the message is printed unmodified.
* Remaining lines indicate an explanation for the preceding message. These
are intended to be processed by a separate program and used to generate
an error messages manual. They are ignored by the message compiler.
......@@ -232,8 +238,8 @@ Using the Logging - C++
=======================
1. Build message header file and source file as describe above.
2. The main program unit should include a call to isc::log::initLogger()
(defined in logger_support.h) to set the logging severity, debug log
2. The main program unit must include a call to isc::log::initLogger()
(described in more detail below) to set the logging severity, debug log
level, and external message file:
a) The logging severity is one of the enum defined in logger.h, i.e.
......@@ -279,9 +285,9 @@ Using the Logging - Python
==========================
1. Build message module as describe above.
2. The main program unit should include a call to isc.log.init() to
set the to set the logging severity, debug log level, and external
message file:
2. The main program unit must include a call to isc.log.init()
(described in more detail below) to set the to set the logging
severity, debug log level, and external message file:
a) The logging severity is one of the strings:
......@@ -316,6 +322,91 @@ Using the Logging - Python
logger.error(LOG_WRITE_ERROR, "output.txt");
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
exception.
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 isc::log::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 definitions used
to replace the compiled-in text of the messages.
Variant #2, Used by Unit Tests
------------------------------
void isc::log::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 inadvertently-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 "local0" 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.
Python
------
To be supplied
Severity Guidelines
===================
......
......@@ -31,7 +31,9 @@
#include <log/logger_level.h>
#include <log/logger_manager.h>
#include <log/logger_specification.h>
#include <log/logger_support.h>
#include <log/output_option.h>
using namespace std;
......@@ -40,6 +42,77 @@ 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.) This is a no-op if the
// environment variable is not defined.
//
// \param root Name of the root logger
// \param severity Severity level to be assigned to the root logger
// \param dbglevel Debug level
void
setDestination(const char* root, const isc::log::Severity severity,
const int dbglevel) {
using namespace isc::log;
const char* destination = getenv("B10_LOGGER_DESTINATION");
if (destination != NULL) {
// Constants: not declared static as this is function is expected to be
// called once only
const string STDOUT = "stdout";
const string STDERR = "stderr";
const string SYSLOG = "syslog";
const string SYSLOG_COLON = "syslog:";
// Prepare the objects to define the logging specification
LoggerSpecification spec(root, severity, dbglevel);
OutputOption option;
// Set up output option according to destination specification
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;
// Use default specified in OutputOption constructor for the
// syslog destination
} 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";
// Use default for logging facility
} else {
// Everything else in the string 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 the destination
spec.addOutputOption(option);
LoggerManager manager;
manager.process(spec);
}
}
} // Anonymous namespace
namespace isc {
......@@ -115,11 +188,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 for logging output
setDestination(root, severity, dbglevel);
}
} // namespace log
......
......@@ -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
......
......@@ -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
......@@ -13,8 +13,6 @@
# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
# PERFORMANCE OF THIS SOFTWARE.
# \brief
#
# The logger supports the idea of a "console" logger than logs to either stdout
# or stderr. This test checks that both these options work.
......
......@@ -13,10 +13,7 @@
# 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.
# Checks that the logger will route messages to the chosen destination.
testname="Destination test"
echo $testname
......
// 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 <log/macros.h>
#include <log/logger_support.h>
#include <log/log_messages.h>
using namespace isc::log;
/// \brief Test InitLogger
///
/// A program used in testing the logger that initializes logging using
/// initLogger(), then outputs several messages at different severities and
/// debug levels. 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);
}
#!/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.
# Checks that the initLogger() call uses for unit tests respects the setting of
# the environment variables.
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
.
B10_LOGGER_SEVERITY=DEBUG B10_LOGGER_DBGLEVEL=99 ./init_logger_test 2>&1 | \
cut -d' ' -f3- | 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
.
B10_LOGGER_SEVERITY=DEBUG B10_LOGGER_DBGLEVEL=50 ./init_logger_test 2>&1 | \
cut -d' ' -f3- | 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
.
B10_LOGGER_SEVERITY=WARN ./init_logger_test 2>&1 | \
cut -d' ' -f3- | 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
......@@ -13,8 +13,6 @@
# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
# PERFORMANCE OF THIS SOFTWARE.
# \brief Local message file test
#
# Checks that a local message file can override the definitions in the message
# dictionary.
......
......@@ -13,9 +13,7 @@
# 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
# Checks that the logger will limit the output of messages less severe than
# the severity/debug setting.
testname="Severity test"
......@@ -33,7 +31,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
......
......@@ -38,6 +38,7 @@ run_unittests_LDADD += $(top_builddir)/src/lib/server_common/libserver_common.la
run_unittests_LDADD += $(top_builddir)/src/lib/asiolink/libasiolink.la
run_unittests_LDADD += $(top_builddir)/src/lib/asiodns/libasiodns.la
run_unittests_LDADD += $(top_builddir)/src/lib/cc/libcc.la
run_unittests_LDADD += $(top_builddir)/src/lib/log/liblog.la
run_unittests_LDADD += $(top_builddir)/src/lib/acl/libacl.la
run_unittests_LDADD += $(top_builddir)/src/lib/util/libutil.la
run_unittests_LDADD += $(top_builddir)/src/lib/dns/libdns++.la
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment