123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305 |
- // 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 Example Program
- ///
- /// Simple example program showing how to use the logger. The various
- /// command-line options let most aspects of the logger be exercised, so
- /// making this a useful tool for testing.
- ///
- /// See the usage() method for details of use.
- #include <stdlib.h>
- #include <unistd.h>
- #include <string.h>
- #include <boost/lexical_cast.hpp>
- #include <iostream>
- #include <string>
- #include <vector>
- #include <util/strutil.h>
- #include <log/logger.h>
- #include <log/logger_level.h>
- #include <log/logger_manager.h>
- #include <log/logger_name.h>
- #include <log/logger_specification.h>
- #include <log/macros.h>
- // Include a set of message definitions.
- #include <log/messagedef.h>
- using namespace isc::log;
- using namespace std;
- // Print usage information
- void usage() {
- cout <<
- "logger_support_test [-h | [logger_spec] [[logger_spec]...]]\n"
- "\n"
- " -h Print this message and exit\n"
- "\n"
- "The rest of the command line comprises the set of logger specifications.\n"
- "Each specification is of the form:\n"
- "\n"
- " -l logger [-s severity] [-d dbglevel] output_spec] [[output_spec] ...\n"
- "\n"
- "where:\n"
- "\n"
- " -l logger Give the name of the logger to which the following\n"
- " output specifications will apply.\n"
- "\n"
- "Each logger is followed by the indication of the serverity it is logging\n"
- "and, if applicable, its debug level:\n"
- "\n"
- " -d dbglevel Debug level. Only interpreted if the severity is 'debug'\n"
- " this is a number between 0 and 99.\n"
- " -s severity Set the severity of messages output. 'severity' is one\n"
- " of 'debug', 'info', 'warn', 'error', 'fatal', the default\n"
- " being 'info'.\n"
- "\n"
- "The output specifications - there may be more than one per logger - detail\n"
- "the output streams attached to the logger. These are of the form:\n"
- "\n"
- " -c stream | -f file [-m maxver] [-z maxsize] | -y facility\n"
- "\n"
- "These are:\n"
- "\n"
- " -c stream Send output to the console. 'stream' is one of 'stdout'\n"
- " of 'stderr'.\n"
- " -f file Send output to specified file, appending to existing file\n"
- " if one exists.\n"
- " -y facility Send output to the syslog file with the given facility\n"
- " name (e.g. local1, cron etc.)\n"
- "\n"
- "The following can be specified for the file logger:\n"
- "\n"
- " -m maxver If file rolling is selected (by the maximum file size being\n"
- " non-zero), the maximum number of versions to keep (defaults\n"
- " to 0)\n"
- " -z maxsize Maximum size of the file before the file is closed and a\n"
- " new one opened. The default of 0 means no maximum size.\n"
- "\n"
- "If none of -c, -f or -y is given, by default, output is sent to stdout. If no\n"
- "logger is specified, the default is the program's root logger ('example').\n";
- }
- // The program sets the attributes on the root logger and logs a set of
- // messages. Looking at the output determines whether the program worked.
- int main(int argc, char** argv) {
- const string ROOT_NAME = "example";
- bool sw_found = false; // Set true if switch found
- bool c_found = false; // Set true if "-c" found
- bool f_found = false; // Set true if "-f" found
- bool y_found = false; // Set true if "-y" found
- int option; // For getopt() processing
- OutputOption def_opt; // Default output option - used
- // for initialization
- LoggerSpecification cur_spec(ROOT_NAME);// Current specification
- OutputOption cur_opt; // Current output option
- vector<LoggerSpecification> loggers; // Set of logger specifications
- vector<OutputOption> options; // Output options for logger
- std::string severity; // Severity set for logger
- // Initialize logging system - set the root logger name.
- LoggerManager manager;
- manager.init(ROOT_NAME);
- // In the parsing loop that follows, the construction of the logging
- // specification is always "one behind". In other words, the parsing of
- // command-line options updates thge current logging specification/output
- // options. When the flag indicating a new logger or output specification
- // is encountered, the previous one is added to the list.
- //
- // One complication is that there is deemed to be a default active when
- // the parsing starts (console output for the BIND 10 root logger). This
- // is included in the logging specifications UNLESS the first switch on
- // the command line is a "-l" flag starting a new logger. To track this,
- // the "sw_found" flag is set when a switch is completey processed. The
- // processing of "-l" will only add information for a previous logger to
- // the list if this flag is set.
- while ((option = getopt(argc, argv, "hc:d:f:l:m:s:y:z:")) != -1) {
- switch (option) {
- case 'c': // Console output
- // New output spec. If one was currently active, add it to the
- // list and reset the current output option to the defaults.
- if (c_found || f_found || y_found) {
- cur_spec.addOutputOption(cur_opt);
- cur_opt = def_opt;
- c_found = f_found = y_found = false;
- }
- // Set the output option for this switch.
- c_found = true;
- cur_opt.destination = OutputOption::DEST_CONSOLE;
- if (strcmp(optarg, "stdout") == 0) {
- cur_opt.stream = OutputOption::STR_STDOUT;
- } else if (strcmp(optarg, "stderr") == 0) {
- cur_opt.stream = OutputOption::STR_STDERR;
- } else {
- cerr << "Unrecognised console option: " << optarg << "\n";
- return (1);
- }
- break;
- case 'd': // Debug level
- cur_spec.setDbglevel(boost::lexical_cast<int>(optarg));
- break;
- case 'f': // File output specification
- // New output spec. If one was currently active, add it to the
- // list and reset the current output option to the defaults.
- if (c_found || f_found || y_found) {
- cur_spec.addOutputOption(cur_opt);
- cur_opt = def_opt;
- c_found = f_found = y_found = false;
- }
- // Set the output option for this switch.
- f_found = true;
- cur_opt.destination = OutputOption::DEST_FILE;
- cur_opt.filename = optarg;
- break;
- case 'h': // Help
- usage();
- return (0);
- case 'l': // Logger
- // If a current specification is active, add the last output option
- // to it, add it to the list and reset. A specification is active
- // if at least one switch has been previously found.
- if (sw_found) {
- cur_spec.addOutputOption(cur_opt);
- loggers.push_back(cur_spec);
- cur_spec.reset();
- }
- // Set the logger name
- cur_spec.setName(std::string(optarg));
- // Reset the output option to the default.
- cur_opt = def_opt;
- // Indicate nothing is found to prevent the console option (the
- // default output option) being added to the output list if an
- // output option is found.
- c_found = f_found = y_found = false;
- break;
- case 'm': // Maximum file version
- if (!f_found) {
- std::cerr << "Attempt to set maximum version (-m) "
- "outside of file output specification\n";
- return (1);
- }
- try {
- cur_opt.maxsize = boost::lexical_cast<unsigned int>(optarg);
- } catch (boost::bad_lexical_cast&) {
- std::cerr << "Maximum version (-m) argument must be a positive "
- "integer\n";
- return (1);
- }
- break;
- case 's': // Severity
- severity = optarg;
- isc::util::str::uppercase(severity);
- cur_spec.setSeverity(getSeverity(severity));
- break;
- case 'y': // Syslog output
- // New output spec. If one was currently active, add it to the
- // list and reset the current output option to the defaults.
- if (c_found || f_found || y_found) {
- cur_spec.addOutputOption(cur_opt);
- cur_opt = def_opt;
- c_found = f_found = y_found = false;
- }
- y_found = true;
- cur_opt.destination = OutputOption::DEST_SYSLOG;
- cur_opt.facility = optarg;
- break;
- case 'z': // Maximum size
- if (! f_found) {
- std::cerr << "Attempt to set file size (-z) "
- "outside of file output specification\n";
- return (1);
- }
- try {
- cur_opt.maxsize = boost::lexical_cast<size_t>(optarg);
- } catch (boost::bad_lexical_cast&) {
- std::cerr << "File size (-z) argument must be a positive "
- "integer\n";
- return (1);
- }
- break;
- default:
- std::cerr << "Unrecognised option: " <<
- static_cast<char>(option) << "\n";
- return (1);
- }
- // Have found at least one command-line switch, so note the fact.
- sw_found = true;
- }
- // Add the current (unfinished specification) to the list.
- cur_spec.addOutputOption(cur_opt);
- loggers.push_back(cur_spec);
- // Set the logging options.
- manager.process(loggers.begin(), loggers.end());
- // Set the local file
- if (optind < argc) {
- LoggerManager::readLocalMessageFile(argv[optind]);
- }
- // Log a few messages to different loggers.
- isc::log::Logger logger_ex(ROOT_NAME);
- isc::log::Logger logger_alpha("alpha");
- isc::log::Logger logger_beta("beta");
- LOG_FATAL(logger_ex, MSG_WRITERR).arg("test1").arg("42");
- LOG_ERROR(logger_ex, MSG_RDLOCMES).arg("dummy/file");
- LOG_WARN(logger_ex, MSG_BADSTREAM).arg("example");
- LOG_WARN(logger_alpha, MSG_READERR).arg("a.txt").arg("dummy reason");
- LOG_INFO(logger_alpha, MSG_OPENIN).arg("example.msg").arg("dummy reason");
- LOG_DEBUG(logger_ex, 0, MSG_RDLOCMES).arg("example/0");
- LOG_DEBUG(logger_ex, 24, MSG_RDLOCMES).arg("example/24");
- LOG_DEBUG(logger_ex, 25, MSG_RDLOCMES).arg("example/25");
- LOG_DEBUG(logger_ex, 26, MSG_RDLOCMES).arg("example/26");
- LOG_FATAL(logger_beta, MSG_BADSEVERITY).arg("beta_fatal");
- LOG_ERROR(logger_beta, MSG_BADDESTINATION).arg("beta_error");
- LOG_WARN(logger_beta, MSG_BADSTREAM).arg("beta_warn");
- LOG_INFO(logger_beta, MSG_READERR).arg("beta").arg("info");
- LOG_DEBUG(logger_beta, 25, MSG_BADSEVERITY).arg("beta/25");
- LOG_DEBUG(logger_beta, 26, MSG_BADSEVERITY).arg("beta/26");
- return (0);
- }
|