From: Otto Moerbeek Date: Mon, 23 Jan 2023 13:02:09 +0000 (+0100) Subject: rec_control trace-regex: trace to a file or stdout instead of the general log. X-Git-Tag: dnsdist-1.8.0-rc1~38^2~10 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=42ae54e350453abda37ecab807a089a9218b5ebe;p=thirdparty%2Fpdns.git rec_control trace-regex: trace to a file or stdout instead of the general log. --trace stil traces to log --- diff --git a/pdns/recursordist/pdns_recursor.cc b/pdns/recursordist/pdns_recursor.cc index b9420e7455..6eea0fd444 100644 --- a/pdns/recursordist/pdns_recursor.cc +++ b/pdns/recursordist/pdns_recursor.cc @@ -42,6 +42,7 @@ thread_local std::shared_ptr t_pdl; thread_local std::shared_ptr t_traceRegex; +thread_local int t_tracefd = -1; thread_local ProtobufServersInfo t_protobufServers; thread_local ProtobufServersInfo t_outgoingProtobufServers; @@ -837,6 +838,37 @@ static bool isEnabledForUDRs(const std::shared_ptrwithName("trace")->error(Logr::Error, err, "Could not dup trace file")); + return; + } + auto filep = std::unique_ptr(fdopen(traceFd, "a"), &fclose); + if (!filep) { + int err = errno; + SLOG(g_log << Logger::Error << "Could not write to trace file: " << stringerror(err) << endl, + g_slog->withName("trace")->error(Logr::Error, err, "Could not write to trace file")); + close(traceFd); + return; + } + vector lines; + boost::split(lines, trace, boost::is_any_of("\n")); + int count = 0; + for (const string& line : lines) { + if (!line.empty()) + fprintf(filep.get(), "%04d %s\n", ++count, line.c_str()); + } + fprintf(filep.get(), "\n"); + // fclose by unique_ptr does implicit flush +} + void startDoResolve(void* p) { auto dc = std::unique_ptr(reinterpret_cast(p)); @@ -1281,15 +1313,7 @@ void startDoResolve(void* p) haveAnswer:; if (tracedQuery || res == -1 || res == RCode::ServFail || pw.getHeader()->rcode == RCode::ServFail) { - string trace(sr.getTrace()); - if (!trace.empty()) { - vector lines; - boost::split(lines, trace, boost::is_any_of("\n")); - for (const string& line : lines) { - if (!line.empty()) - g_log << Logger::Warning << line << endl; - } - } + dumpTrace(sr.getTrace()); } if (res == -1) { diff --git a/pdns/recursordist/rec-main.cc b/pdns/recursordist/rec-main.cc index 4e0b2392f1..3acf1bfb62 100644 --- a/pdns/recursordist/rec-main.cc +++ b/pdns/recursordist/rec-main.cc @@ -3091,24 +3091,35 @@ RecursorControlChannel::Answer doQueueReloadLuaScript(vector::const_iter return broadcastAccFunction(doReloadLuaScript); } -static string* pleaseUseNewTraceRegex(const std::string& newRegex) -try { - if (newRegex.empty()) { - t_traceRegex.reset(); - return new string("unset\n"); - } - else { +static string* pleaseUseNewTraceRegex(const std::string& newRegex, int file) +{ + try { + if (newRegex.empty()) { + t_traceRegex.reset(); + close(t_tracefd); + t_tracefd = -1; + return new string("unset\n"); + } + if (file == -1) { + return new string("could not dup file\n"); + } + if (t_tracefd != -1) { + close(t_tracefd); + } t_traceRegex = std::make_shared(newRegex); + t_tracefd = file; return new string("ok\n"); } -} -catch (PDNSException& ae) { - return new string(ae.reason + "\n"); + catch (PDNSException& ae) { + return new string(ae.reason + "\n"); + } } -string doTraceRegex(vector::const_iterator begin, vector::const_iterator end) +string doTraceRegex(FDWrapper file, vector::const_iterator begin, vector::const_iterator end) { - return broadcastAccFunction([=] { return pleaseUseNewTraceRegex(begin != end ? *begin : ""); }); + int fileno = dup(file); + // Potential dup failure handled in pleaseUseNewTraceRegex() + return broadcastAccFunction([=] { return pleaseUseNewTraceRegex(begin != end ? *begin : "", fileno); }); } static uint64_t* pleaseWipePacketCache(const DNSName& canon, bool subtree, uint16_t qtype) diff --git a/pdns/recursordist/rec-main.hh b/pdns/recursordist/rec-main.hh index 9416f4a8d7..58ee029e2e 100644 --- a/pdns/recursordist/rec-main.hh +++ b/pdns/recursordist/rec-main.hh @@ -227,6 +227,7 @@ extern std::shared_ptr g_initialAllowFrom; // new thread needs to extern std::shared_ptr g_initialAllowNotifyFrom; // new threads need this to be setup extern std::shared_ptr g_initialAllowNotifyFor; // new threads need this to be setup extern thread_local std::shared_ptr t_traceRegex; +extern thread_local int t_tracefd; extern string g_programname; extern string g_pidfname; extern RecursorControlChannel g_rcc; // only active in the handler thread @@ -548,6 +549,7 @@ void makeTCPServerSockets(deferredAdd_t& deferredAdds, std::set& tcpSockets void handleNewTCPQuestion(int fd, FDMultiplexer::funcparam_t&); void makeUDPServerSockets(deferredAdd_t& deferredAdds, Logr::log_t); +string doTraceRegex(FDWrapper file, vector::const_iterator begin, vector::const_iterator end); #define LOCAL_NETS "127.0.0.0/8, 10.0.0.0/8, 100.64.0.0/10, 169.254.0.0/16, 192.168.0.0/16, 172.16.0.0/12, ::1/128, fc00::/7, fe80::/10" #define LOCAL_NETS_INVERSE "!127.0.0.0/8, !10.0.0.0/8, !100.64.0.0/10, !169.254.0.0/16, !192.168.0.0/16, !172.16.0.0/12, !::1/128, !fc00::/7, !fe80::/10" diff --git a/pdns/recursordist/rec_channel_rec.cc b/pdns/recursordist/rec_channel_rec.cc index dd8f7f266a..36dcfb1db2 100644 --- a/pdns/recursordist/rec_channel_rec.cc +++ b/pdns/recursordist/rec_channel_rec.cc @@ -2215,7 +2215,7 @@ RecursorControlChannel::Answer RecursorControlParser::getAnswer(int s, const str return {0, doSetCarbonServer(begin, end)}; } if (cmd == "trace-regex") { - return {0, doTraceRegex(begin, end)}; + return {0, doTraceRegex(begin == end ? FDWrapper(-1) : getfd(s), begin, end)}; } if (cmd == "unload-lua-script") { vector empty; diff --git a/pdns/recursordist/rec_control.cc b/pdns/recursordist/rec_control.cc index 2c81aafbad..6e2ae91dc1 100644 --- a/pdns/recursordist/rec_control.cc +++ b/pdns/recursordist/rec_control.cc @@ -98,6 +98,7 @@ int main(int argc, char** argv) "dump-non-resolving", "dump-saved-parent-ns-sets", "dump-dot-probe-map", + "trace-regex", }; try { initArguments(argc, argv); @@ -145,16 +146,22 @@ int main(int argc, char** argv) command += " "; } command += commands[i]; - if (fileCommands.count(commands[i]) > 0) { + + // special case: trace-regex with no arguments is clear regex + auto traceregexClear = command == "trace-regex" && commands.size() == 1; + + if (fileCommands.count(commands[i]) > 0 && !traceregexClear) { if (i + 1 < commands.size()) { // dump-rpz is different, it also has a zonename as argument - if (commands[i] == "dump-rpz") { + // trace-regex is different, it also has a regexp as argument + if (commands[i] == "dump-rpz" || commands[i] == "trace-regex") { if (i + 2 < commands.size()) { ++i; - command += " " + commands[i]; // add rpzname and continue with filename + command += " "; + command += commands[i]; // add rpzname/regex and continue with filename } else { - throw PDNSException("Command needs a zone and file argument"); + throw PDNSException("Command needs two arguments"); } } ++i; diff --git a/pdns/recursordist/syncres.hh b/pdns/recursordist/syncres.hh index 9e7dd3111c..50af5bf25b 100644 --- a/pdns/recursordist/syncres.hh +++ b/pdns/recursordist/syncres.hh @@ -890,7 +890,6 @@ extern thread_local std::unique_ptr t_servfailremotes, t_largeans extern thread_local std::unique_ptr>> t_queryring, t_servfailqueryring, t_bogusqueryring; extern thread_local std::shared_ptr t_allowFrom; extern thread_local std::shared_ptr t_allowNotifyFrom; -string doTraceRegex(vector::const_iterator begin, vector::const_iterator end); extern unsigned int g_networkTimeoutMsec; extern uint16_t g_outgoingEDNSBufsize; extern std::atomic g_maxCacheEntries, g_maxPacketCacheEntries;