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;