diff options
author | randomdan <randomdan@localhost> | 2011-02-10 10:33:36 +0000 |
---|---|---|
committer | randomdan <randomdan@localhost> | 2011-02-10 10:33:36 +0000 |
commit | 66ead1d7832333feb2be2e42fb88af84b59f690b (patch) | |
tree | 705a8548c3df1048e6bcef70f703a01d3867a758 | |
parent | Make different DB connectors optional (diff) | |
download | project2-66ead1d7832333feb2be2e42fb88af84b59f690b.tar.bz2 project2-66ead1d7832333feb2be2e42fb88af84b59f690b.tar.xz project2-66ead1d7832333feb2be2e42fb88af84b59f690b.zip |
Fix silly bug loading readonly RDBMS config entries
Add centralised logging system
Add code for runtime configuration
Add support for configuring logging
Move all existing logging to new logging system
-rw-r--r-- | project2/Jamfile.jam | 4 | ||||
-rw-r--r-- | project2/cgi/cgiAppEngine.cpp | 7 | ||||
-rw-r--r-- | project2/cgi/cgiAppEngine.h | 12 | ||||
-rw-r--r-- | project2/cgi/cgiCommon.cpp | 59 | ||||
-rw-r--r-- | project2/cgi/cgiEnvironment.cpp | 14 | ||||
-rw-r--r-- | project2/cgi/cgiEnvironment.h | 4 | ||||
-rw-r--r-- | project2/cgi/p2webFCgi.cpp | 9 | ||||
-rw-r--r-- | project2/console/consoleEnvironment.cpp | 47 | ||||
-rw-r--r-- | project2/console/consoleEnvironment.h | 12 | ||||
-rw-r--r-- | project2/console/p2consoleMain.cpp | 13 | ||||
-rw-r--r-- | project2/environment.cpp | 49 | ||||
-rw-r--r-- | project2/environment.h | 11 | ||||
-rw-r--r-- | project2/fsRows.cpp | 4 | ||||
-rw-r--r-- | project2/iterate.cpp | 1 | ||||
-rw-r--r-- | project2/logger.cpp | 182 | ||||
-rw-r--r-- | project2/logger.h | 43 | ||||
-rw-r--r-- | project2/loggers.h | 55 | ||||
-rw-r--r-- | project2/rdbmsDataSource.cpp | 14 | ||||
-rw-r--r-- | project2/rowProcessor.cpp | 1 | ||||
-rw-r--r-- | project2/rowSet.cpp | 4 | ||||
-rw-r--r-- | project2/sessionSetTask.cpp | 1 | ||||
-rw-r--r-- | project2/sqlMergeTask.cpp | 2 | ||||
-rw-r--r-- | project2/tablepatch.cpp | 1 | ||||
-rw-r--r-- | project2/variables.cpp | 1 |
24 files changed, 487 insertions, 63 deletions
diff --git a/project2/Jamfile.jam b/project2/Jamfile.jam index 53b530f..040991e 100644 --- a/project2/Jamfile.jam +++ b/project2/Jamfile.jam @@ -18,6 +18,7 @@ lib fcgi++ : : <name>fcgi++ ; lib boost_regex : : <name>boost_regex ; lib boost_filesystem : : <name>boost_filesystem ; lib boost_date_time : : <name>boost_date_time ; +lib boost_program_options : : <name>boost_program_options ; lib cgicc : : <name>cgicc ; lib esmtp : : <name>esmtp ; lib curl : : <name>curl ; @@ -47,7 +48,7 @@ lib p2uuid : lib p2common : appEngine.cpp dataSource.cpp environment.cpp fileStarGlibIoChannel.cpp iHaveParameters.cpp - iterate.cpp paramChecker.cpp presenter.cpp rawView.cpp dumpTask.cpp + iterate.cpp paramChecker.cpp presenter.cpp rawView.cpp dumpTask.cpp logger.cpp sourceObject.cpp task.cpp variables.cpp view.cpp xmlObjectLoader.cpp exceptions.cpp sessionClearTask.cpp session.cpp sessionSetTask.cpp commonObjects.cpp xmlPresenter.cpp rowView.cpp rowSet.cpp rowUser.cpp rowProcessor.cpp config.cpp @@ -56,6 +57,7 @@ lib p2common : <library>libxmlpp <library>boost_filesystem <library>boost_date_time + <library>boost_program_options ; lib p2xml : diff --git a/project2/cgi/cgiAppEngine.cpp b/project2/cgi/cgiAppEngine.cpp index 3a9e362..364d393 100644 --- a/project2/cgi/cgiAppEngine.cpp +++ b/project2/cgi/cgiAppEngine.cpp @@ -1,5 +1,4 @@ #include "cgiAppEngine.h" -#include <syslog.h> #include <cgicc/Cgicc.h> #include <cgicc/HTTPContentHeader.h> #include "cgiEnvironment.h" @@ -48,6 +47,12 @@ CgiApplicationEngine::env() const } void +CgiApplicationEngine::write(const XmlWriter & w) const +{ + w(doc->cobj()); +} + +void CgiApplicationEngine::process() const { while (!doc && currentStage) { diff --git a/project2/cgi/cgiAppEngine.h b/project2/cgi/cgiAppEngine.h index 5a21e98..25c6537 100644 --- a/project2/cgi/cgiAppEngine.h +++ b/project2/cgi/cgiAppEngine.h @@ -8,6 +8,7 @@ #include "../commonObjects.h" #include "../uuid.h" #include <boost/intrusive_ptr.hpp> +#include <boost/function.hpp> #include <libxml++/document.h> #include <libxml++/parsers/domparser.h> @@ -19,16 +20,15 @@ namespace cgicc { class CgiApplicationEngine : public ApplicationEngine { public: + typedef boost::shared_ptr<xmlpp::Document> XmlDocPtr; + typedef boost::function1<void, xmlDocPtr> XmlWriter; + CgiApplicationEngine(const CgiEnvironment *); virtual ~CgiApplicationEngine(); void process() const; const cgicc::HTTPContentHeader * getHeader() const { return header; } - template <class Writer> - void write(const Writer & w) const - { - w(doc->cobj()); - } + void write(const XmlWriter & w) const; const Environment * env() const; SessionPtr session() const; virtual Glib::ustring resolveCurrentConfig() const; @@ -45,7 +45,7 @@ class CgiApplicationEngine : public ApplicationEngine { bool checkDomain(const DomainPlatforms::value_type & i) const; void loadEngineSection(const xmlpp::Element *) const; - mutable boost::shared_ptr<xmlpp::Document> doc; + mutable XmlDocPtr doc; class Stage; typedef boost::intrusive_ptr<Stage> StagePtr; diff --git a/project2/cgi/cgiCommon.cpp b/project2/cgi/cgiCommon.cpp index bfbec36..322bdf7 100644 --- a/project2/cgi/cgiCommon.cpp +++ b/project2/cgi/cgiCommon.cpp @@ -1,10 +1,10 @@ #include "cgiCommon.h" +#include "../logger.h" #include <libxml/tree.h> #include <glibmm/exception.h> #include <cgicc/CgiEnvironment.h> #include <cgicc/HTTPContentHeader.h> #include <cgicc/HTTPStatusHeader.h> -#include <fcgi_stdio.h> #include "cgiEnvironment.h" #include "cgiAppEngine.h" #include <boost/bind.hpp> @@ -19,41 +19,62 @@ xmlWrite(void * _out, const char * buf, int len) return len; } +// These are templates because some people don't inherit their +// exceptions from std::exception like normal people (Glib) +const char * +what(const Glib::Exception & e) +{ + return e.what().c_str(); +} +const char * +what(const std::exception & e) +{ + return e.what(); +} +template <typename E> +void +doExceptionReporting(const E & e, std::ostream & IO) +{ + char * buf = __cxxabiv1::__cxa_demangle(typeid(e).name(), NULL, NULL, NULL); + Logger()->messagef(LOG_ERR, "%s: Request errored: %s: %s", __FUNCTION__, buf, what(e)); + cgicc::HTTPStatusHeader header(500, e.what()); + header.render(IO); + IO << "Kaboom!" << std::endl + << std::endl + << buf << std::endl + << e.what() << std::endl; + free(buf); +} + void cgiServe(cgicc::CgiInput * i, std::ostream & IO) { + cgicc::Cgicc cgi(i); + CgiEnvironment env(&cgi); + env.init(); try { - cgicc::Cgicc cgi(i); - CgiEnvironment env(&cgi); CgiApplicationEngine app(&env); + + Logger()->messagef(LOG_DEBUG, "%s: Processing request", __FUNCTION__); app.process(); + + Logger()->messagef(LOG_DEBUG, "%s: Sending request result", __FUNCTION__); IO << "Cache-control: no-cache" << std::endl; app.getHeader()->render(IO); xmlOutputBufferPtr out = xmlOutputBufferCreateIO( xmlWrite, NULL, &IO, xmlGetCharEncodingHandler(XML_CHAR_ENCODING_UTF8)); app.write(boost::bind(xmlSaveFileTo, out, _1, "utf-8")); + + Logger()->messagef(LOG_DEBUG, "%s: Completed request", __FUNCTION__); } catch (const std::exception & e) { - cgicc::HTTPStatusHeader header(500, e.what()); - header.render(IO); - char * buf = __cxxabiv1::__cxa_demangle(typeid(e).name(), NULL, NULL, NULL); - IO << "Kaboom!" << std::endl - << std::endl - << buf << std::endl - << e.what() << std::endl; - free(buf); + doExceptionReporting(e, IO); } catch (const Glib::Exception & e) { - cgicc::HTTPStatusHeader header(500, e.what()); - header.render(IO); - char * buf = __cxxabiv1::__cxa_demangle(typeid(e).name(), NULL, NULL, NULL); - IO << "Kaboom!" << std::endl - << std::endl - << buf << std::endl - << e.what() << std::endl; - free(buf); + doExceptionReporting(e, IO); } catch (...) { + Logger()->messagef(LOG_ERR, "%s: Request errored: Unknown exception", __FUNCTION__); cgicc::HTTPStatusHeader header(500, "Unknown exception"); header.render(IO); IO << "Kaboom!" << std::endl diff --git a/project2/cgi/cgiEnvironment.cpp b/project2/cgi/cgiEnvironment.cpp index e541f7f..ae65183 100644 --- a/project2/cgi/cgiEnvironment.cpp +++ b/project2/cgi/cgiEnvironment.cpp @@ -2,7 +2,6 @@ #include "../appEngine.h" #include "../exceptions.h" #include <map> -#include <syslog.h> #include <cgicc/Cgicc.h> #include <boost/tokenizer.hpp> @@ -13,6 +12,7 @@ std::vector<X>makeVector(const Y & y) } CgiEnvironment::CgiEnvironment(cgicc::Cgicc * c) : + Environment(0, NULL), cgicc::CgiEnvironment(c->getEnvironment()), elems(makeVector<std::string>(boost::tokenizer<boost::char_separator<char> >(getRedirectURL(), boost::char_separator<char>("/")))), cgi(c) @@ -23,6 +23,18 @@ CgiEnvironment::~CgiEnvironment() { } +boost::program_options::options_description +CgiEnvironment::addOptions(boost::program_options::positional_options_description &) +{ + boost::program_options::options_description cgi("Project2 CGI options"); + return cgi; +} + +void +CgiEnvironment::postinit(const boost::program_options::options_description &, const boost::program_options::variables_map &) +{ +} + Glib::ustring CgiEnvironment::getParamUri(unsigned int p) const { diff --git a/project2/cgi/cgiEnvironment.h b/project2/cgi/cgiEnvironment.h index 5c0455c..005a49b 100644 --- a/project2/cgi/cgiEnvironment.h +++ b/project2/cgi/cgiEnvironment.h @@ -22,6 +22,10 @@ class CgiEnvironment : public Environment, public cgicc::CgiEnvironment { std::vector<std::string> elems; const cgicc::Cgicc * const cgi; + + private: + boost::program_options::options_description addOptions(boost::program_options::positional_options_description &); + void postinit(const boost::program_options::options_description &, const boost::program_options::variables_map &); }; #endif diff --git a/project2/cgi/p2webFCgi.cpp b/project2/cgi/p2webFCgi.cpp index 620c441..d501787 100644 --- a/project2/cgi/p2webFCgi.cpp +++ b/project2/cgi/p2webFCgi.cpp @@ -1,7 +1,7 @@ -#include <syslog.h> #include "cgiCommon.h" #include "FCgiIO.h" #include "../xmlObjectLoader.h" +#include "../logger.h" time_t lastPeriodic = 0; time_t periodicDelay = 600; @@ -28,7 +28,6 @@ int main(void) { if (!FCGX_IsCGI()) { - syslog(LOG_NOTICE, "FCGID Startup ($Id$)"); FCGX_Request request; FCGX_Init(); @@ -38,7 +37,7 @@ main(void) onAlarm.sa_handler = &p2webGoingIdle; onAlarm.sa_flags = 0; if (sigaction(SIGALRM, &onAlarm, NULL)) { - syslog(LOG_WARNING, "Failed to set signal handler"); + fprintf(stderr, "Failed to set signal handler\n"); } alarm(60); while (FCGX_Accept_r(&request) == 0) { @@ -51,9 +50,9 @@ main(void) p2webPeriodic(); } } + return 0; } else { - syslog(LOG_ERR, "FCGID not running as a FastCGI program"); + return 1; } - return 0; } diff --git a/project2/console/consoleEnvironment.cpp b/project2/console/consoleEnvironment.cpp index 0d2f026..1c39dd0 100644 --- a/project2/console/consoleEnvironment.cpp +++ b/project2/console/consoleEnvironment.cpp @@ -1,13 +1,17 @@ #include "consoleEnvironment.h" #include <sys/utsname.h> -#include <syslog.h> #include <errno.h> #include <stdio.h> #include <string.h> +#include "../logger.h" +#include <iostream> +#include <string> +#include <boost/program_options.hpp> + +namespace po = boost::program_options; ConsoleEnvironment::ConsoleEnvironment(int argc, char ** argv) : - scriptname(argv[0]), - todolist(argv + 1, argv + argc) + Environment(argc, argv) { } @@ -15,6 +19,33 @@ ConsoleEnvironment::~ConsoleEnvironment() { } +boost::program_options::options_description +ConsoleEnvironment::addOptions(boost::program_options::positional_options_description & poptions) +{ + boost::program_options::options_description console("Project2 Console options"); + console.add_options() + //("version,v", "Print version and exit") + ("help,h", "Print usage and exit") + ("syslogident,i", po::value<std::string>(&scriptname)->default_value(scriptname), "Log to syslog with ident <arg>") + ("file,f", po::value<ToDoList>(&todolist), "File to process") + ; + poptions.add("file", -1); + return console; +} + +void +ConsoleEnvironment::postinit(const boost::program_options::options_description & options, const boost::program_options::variables_map & settings) +{ + if (settings.count("version")) { + //show_version(version); + exit(1); + } + if (settings.count("help")) { + std::cout << options << std::endl; + exit(1); + } +} + Glib::ustring ConsoleEnvironment::getParamUri(unsigned int idx) const { @@ -32,8 +63,8 @@ ConsoleEnvironment::getServerName() const { struct utsname name; if (uname(&name)) { - syslog(LOG_WARNING, "%s: Unable to determine local host name (%d:%s)", - __FUNCTION__, errno, strerror(errno)); + Logger()->messagef(LOG_WARNING, "%s: Unable to determine local host name (%d:%s)", + __PRETTY_FUNCTION__, errno, strerror(errno)); return "unknown"; } else { @@ -47,3 +78,9 @@ ConsoleEnvironment::getScriptName() const return scriptname; } +const ConsoleEnvironment::ToDoList & +ConsoleEnvironment::todoList() const +{ + return todolist; +} + diff --git a/project2/console/consoleEnvironment.h b/project2/console/consoleEnvironment.h index faa6431..23bbd05 100644 --- a/project2/console/consoleEnvironment.h +++ b/project2/console/consoleEnvironment.h @@ -2,22 +2,28 @@ #define ENVPROC_H #include <string> -#include <list> +#include <vector> #include <boost/filesystem/path.hpp> #include "../environment.h" class ConsoleEnvironment : public Environment { public: + typedef std::vector<boost::filesystem::path> ToDoList; + ConsoleEnvironment(int argc, char ** argv); virtual ~ConsoleEnvironment(); + Glib::ustring getParamUri(unsigned int idx) const; Glib::ustring getParamQuery(const std::string & idx) const; std::string getServerName() const; std::string getScriptName() const; + const ToDoList & todoList() const; - const std::string scriptname; - typedef std::list<boost::filesystem::path> ToDoList; + private: + boost::program_options::options_description addOptions(boost::program_options::positional_options_description &); + void postinit(const boost::program_options::options_description &, const boost::program_options::variables_map &); + std::string scriptname; ToDoList todolist; }; diff --git a/project2/console/p2consoleMain.cpp b/project2/console/p2consoleMain.cpp index eb3ff0d..eee7603 100644 --- a/project2/console/p2consoleMain.cpp +++ b/project2/console/p2consoleMain.cpp @@ -1,14 +1,21 @@ #include <libxml/tree.h> #include "consoleEnvironment.h" #include "consoleAppEngine.h" -#include <iostream> +#include "../logger.h" -int main(int argc, char ** argv) +int +main(int argc, char ** argv) { ConsoleEnvironment env(argc, argv); - BOOST_FOREACH(const boost::filesystem::path & file, env.todolist) { + env.init(); + BOOST_FOREACH(const boost::filesystem::path & file, env.todoList()) { + Logger()->messagef(LOG_DEBUG, "%s: Beginning file '%s'", __FUNCTION__, file.string().c_str()); ConsoleApplicationEngine app(&env, file); + + Logger()->messagef(LOG_DEBUG, "%s: Processing file", __FUNCTION__); app.process(); + + Logger()->messagef(LOG_DEBUG, "%s: Complete", __FUNCTION__); LoaderBase::onIteration(); } LoaderBase::onPeriodic(); diff --git a/project2/environment.cpp b/project2/environment.cpp index c0cc0fa..5c50517 100644 --- a/project2/environment.cpp +++ b/project2/environment.cpp @@ -1,11 +1,58 @@ #include "environment.h" +#include "loggers.h" +#include <stdio.h> +#include <fstream> +#include <boost/filesystem/convenience.hpp> -Environment::Environment() +namespace po = boost::program_options; + +Environment::Environment(int c, char ** v) : + argc(c), + argv(v) +{ +} + +void +Environment::init() { + int clLevel = -1; + int slLevel = -1; + + po::options_description common("Project2 Common options"); + po::positional_options_description poptions; + common.add_options() + ("sysloglevel,s", po::value<int>(&slLevel)->default_value(-1), + "Log to syslog with level <arg> (default OFF)") + ("consoleloglevel,c", po::value<int>(&clLevel)->default_value(LOG_WARNING), + "Log to console with level <arg> (default WARNING)") + ; + po::options_description all("Project2 options"); + all.add(common).add(addOptions(poptions)); + + po::variables_map settings; + if (argc > 0 && argv != NULL) { + po::store(po::command_line_parser(argc, argv).options(all).positional(poptions).run(), settings); + } + po::store(po::parse_environment(all, "P2_"), settings); + if (boost::filesystem::exists(".p2config")) { + std::ifstream f(".p2config"); + po::store(po::parse_config_file(f, all), settings); + } + po::notify(settings); + + postinit(all, settings); + + if (clLevel >= 0) { + Logger()->addLogger(new ConsoleLogDriver(stderr, clLevel, false)); + } + if (slLevel >= 0) { + Logger()->addLogger(new SyslogLogDriver(getScriptName().c_str(), slLevel)); + } } Environment::~Environment() { + Logger()->clear(); } Glib::ustring diff --git a/project2/environment.h b/project2/environment.h index 97ae4f1..60b5f66 100644 --- a/project2/environment.h +++ b/project2/environment.h @@ -3,20 +3,29 @@ #include <string> #include <glibmm/ustring.h> +#include <boost/program_options.hpp> +#include <boost/function.hpp> class Environment { public: class ParameterTypeNotSupported : public std::exception { }; - Environment(); + + Environment(int argc, char ** argv); virtual ~Environment() = 0; + void init(); + virtual Glib::ustring getParamUri(unsigned int idx) const = 0; virtual Glib::ustring getParamQuery(const std::string & idx) const = 0; virtual std::string getServerName() const = 0; virtual std::string getScriptName() const = 0; private: + virtual boost::program_options::options_description addOptions(boost::program_options::positional_options_description &) = 0; + virtual void postinit(const boost::program_options::options_description &, const boost::program_options::variables_map &) = 0; + int argc; + char ** argv; }; #endif diff --git a/project2/fsRows.cpp b/project2/fsRows.cpp index b55e058..1b2d2ce 100644 --- a/project2/fsRows.cpp +++ b/project2/fsRows.cpp @@ -1,4 +1,5 @@ #include "fsRows.h" +#include "logger.h" #include "xmlObjectLoader.h" #include "rowProcessor.h" #include "exceptions.h" @@ -8,7 +9,6 @@ #include <boost/algorithm/string/split.hpp> #include <boost/bind.hpp> #include <boost/lexical_cast.hpp> -#include <syslog.h> #include <sys/types.h> #include <pwd.h> #include <grp.h> @@ -194,7 +194,7 @@ FsRows::execute(const Path & dir, const RowProcessor * rp) const } } catch (const boost::filesystem::basic_filesystem_error<Path> & e) { - fprintf(stderr, "err %s\n", e.what()); + Logger()->messagef(LOG_WARNING, "%s when processing '%s'", e.what(), dir.string().c_str()); } depth -= 1; } diff --git a/project2/iterate.cpp b/project2/iterate.cpp index f4c8d81..d56fd31 100644 --- a/project2/iterate.cpp +++ b/project2/iterate.cpp @@ -1,6 +1,5 @@ #include "iterate.h" #include <boost/foreach.hpp> -#include <syslog.h> #include "xmlObjectLoader.h" ElementLoaderImpl<Iterate> iterateLoader("iterate"); diff --git a/project2/logger.cpp b/project2/logger.cpp new file mode 100644 index 0000000..6133ce9 --- /dev/null +++ b/project2/logger.cpp @@ -0,0 +1,182 @@ +#define SYSLOG_NAMES 1 // Enables the definition of names in syslog.h + +#include "logger.h" +#include "loggers.h" +#include <stdio.h> +#include <boost/foreach.hpp> +#include <boost/algorithm/string/case_conv.hpp> + +const char * const version = "$Id: logger.cpp 8818 2011-01-10 10:09:59Z danielg $"; + +Log Logger::log; + +Log::Log() : + lowestLevel(-1) +{ +} + +Log::~Log() +{ + logs.clear(); +} + +int +Log::addLogger(LogDriverBasePtr log) +{ + logs[++nextId] = log; + if (log->level > lowestLevel) { + lowestLevel = log->level; + } + return nextId; +} + +void +Log::clear() +{ + logs.clear(); +} + +const char * +Log::priorityName(int priority) +{ + const char * name = NULL; + for (CODE * c = prioritynames; c->c_name; c++) { + if (c->c_val == priority) { + name = c->c_name; + } + } + return name; +} + + +void +Log::message(int priority, const char * msg) const +{ + if (priority > lowestLevel) return; + BOOST_FOREACH(const LogDrivers::value_type & l, logs) { + l.second->message(priority, msg); + } +} + +void +Log::messagef(int priority, const char * msgfmt, ...) const +{ + if (priority > lowestLevel) return; + va_list v; + va_start(v, msgfmt); + vmessagef(priority, msgfmt, v); + va_end(v); +} + +void +Log::vmessagef(int priority, const char * msgfmt, va_list va) const +{ + if (priority > lowestLevel) return; + char * msg; + int len = vasprintf(&msg, msgfmt, va); + if (len > 0) { + message(priority, msg); + } + free(msg); +} + +Log * +Logger::operator->() const +{ + return &log; +} + +LogDriverBase::LogDriverBase(int l) : + level(l) +{ +} + +LogDriverBase::~LogDriverBase() +{ +} + +// File based log driver +//---------------------- +FileBasedLogDriver::FileBasedLogDriver(FILE * f, int l, bool ts) : + LogDriverBase(l), + file(f), + timestamp(ts) +{ +} +FileBasedLogDriver::~FileBasedLogDriver() +{ +} +void +FileBasedLogDriver::message(int priority, const char * msg) const +{ + if (priority <= level) { + writeTimestamp(); + writeLevel(priority); + fprintf(file, "%s\n", msg); + fflush(file); + } +} +const char * +FileBasedLogDriver::timeStr() const +{ + struct tm tm; + time_t t = time(NULL); + localtime_r(&t, &tm); + strftime(tmbuf, sizeof(tmbuf), "%F %T", &tm); + return tmbuf; +} +void +FileBasedLogDriver::writeTimestamp() const +{ + if (timestamp) { + fprintf(file, "%s ", timeStr()); + } +} +void +FileBasedLogDriver::writeLevel(int level) const +{ + if (timestamp) { + fprintf(file, "%-6.*s", 5, boost::algorithm::to_upper_copy(std::string(Log::priorityName(level))).c_str()); + } +} + +// Consol driver +//------------------- +ConsoleLogDriver::ConsoleLogDriver(FILE * f, int l, bool ts) : + FileBasedLogDriver(f, l, ts) +{ +} +ConsoleLogDriver::~ConsoleLogDriver() +{ +} + +// File log driver +//------------------- +FileLogDriver::FileLogDriver(const char * path, int l) : + FileBasedLogDriver(fopen(path, "a"), l, true) +{ +} +FileLogDriver::~FileLogDriver() +{ + fclose(file); +} + +// Syslog Log Driver +//------------------- +SyslogLogDriver::SyslogLogDriver(const char * ident, int level, int option, int facility) : + LogDriverBase(level) +{ + openlog(ident, option, facility); +} +SyslogLogDriver::~SyslogLogDriver() +{ + closelog(); +} +void +SyslogLogDriver::message(int priority, const char * msg) const +{ + if (priority <= level) { + syslog(priority, "%s", msg); + } +} + diff --git a/project2/logger.h b/project2/logger.h new file mode 100644 index 0000000..5d42631 --- /dev/null +++ b/project2/logger.h @@ -0,0 +1,43 @@ +#ifndef LOGGER_H +#define LOGGER_H + +#include <map> +#include <stdarg.h> +#include <syslog.h> // Pulled in for easy client lookups of LOG_* priorties +#include <boost/intrusive_ptr.hpp> +#include "intrusivePtrBase.h" + +class LogDriverBase; + +class Log { + public: + typedef boost::intrusive_ptr<LogDriverBase> LogDriverBasePtr; + typedef std::map<int, LogDriverBasePtr> LogDrivers; + + Log(); + ~Log(); + + int addLogger(LogDriverBasePtr); + void clear(); + + void message(int priority, const char * msg) const; + void messagef(int priority, const char * msgfmt, ...) const __attribute__ ((format (printf, 3, 4))); + void vmessagef(int priority, const char * msgfmt, va_list) const; + + static const char * priorityName(int priority); // Look up the priority as defined in syslog.h + + private: + LogDrivers logs; + int lowestLevel; + int nextId; +}; + +class Logger { + public: + Log * operator->() const; + private: + static Log log; +}; + +#endif + diff --git a/project2/loggers.h b/project2/loggers.h new file mode 100644 index 0000000..7be5280 --- /dev/null +++ b/project2/loggers.h @@ -0,0 +1,55 @@ +#ifndef LOGGERS_H +#define LOGGERS_H + +#include "logger.h" + +class LogDriverBase : public virtual IntrusivePtrBase { + public: + LogDriverBase(int level); + virtual ~LogDriverBase(); + + virtual void message(int priority, const char * msg) const = 0; + const int level; +}; + +class FileBasedLogDriver : public LogDriverBase { + public: + FileBasedLogDriver(FILE *, int level, bool timestamp); + virtual ~FileBasedLogDriver() = 0; + + virtual void message(int priority, const char * msg) const; + + protected: + void writeTimestamp() const; + void writeLevel(int level) const; + FILE * file; + bool timestamp; + + private: + const char * timeStr() const; + mutable char tmbuf[30]; +}; + +class ConsoleLogDriver : public FileBasedLogDriver { + public: + ConsoleLogDriver(FILE *, int level, bool timestamp); + ~ConsoleLogDriver(); + +}; + +class FileLogDriver : public FileBasedLogDriver { + public: + FileLogDriver(const char * path, int level); + ~FileLogDriver(); +}; + +class SyslogLogDriver : public LogDriverBase { + public: + SyslogLogDriver(const char * ident, int level, int option = 0, int facility = LOG_USER); + virtual ~SyslogLogDriver(); + + virtual void message(int priority, const char * msg) const; +}; + +#endif + diff --git a/project2/rdbmsDataSource.cpp b/project2/rdbmsDataSource.cpp index bd3c0b1..6d9e566 100644 --- a/project2/rdbmsDataSource.cpp +++ b/project2/rdbmsDataSource.cpp @@ -2,7 +2,7 @@ #include "xmlObjectLoader.h" #include <libxml++/nodes/textnode.h> #include <sys/utsname.h> -#include <syslog.h> +#include "logger.h" #include <errno.h> #include <sqlext.h> @@ -56,7 +56,7 @@ RdbmsDataSource::RdbmsDataSource(const xmlpp::Element * p) : BOOST_FOREACH(const xmlpp::Node * node, p->find("readonly/dsn")) { const xmlpp::Element * elem = dynamic_cast<const xmlpp::Element *>(node); if (elem) { - roDSNs.insert(ReadonlyDSNs::value_type(elem->get_attribute_value("host"), p)); + roDSNs.insert(ReadonlyDSNs::value_type(elem->get_attribute_value("host"), elem)); } } } @@ -90,8 +90,8 @@ RdbmsDataSource::getReadonly() const if (localhost.length() == 0 && preferLocal) { struct utsname name; if (uname(&name)) { - syslog(LOG_WARNING, "%s: Unable to determine local host name (%d:%s)", - __FUNCTION__, errno, strerror(errno)); + Logger()->messagef(LOG_WARNING, "%s: Unable to determine local host name (%d:%s)", + __PRETTY_FUNCTION__, errno, strerror(errno)); localhost = "unknown"; } else { @@ -102,8 +102,8 @@ RdbmsDataSource::getReadonly() const ReadonlyDSNs::const_iterator ro = roDSNs.find(localhost); try { if (ro == roDSNs.end()) { - syslog(LOG_WARNING, "%s: No database host matches local host name (%s) Will use master DSN", - __FUNCTION__, localhost.c_str()); + Logger()->messagef(LOG_WARNING, "%s: No database host matches local host name (%s) Will use master DSN", + __PRETTY_FUNCTION__, localhost.c_str()); return *connectTo(masterDsn)->connection; } return *connectTo(ro->second)->connection; @@ -162,7 +162,7 @@ RdbmsDataSource::connectTo(const ConnectionInfo & dsn) } catch (...) { // Connection in failed state - syslog(LOG_WARNING, "%s: Cached connection failed", __FUNCTION__); + Logger()->messagef(LOG_DEBUG, "%s: Cached connection failed", __PRETTY_FUNCTION__); } } diff --git a/project2/rowProcessor.cpp b/project2/rowProcessor.cpp index 71d2548..fbb470a 100644 --- a/project2/rowProcessor.cpp +++ b/project2/rowProcessor.cpp @@ -2,7 +2,6 @@ #include "commonObjects.h" #include <cstdlib> #include <boost/foreach.hpp> -#include <syslog.h> RowProcessor::RowProcessor(const xmlpp::Element * p) : SourceObject(p), diff --git a/project2/rowSet.cpp b/project2/rowSet.cpp index 318407a..2e4b3f7 100644 --- a/project2/rowSet.cpp +++ b/project2/rowSet.cpp @@ -1,9 +1,9 @@ #include "rowSet.h" #include "rowUser.h" #include "commonObjects.h" +#include "logger.h" #include <boost/foreach.hpp> #include <boost/bind.hpp> -#include <syslog.h> RowSet::RowValuesStack RowSet::stack; @@ -39,7 +39,7 @@ void RowSet::endRow(const RowSet * r) { if (stack.back() != r) { - syslog(LOG_ERR, "RowSet::endRow: stack is corrupted"); + Logger()->messagef(LOG_CRIT, "%s: stack is corrupted", __PRETTY_FUNCTION__); std::abort(); } stack.pop_back(); diff --git a/project2/sessionSetTask.cpp b/project2/sessionSetTask.cpp index a4b0e44..401604b 100644 --- a/project2/sessionSetTask.cpp +++ b/project2/sessionSetTask.cpp @@ -1,4 +1,3 @@ -#include <syslog.h> #include <boost/foreach.hpp> #include "xmlObjectLoader.h" #include "sessionSetTask.h" diff --git a/project2/sqlMergeTask.cpp b/project2/sqlMergeTask.cpp index f707a77..f59cc97 100644 --- a/project2/sqlMergeTask.cpp +++ b/project2/sqlMergeTask.cpp @@ -1,5 +1,5 @@ #include "sqlMergeTask.h" -#include "appEngine.h" +#include "commonObjects.h" #include "rdbmsDataSource.h" #include "exceptions.h" #include "sqlVariableBinder.h" diff --git a/project2/tablepatch.cpp b/project2/tablepatch.cpp index 8acc8da..540da5e 100644 --- a/project2/tablepatch.cpp +++ b/project2/tablepatch.cpp @@ -1,5 +1,4 @@ #include "tablepatch.h" -#include <syslog.h> #include <stdio.h> #include <misc.h> #include <selectcommand.h> diff --git a/project2/variables.cpp b/project2/variables.cpp index 20b4fa2..32a1a15 100644 --- a/project2/variables.cpp +++ b/project2/variables.cpp @@ -6,7 +6,6 @@ #include "genericVisitor.h" #include <libxml++/nodes/textnode.h> #include <stdexcept> -#include <syslog.h> #include <boost/tokenizer.hpp> #include <boost/foreach.hpp> #include <boost/algorithm/string/predicate.hpp> |