From 456fc64526956e9426e0278aac49e5dcb56b6dc9 Mon Sep 17 00:00:00 2001 From: wessels Date: Wed, 17 Aug 2016 18:34:11 -0400 Subject: [PATCH] Add options to LogAction() so it can append (instead of truncate) and write without buffering. Was so happy to discover LogAction() but disappointed that it truncates the file each time the process starts, and apparently doesn't flush the file upon exiting. With two new optional args, the file can be appended rather than truncated and buffering disabled. The defaults remain as before, which is to say to truncate and to buffer. --- pdns/README-dnsdist.md | 2 +- pdns/dnsdist-console.cc | 2 +- pdns/dnsdist-lua.cc | 4 ++-- pdns/dnsdistconf.lua | 4 ++-- pdns/dnsrulactions.hh | 11 +++++++++-- 5 files changed, 15 insertions(+), 8 deletions(-) diff --git a/pdns/README-dnsdist.md b/pdns/README-dnsdist.md index b593e7d5c..87565a6cc 100644 --- a/pdns/README-dnsdist.md +++ b/pdns/README-dnsdist.md @@ -1257,7 +1257,7 @@ instantiate a server with additional parameters * `DelayAction(milliseconds)`: delay the response by the specified amount of milliseconds (UDP-only) * `DisableValidationAction()`: set the CD bit in the question, let it go through * `DropAction()`: drop these packets - * `LogAction([filename], [binary])`: Log a line for each query, to the specified file if any, to the console (require verbose) otherwise. When logging to a file, the `binary` optional parameter specifies whether we log in binary form (default) or in textual form + * `LogAction([filename], [binary])`: Log a line for each query, to the specified file if any, to the console (require verbose) otherwise. When logging to a file, the `binary` optional parameter specifies whether we log in binary form (default) or in textual form, the `append` optional parameter specifies whether we open the file for appending or truncate each time (default), and the `buffered` optional parameter specifies whether writes to the file are buffered (default) or not. * `NoRecurseAction()`: strip RD bit from the question, let it go through * `PoolAction(poolname)`: set the packet into the specified pool * `QPSPoolAction(maxqps, poolname)`: set the packet into the specified pool only if it **does not** exceed the specified QPS limits, letting the subsequent rules apply otherwise diff --git a/pdns/dnsdist-console.cc b/pdns/dnsdist-console.cc index d3611ff57..619f3790c 100644 --- a/pdns/dnsdist-console.cc +++ b/pdns/dnsdist-console.cc @@ -265,7 +265,7 @@ const std::vector g_consoleKeywords{ { "getServers", true, "", "returns a table with all defined servers" }, { "grepq", true, "Netmask|DNS Name|100ms|{\"::1\", \"powerdns.com\", \"100ms\"} [, n]", "shows the last n queries and responses matching the specified client address or range (Netmask), or the specified DNS Name, or slower than 100ms" }, { "leastOutstanding", false, "", "Send traffic to downstream server with least outstanding queries, with the lowest 'order', and within that the lowest recent latency"}, - { "LogAction", true, "[filename], [binary]", "Log a line for each query, to the specified file if any, to the console (require verbose) otherwise. When logging to a file, the `binary` optional parameter specifies whether we log in binary form (default) or in textual form" }, + { "LogAction", true, "[filename], [binary], [append], [buffered]", "Log a line for each query, to the specified file if any, to the console (require verbose) otherwise. When logging to a file, the `binary` optional parameter specifies whether we log in binary form (default) or in textual form, the `append` optional parameter specifies whether we open the file for appending or truncate each time (default), and the `buffered` optional parameter specifies whether writes to the file are buffered (default) or not." }, { "makeKey", true, "", "generate a new server access key, emit configuration line ready for pasting" }, { "MaxQPSIPRule", true, "qps, v4Mask=32, v6Mask=64", "matches traffic exceeding the qps limit per subnet" }, { "MaxQPSRule", true, "qps", "matches traffic **not** exceeding this qps limit" }, diff --git a/pdns/dnsdist-lua.cc b/pdns/dnsdist-lua.cc index 8e122046c..bd997e197 100644 --- a/pdns/dnsdist-lua.cc +++ b/pdns/dnsdist-lua.cc @@ -756,8 +756,8 @@ vector> setupLua(bool client, const std::string& confi return std::shared_ptr(new DisableValidationAction); }); - g_lua.writeFunction("LogAction", [](const std::string& fname, boost::optional binary) { - return std::shared_ptr(new LogAction(fname, binary ? *binary : true)); + g_lua.writeFunction("LogAction", [](const std::string& fname, boost::optional binary, boost::optional append, boost::optional buffered) { + return std::shared_ptr(new LogAction(fname, binary ? *binary : true, append ? *append : false, buffered ? *buffered : false)); }); g_lua.writeFunction("RCodeAction", [](int rcode) { diff --git a/pdns/dnsdistconf.lua b/pdns/dnsdistconf.lua index 63fa897f6..028f49cac 100644 --- a/pdns/dnsdistconf.lua +++ b/pdns/dnsdistconf.lua @@ -171,8 +171,8 @@ end -- return 'not implemented' for qtype == A OR received over UDP -- addAction(OrRule({QTypeRule("A"), TCPRule(false)}), RCodeAction(dnsdist.NOTIMP)) --- log all queries to a 'dndist.log' file, in text-mode (not binary) --- addAction(AllRule(), LogAction("dnsdist.log", false)) +-- log all queries to a 'dndist.log' file, in text-mode (not binary) appending and unbuffered +-- addAction(AllRule(), LogAction("dnsdist.log", false, true, false)) -- drop all queries with the DO flag set -- addAction(DNSSECRule(), DropAction()) diff --git a/pdns/dnsrulactions.hh b/pdns/dnsrulactions.hh index 9441bce9b..12c0468bb 100644 --- a/pdns/dnsrulactions.hh +++ b/pdns/dnsrulactions.hh @@ -872,13 +872,18 @@ public: LogAction() : d_fp(0) { } - LogAction(const std::string& str, bool binary=true) : d_fname(str), d_binary(binary) + LogAction(const std::string& str, bool binary=true, bool append=false, bool buffered=true) : d_fname(str), d_binary(binary), d_append(append), d_buffered(buffered) { if(str.empty()) return; - d_fp = fopen(str.c_str(), "w"); + if(d_append) + d_fp = fopen(str.c_str(), "a+"); + else + d_fp = fopen(str.c_str(), "w"); if(!d_fp) throw std::runtime_error("Unable to open file '"+str+"' for logging: "+string(strerror(errno))); + if(!d_buffered) + setbuf(d_fp, 0); } ~LogAction() { @@ -913,6 +918,8 @@ private: string d_fname; FILE* d_fp{0}; bool d_binary{true}; + bool d_append{false}; + bool d_buffered{true}; }; -- 2.40.0