From 39a254ce9f2bf1e4de5945a331266afa33350a5e Mon Sep 17 00:00:00 2001 From: Adrien Beraud Date: Tue, 30 May 2017 12:19:58 +0200 Subject: [PATCH] log: add syslog support Add support to log using standard syslog, add related option in dhtnode. dhtnode will use syslog by default when starting in daemon mode and no logfile is defined. --- include/opendht/log.h | 5 +++-- src/log.cpp | 39 ++++++++++++++++++++++++++++++++++++--- tools/dhtnode.cpp | 4 +++- tools/tools_common.h | 6 ++++++ 4 files changed, 48 insertions(+), 6 deletions(-) diff --git a/include/opendht/log.h b/include/opendht/log.h index 2c69aede..220eaa70 100644 --- a/include/opendht/log.h +++ b/include/opendht/log.h @@ -22,8 +22,6 @@ #include "dhtrunner.h" #include -#include -#include namespace dht { namespace log { @@ -73,5 +71,8 @@ enableFileLogging(dht::DhtRunner &dht, const std::string &path); OPENDHT_PUBLIC void disableLogging(dht::DhtRunner &dht); +OPENDHT_PUBLIC void +enableSyslog(dht::DhtRunner &dht, const char* name); + } /* log */ } /* dht */ diff --git a/src/log.cpp b/src/log.cpp index 74ec0115..6b63a610 100644 --- a/src/log.cpp +++ b/src/log.cpp @@ -19,6 +19,13 @@ #include "log.h" +#ifndef _WIN32 +#include +#endif + +#include +#include + namespace dht { namespace log { @@ -37,9 +44,9 @@ printLog(std::ostream& s, char const *m, va_list args) { using namespace std::chrono; using log_precision = microseconds; constexpr auto den = log_precision::period::den; - auto micro = duration_cast(steady_clock::now().time_since_epoch()).count(); - s << "[" << std::setfill('0') << std::setw(6) << micro / den << "." - << std::setfill('0') << std::setw(6) << micro % den << "]" << " "; + auto num = duration_cast(steady_clock::now().time_since_epoch()).count(); + s << "[" << std::setfill('0') << std::setw(6) << num / den << "." + << std::setfill('0') << std::setw(6) << num % den << "]" << " "; // write log s.write(buffer.data(), std::min((size_t) ret, buffer.size())); @@ -77,6 +84,32 @@ enableFileLogging(dht::DhtRunner &dht, const std::string &path) { ); } +OPENDHT_PUBLIC void +enableSyslog(dht::DhtRunner &dht, const char* name) { +#ifndef _WIN32 + struct Syslog { + Syslog(const char* n) { + openlog(n, LOG_NDELAY, LOG_USER); + } + ~Syslog() { + closelog(); + } + }; + // syslog is global. Existing instance must be reused. + static std::weak_ptr opened_logfile; + auto logfile = opened_logfile.lock(); + if (not logfile) { + logfile = std::make_shared(name); + opened_logfile = logfile; + } + dht.setLoggers( + [logfile](char const *m, va_list args) { vsyslog(LOG_ERR, m, args); }, + [logfile](char const *m, va_list args) { vsyslog(LOG_WARNING, m, args); }, + [logfile](char const *m, va_list args) { vsyslog(LOG_INFO, m, args); } + ); +#endif +} + void disableLogging(dht::DhtRunner &dht) { dht.setLoggers(dht::NOLOG, dht::NOLOG, dht::NOLOG); diff --git a/tools/dhtnode.cpp b/tools/dhtnode.cpp index 5e989ad9..30ac421b 100644 --- a/tools/dhtnode.cpp +++ b/tools/dhtnode.cpp @@ -370,7 +370,9 @@ main(int argc, char **argv) dht->run(params.port, crt, true, params.network); if (params.log) { - if (not params.logfile.empty()) + if (params.syslog or (params.daemonize and params.logfile.empty())) + log::enableSyslog(*dht, "dhtnode"); + else if (not params.logfile.empty()) log::enableFileLogging(*dht, params.logfile); else log::enableLogging(*dht); diff --git a/tools/tools_common.h b/tools/tools_common.h index 291e6495..10b6f9a9 100644 --- a/tools/tools_common.h +++ b/tools/tools_common.h @@ -111,6 +111,7 @@ struct dht_params { bool help {false}; // print help and exit bool log {false}; std::string logfile {}; + bool syslog {false}; in_port_t port {0}; dht::NetId network {0}; bool generate_identity {false}; @@ -127,6 +128,7 @@ static const constexpr struct option long_options[] = { {"verbose", no_argument , nullptr, 'v'}, {"daemonize", no_argument , nullptr, 'd'}, {"logfile", required_argument, nullptr, 'l'}, + {"syslog", no_argument , nullptr, 'L'}, {nullptr, 0 , nullptr, 0} }; @@ -161,6 +163,10 @@ parseArgs(int argc, char **argv) { case 'l': params.logfile = optarg; break; + case 'L': + params.log = true; + params.syslog = true; + break; case 'v': params.log = true; break;