Using arguments.cc as a test-case.
json.cc json.hh \
lock.hh \
logger.cc logger.hh \
+ logging.hh \
lua-auth4.cc lua-auth4.hh \
lua-base4.cc lua-base4.hh \
mastercommunicator.cc \
{ "snmp-master-socket", "snmp-daemon-socket" }
};
-static void warnIfDeprecated(const string& var)
+void ArgvMap::warnIfDeprecated(const string& var)
{
const auto msg = deprecateList.find(var);
if (msg != deprecateList.end()) {
- g_log << Logger::Warning << "'" << var << "' is deprecated and will be removed in a future release, use '" << msg->second << "' instead" << endl;
+ SLOG(g_log << Logger::Warning << "'" << var << "' is deprecated and will be removed in a future release, use '" << msg->second << "' instead" << endl,
+ d_log->info(Logr::Warning, "Option is deprecated and will be removed in a future release", "deprecatedName", Logging::Loggable(var), "name", Logging::Loggable(msg->second)));
}
}
boost::trim(var);
if(var!="" && (parseOnly.empty() || var==parseOnly)) {
- warnIfDeprecated(var);
+ if (!lax) {
+ warnIfDeprecated(var);
+ }
pos=val.find_first_not_of(" \t"); // strip leading whitespace
if(pos && pos!=string::npos)
val=val.substr(pos);
stringtok(parts, d_params["ignore-unknown-settings"], " ,\t\n\r");
if (find(parts.begin(), parts.end(), var) != parts.end()) {
d_unknownParams[var] = val;
- g_log<<Logger::Warning<<"Ignoring unknown setting '"<<var<<"' as requested"<<endl;
+ SLOG(g_log<<Logger::Warning<<"Ignoring unknown setting '"<<var<<"' as requested"<<endl,
+ d_log->info(Logr::Warning, "Ignoring unknown setting as requested", "name", Logging::Loggable(var)));
return;
}
set("include-dir","Directory to include configuration files from");
if(!parseFile(fname, "", lax)) {
- g_log << Logger::Warning << "Unable to open " << fname << std::endl;
+ SLOG(g_log << Logger::Warning << "Unable to open " << fname << std::endl,
+ d_log->error(Logr::Warning, "Unable to open", "name", Logging::Loggable(fname)));
return false;
}
gatherIncludes(extraConfigs);
for(const std::string& fn : extraConfigs) {
if (!file(fn.c_str(), lax, true)) {
- g_log << Logger::Error << fn << " could not be parsed" << std::endl;
+ SLOG(g_log << Logger::Error << fn << " could not be parsed" << std::endl,
+ d_log->info(Logr::Error, "Could not be parsed", "name", Logging::Loggable(fn)));
throw ArgException(fn + " could not be parsed");
}
}
if (!(dir = opendir(d_params["include-dir"].c_str()))) {
int err = errno;
string msg = d_params["include-dir"] + " is not accessible: " + strerror(err);
- g_log << Logger::Error << msg << std::endl;
+ SLOG(g_log << Logger::Error << msg << std::endl,
+ d_log->error(Logr::Error, err, "Directory is not accessible", "name", Logging::Loggable(d_params["include-dir"])));
throw ArgException(msg);
}
struct stat st;
if (stat(name.c_str(), &st) || !S_ISREG(st.st_mode)) {
string msg = name + " is not a regular file";
- g_log << Logger::Error << msg << std::endl;
+ SLOG(g_log << Logger::Error << msg << std::endl,
+ d_log->info(Logr::Error, "Is not a regular file", "name", Logging::Loggable(name)));
closedir(dir);
throw ArgException(msg);
}
#include <grp.h>
#include "namespaces.hh"
+#include "logging.hh"
typedef PDNSException ArgException;
{
public:
ArgvMap();
+#ifdef RECURSOR
+ std::shared_ptr<Logr::Logger> d_log;
+#endif
void parse(int &argc, char **argv, bool lax=false); //!< use this to parse from argc and argv
void laxParse(int &argc, char **argv) //!< use this to parse from argc and argv
{
const vector<string>&getCommands();
void gatherIncludes(std::vector<std::string> &extraConfigs);
private:
+ void warnIfDeprecated(const string& var);
void parseOne(const string &unparsed, const string &parseOnly="", bool lax=false);
const string formatOne(bool running, bool full, const string &var, const string &help, const string& theDefault, const string& value);
map<string,string> d_params;
--- /dev/null
+/*
+ * This file is part of PowerDNS or dnsdist.
+ * Copyright -- PowerDNS.COM B.V. and its contributors
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * In addition, for the avoidance of any doubt, permission is granted to
+ * link this program with OpenSSL and to (re)distribute the binaries
+ * produced as the result of such linking.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#pragma once
+
+#include "config.h"
+
+#ifdef RECURSOR
+
+#include <map>
+#include <memory>
+#include <string>
+#include <sstream>
+#include <boost/optional.hpp>
+
+#include "logr.hh"
+#include "dnsname.hh"
+#include "iputils.hh"
+
+namespace Logging
+{
+
+struct Entry
+{
+ boost::optional<std::string> name; // name parts joined with '.'
+ std::string message; // message as send to log call
+ boost::optional<std::string> error; // error if .Error() was called
+ struct timeval d_timestamp; // time of entry generation
+ std::map<std::string, std::string> values; // key-value pairs
+ size_t level; // level at which this was logged
+ Logr::Priority d_priority; // (syslog) priority)
+};
+
+template <typename T>
+struct Loggable : public Logr::Loggable
+{
+ const T& _t;
+ Loggable(const T& v) :
+ _t(v)
+ {
+ }
+ std::string to_string() const
+ {
+ std::ostringstream oss;
+ oss << _t;
+ return oss.str();
+ }
+};
+template <>
+std::string Loggable<DNSName>::to_string() const;
+template <>
+std::string Loggable<ComboAddress>::to_string() const;
+template <>
+std::string Loggable<std::string>::to_string() const;
+
+// Loggable<std::string>::Loggable(const std::string& v): _t(v) {}
+
+typedef void (*EntryLogger)(const Entry&);
+
+class Logger : public Logr::Logger, public std::enable_shared_from_this<const Logger>
+{
+public:
+ bool enabled(Logr::Priority) const override;
+
+ void info(const std::string& msg) const override;
+ void info(Logr::Priority, const std::string& msg) const override;
+ void error(int err, const std::string& msg) const override;
+ void error(const std::string& err, const std::string& msg) const override;
+ void error(Logr::Priority, int err, const std::string& msg) const override;
+ void error(Logr::Priority, const std::string& err, const std::string& msg) const override;
+
+ std::shared_ptr<Logr::Logger> v(size_t level) const override;
+ std::shared_ptr<Logr::Logger> withValues(const std::map<std::string, std::string>& values) const override;
+ virtual std::shared_ptr<Logr::Logger> withName(const std::string& name) const override;
+
+ static std::shared_ptr<Logger> create(EntryLogger callback);
+ static std::shared_ptr<Logger> create(EntryLogger callback, const std::string& name);
+
+ Logger(EntryLogger callback);
+ Logger(EntryLogger callback, boost::optional<std::string> name);
+ Logger(std::shared_ptr<const Logger> parent, boost::optional<std::string> name, size_t verbosity, size_t lvl, EntryLogger callback);
+ virtual ~Logger();
+
+ size_t getVerbosity() const;
+ void setVerbosity(size_t verbosity);
+
+private:
+ void logMessage(const std::string& msg, boost::optional<const std::string> err) const;
+ void logMessage(const std::string& msg, Logr::Priority p, boost::optional<const std::string> err) const;
+ std::shared_ptr<const Logger> getptr() const;
+
+ std::shared_ptr<const Logger> _parent{nullptr};
+ EntryLogger _callback;
+ boost::optional<std::string> _name;
+ std::map<std::string, std::string> _values;
+ // current Logger's level. the higher the more verbose.
+ size_t _level{0};
+ // verbosity settings. messages with level higher's than verbosity won't appear
+ size_t _verbosity{0};
+};
+}
+
+extern std::shared_ptr<Logging::Logger> g_slog;
+
+// Prefer structured logging?
+extern bool g_slogStructured;
+
+// A helper macro to switch between old-style logging and new-style (structured logging)
+// A typical use:
+//
+// SLOG(g_log<<Logger::Warning<<"Unable to parse configuration file '"<<configname<<"'"<<endl,
+// startupLog->error("No such file", "Unable to parse configuration file", "config_file", Logging::Loggable(configname));
+//
+#define SLOG(oldStyle, slogCall) \
+ do { \
+ if (g_slogStructured) { \
+ slogCall; \
+ } \
+ else { \
+ oldStyle; \
+ } \
+ } while (0);
+
+#else // No structured logging (e.g. auth)
+#define SLOG(oldStyle, slogCall) \
+ do { \
+ oldStyle; \
+ } while (0);
+#endif
}
}
+
int main(int argc, char** argv)
{
+ g_slogStructured = false;
const set<string> fileCommands = {
"dump-cache",
"dump-edns",
dnslabeltext.cc \
dnsname.hh dnsname.cc \
logger.cc \
+ logging.cc \
misc.cc \
qtype.cc \
rec_channel.cc rec_channel.hh \
+++ /dev/null
-/*
- * This file is part of PowerDNS or dnsdist.
- * Copyright -- PowerDNS.COM B.V. and its contributors
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * In addition, for the avoidance of any doubt, permission is granted to
- * link this program with OpenSSL and to (re)distribute the binaries
- * produced as the result of such linking.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#pragma once
-
-#include <map>
-#include <memory>
-#include <string>
-#include <sstream>
-#include <boost/optional.hpp>
-
-#include "logr.hh"
-#include "dnsname.hh"
-#include "iputils.hh"
-
-namespace Logging
-{
-
-struct Entry
-{
- boost::optional<std::string> name; // name parts joined with '.'
- std::string message; // message as send to log call
- boost::optional<std::string> error; // error if .Error() was called
- struct timeval d_timestamp; // time of entry generation
- std::map<std::string, std::string> values; // key-value pairs
- size_t level; // level at which this was logged
- Logr::Priority d_priority; // (syslog) priority)
-};
-
-template <typename T>
-struct Loggable : public Logr::Loggable
-{
- const T& _t;
- Loggable(const T& v) :
- _t(v)
- {
- }
- std::string to_string() const
- {
- std::ostringstream oss;
- oss << _t;
- return oss.str();
- }
-};
-template <>
-std::string Loggable<DNSName>::to_string() const;
-template <>
-std::string Loggable<ComboAddress>::to_string() const;
-template <>
-std::string Loggable<std::string>::to_string() const;
-
-// Loggable<std::string>::Loggable(const std::string& v): _t(v) {}
-
-typedef void (*EntryLogger)(const Entry&);
-
-class Logger : public Logr::Logger, public std::enable_shared_from_this<const Logger>
-{
-public:
- bool enabled(Logr::Priority) const override;
-
- void info(const std::string& msg) const override;
- void info(Logr::Priority, const std::string& msg) const override;
- void error(int err, const std::string& msg) const override;
- void error(const std::string& err, const std::string& msg) const override;
- void error(Logr::Priority, int err, const std::string& msg) const override;
- void error(Logr::Priority, const std::string& err, const std::string& msg) const override;
-
- std::shared_ptr<Logr::Logger> v(size_t level) const override;
- std::shared_ptr<Logr::Logger> withValues(const std::map<std::string, std::string>& values) const override;
- virtual std::shared_ptr<Logr::Logger> withName(const std::string& name) const override;
-
- static std::shared_ptr<Logger> create(EntryLogger callback);
- static std::shared_ptr<Logger> create(EntryLogger callback, const std::string& name);
-
- Logger(EntryLogger callback);
- Logger(EntryLogger callback, boost::optional<std::string> name);
- Logger(std::shared_ptr<const Logger> parent, boost::optional<std::string> name, size_t verbosity, size_t lvl, EntryLogger callback);
- virtual ~Logger();
-
- size_t getVerbosity() const;
- void setVerbosity(size_t verbosity);
-
-private:
- void logMessage(const std::string& msg, boost::optional<const std::string> err) const;
- void logMessage(const std::string& msg, Logr::Priority p, boost::optional<const std::string> err) const;
- std::shared_ptr<const Logger> getptr() const;
-
- std::shared_ptr<const Logger> _parent{nullptr};
- EntryLogger _callback;
- boost::optional<std::string> _name;
- std::map<std::string, std::string> _values;
- // current Logger's level. the higher the more verbose.
- size_t _level{0};
- // verbosity settings. messages with level higher's than verbosity won't appear
- size_t _verbosity{0};
-};
-}
-
-extern std::shared_ptr<Logging::Logger> g_slog;
-
-// Prefer structured logging?
-extern bool g_slogStructured;
-
-// A helper macro to switch between old-style logging and new-style (structured logging)
-// A typical use:
-//
-// SLOG(g_log<<Logger::Warning<<"Unable to parse configuration file '"<<configname<<"'"<<endl,
-// startupLog->error("No such file", "Unable to parse configuration file", "config_file", Logging::Loggable(configname));
-//
-#define SLOG(oldStyle, slogCall) \
- do { \
- if (g_slogStructured) { \
- slogCall; \
- } \
- else { \
- oldStyle; \
- } \
- } while (0);
--- /dev/null
+../logging.hh
\ No newline at end of file
#include <string>
#include <memory>
+#include <map>
// Minimal logging API based on https://github.com/go-logr/logr
buf << " ";
buf << v.first << "=" << std::quoted(v.second);
}
+ cerr << entry.d_priority << endl;
Logger::Urgency u = entry.d_priority ? Logger::Urgency(entry.d_priority) : Logger::Info;
g_log << u << buf.str() << endl;
}
static int serviceMain(int argc, char* argv[])
{
- g_slogStructured = ::arg().mustDo("structured-logging");
-
g_log.setName(g_programname);
g_log.disableSyslog(::arg().mustDo("disable-syslog"));
g_log.setTimestamps(::arg().mustDo("log-timestamp"));
showBuildConfiguration();
exit(0);
}
+ if (::arg().mustDo("help")) {
+ cout << "syntax:" << endl
+ << endl;
+ cout << ::arg().helpstring(::arg()["help"]) << endl;
+ exit(0);
+ }
+
+ // Pick up options given on command line to setup logging asap.
+ g_quiet = ::arg().mustDo("quiet");
+ Logger::Urgency logUrgency = (Logger::Urgency)::arg().asNum("loglevel");
+ g_slogStructured = ::arg().mustDo("structured-logging");
+
+ if (logUrgency < Logger::Error)
+ logUrgency = Logger::Error;
+ if (!g_quiet && logUrgency < Logger::Info) { // Logger::Info=6, Logger::Debug=7
+ logUrgency = Logger::Info; // if you do --quiet=no, you need Info to also see the query log
+ }
+ g_log.setLoglevel(logUrgency);
+ g_log.toConsole(logUrgency);
string configname = ::arg()["config-dir"] + "/recursor.conf";
if (::arg()["config-name"] != "") {
}
g_slog = Logging::Logger::create(loggerBackend);
+ // Missing: a mechanism to call setVerbosity(x)
auto startupLog = g_slog->withName("startup");
+ ::arg().d_log = startupLog;
if (!::arg().file(configname.c_str())) {
SLOG(g_log << Logger::Warning << "Unable to parse configuration file '" << configname << "'" << endl,
startupLog->error("No such file", "Unable to parse configuration file", "config_file", Logging::Loggable(configname)));
}
+ // Reparse, now with config file as well
::arg().parse(argc, argv);
+ g_quiet = ::arg().mustDo("quiet");
+ logUrgency = (Logger::Urgency)::arg().asNum("loglevel");
+ g_slogStructured = ::arg().mustDo("structured-logging");
+
+
+ if (logUrgency < Logger::Error)
+ logUrgency = Logger::Error;
+ if (!g_quiet && logUrgency < Logger::Info) { // Logger::Info=6, Logger::Debug=7
+ logUrgency = Logger::Info; // if you do --quiet=no, you need Info to also see the query log
+ }
+ g_log.setLoglevel(logUrgency);
+ g_log.toConsole(logUrgency);
+
if (!::arg()["chroot"].empty() && !::arg()["api-config-dir"].empty()) {
SLOG(g_log << Logger::Error << "Using chroot and enabling the API is not possible" << endl,
startupLog->info("Cannot use chroot and enable the API at the same time"));
::arg().set("distributor-threads") = "0";
}
- if (::arg().mustDo("help")) {
- cout << "syntax:" << endl
- << endl;
- cout << ::arg().helpstring(::arg()["help"]) << endl;
- exit(0);
- }
g_recCache = std::make_unique<MemRecursorCache>(::arg().asNum("record-cache-shards"));
g_negCache = std::make_unique<NegCache>(::arg().asNum("record-cache-shards"));
- g_quiet = ::arg().mustDo("quiet");
- Logger::Urgency logUrgency = (Logger::Urgency)::arg().asNum("loglevel");
-
- if (logUrgency < Logger::Error)
- logUrgency = Logger::Error;
- if (!g_quiet && logUrgency < Logger::Info) { // Logger::Info=6, Logger::Debug=7
- logUrgency = Logger::Info; // if you do --quiet=no, you need Info to also see the query log
- }
- g_log.setLoglevel(logUrgency);
- g_log.toConsole(logUrgency);
-
ret = serviceMain(argc, argv);
}
catch (PDNSException& ae) {