]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
dnsdist: Keep non-structured logging alive after all
authorRemi Gacogne <remi.gacogne@powerdns.com>
Mon, 1 Dec 2025 16:21:02 +0000 (17:21 +0100)
committerRemi Gacogne <remi.gacogne@powerdns.com>
Mon, 19 Jan 2026 09:49:34 +0000 (10:49 +0100)
Signed-off-by: Remi Gacogne <remi.gacogne@powerdns.com>
pdns/dnsdistdist/dnsdist-configuration-yaml.cc
pdns/dnsdistdist/dnsdist-configuration.hh
pdns/dnsdistdist/dnsdist-logging.cc
pdns/dnsdistdist/dnsdist-logging.hh
pdns/dnsdistdist/dnsdist-lua.cc
pdns/dnsdistdist/dnsdist-settings-definitions.yml
pdns/dnsdistdist/dolog.cc
pdns/dolog.hh
pdns/logging.hh
pdns/remote_logger.cc

index 85132c2d8e39e4c07a0947f161458bdefa99ca45..2cc410adc5bcd57320d44a64a9fa4e62aac4cdeb 100644 (file)
@@ -966,26 +966,9 @@ static void handleLoggingConfiguration(const dnsdist::rust::settings::LoggingCon
     }
   }
 
-  if (settings.structured.enabled) {
-    auto levelPrefix = std::string(settings.structured.level_prefix);
-    auto timeFormat = std::string(settings.structured.time_format);
-    if (!timeFormat.empty()) {
-      if (timeFormat == "numeric") {
-        dnsdist::logging::LoggingConfiguration::setStructuredTimeFormat(dnsdist::logging::LoggingConfiguration::TimeFormat::Numeric);
-      }
-      else if (timeFormat == "ISO8601") {
-        dnsdist::logging::LoggingConfiguration::setStructuredTimeFormat(dnsdist::logging::LoggingConfiguration::TimeFormat::ISO8601);
-      }
-      else {
-        warnlog("Unknown value '%s' to logging.structured.time_format parameter", timeFormat);
-      }
-    }
-
-    dnsdist::logging::LoggingConfiguration::setStructuredLogging(true, std::move(levelPrefix));
-  }
-
   dnsdist::configuration::updateImmutableConfiguration([settings](dnsdist::configuration::ImmutableConfiguration& config) {
     config.d_loggingBackend = std::string(settings.structured.backend);
+    config.d_structuredLogging = settings.structured.enabled;
   });
 
 }
index 7e2fa5d11c132a560fc1e35227e69305f2e2fe86..7ae1158251e37e0cbc2366101778fb1b08081d69 100644 (file)
@@ -109,6 +109,7 @@ struct ImmutableConfiguration
   bool d_ringsRecordResponses{true};
   bool d_snmpEnabled{false};
   bool d_snmpTrapsEnabled{false};
+  bool d_structuredLogging{true};
 };
 
 /* this part of the configuration can be updated at runtime via
index e44186667fbbb77bbeaa1581cd478349e2eeff80..db1aa907fd8e3331f025dbdf30a2c0a2f5f9e21f 100644 (file)
@@ -204,4 +204,9 @@ bool doVerboseLogging()
   return dnsdist::configuration::getCurrentRuntimeConfiguration().d_verbose;
 }
 
+bool doStructuredLogging()
+{
+  return dnsdist::configuration::getImmutableConfiguration().d_structuredLogging;
+}
+
 }
index e54ab34a6e536c3158b41fd57b9bd9cb85e96110..29a78b1775bebb5eb6e14ab69a024ab79405ce17 100644 (file)
@@ -30,4 +30,5 @@ namespace dnsdist::logging
 void setup(const std::string& backend);
 std::shared_ptr<const Logr::Logger> getTopLogger();
 bool doVerboseLogging();
+bool doStructuredLogging();
 }
index 345699aacd72df0ab2804c4b43acf429df2b675f..caeb54e16212ed2b1e07a26447328298df1ed516 100644 (file)
@@ -1711,25 +1711,18 @@ static void setupLuaConfig(LuaContext& luaCtx, bool client, bool configCheck)
     }
   });
   luaCtx.writeFunction("setStructuredLogging", [](bool enable, std::optional<LuaAssociativeTable<std::string>> options) {
-    std::string levelPrefix;
-    std::string timeFormat;
+    std::string backend;
     if (options) {
-      getOptionalValue<std::string>(options, "levelPrefix", levelPrefix);
-      if (getOptionalValue<std::string>(options, "timeFormat", timeFormat) == 1) {
-        if (timeFormat == "numeric") {
-          dnsdist::logging::LoggingConfiguration::setStructuredTimeFormat(dnsdist::logging::LoggingConfiguration::TimeFormat::Numeric);
-        }
-        else if (timeFormat == "ISO8601") {
-          dnsdist::logging::LoggingConfiguration::setStructuredTimeFormat(dnsdist::logging::LoggingConfiguration::TimeFormat::ISO8601);
-        }
-        else {
-          warnlog("Unknown value '%s' to setStructuredLogging's 'timeFormat' parameter", timeFormat);
-        }
-      }
+      getOptionalValue<std::string>(options, "backend", backend);
       checkAllParametersConsumed("setStructuredLogging", options);
     }
 
-    dnsdist::logging::LoggingConfiguration::setStructuredLogging(enable, std::move(levelPrefix));
+    dnsdist::configuration::updateImmutableConfiguration([enable, &backend](dnsdist::configuration::ImmutableConfiguration& config) {
+      if (enable && !backend.empty()) {
+        config.d_loggingBackend = backend;
+      }
+      config.d_structuredLogging = enable;
+    });
   });
 
   luaCtx.writeFunction("showBinds", []() {
@@ -3243,12 +3236,17 @@ void loadLuaConfigurationFile(LuaContext& luaCtx, const std::string& config, boo
     if (configCheck) {
       throw std::runtime_error("Unable to read configuration file from " + config);
     }
-    dnsdist::logging::getTopLogger()->withName("lua-configuration")->info(Logr::Error, "Unable to read configuration from file", "configuration-file", Logging::Loggable(config));
+    SLOG(
+      warnlog("Unable to read configuration from '%s'", config),
+      dnsdist::logging::getTopLogger()->withName("lua-configuration")->info(Logr::Error, "Unable to read configuration from file", "configuration-file", Logging::Loggable(config))
+    );
   }
   else {
-    vinfolog("Read configuration from '%s'", config);
     if (dnsdist::logging::doVerboseLogging()) {
-      dnsdist::logging::getTopLogger()->withName("lua-configuration")->info(Logr::Info, "Read configuration from file", "configuration-file", Logging::Loggable(config));
+      SLOG(
+        infolog("Read configuration from '%s'", config),
+        dnsdist::logging::getTopLogger()->withName("lua-configuration")->info(Logr::Info, "Read configuration from file", "configuration-file", Logging::Loggable(config))
+      );
     }
   }
 
index 8af9797297aed7851b75bc9a7fdcd3e7de2f9bb0..ac82b339599f29456b114eef02be69dc1fb3f337 100644 (file)
@@ -1777,21 +1777,19 @@ structured_logging:
   parameters:
     - name: "enabled"
       type: "bool"
-      default: "false"
+      default: "true"
       description: |
-        Set whether log messages should be in a structured-logging-like format. This is turned off by default.
-          The resulting format looks like this (when timestamps are enabled via ``--log-timestamps`` and with ``level_prefix: prio`` and ``time_format: ISO8601``)::
-
-              ts=\"2023-11-06T12:04:58+0100\" prio=\"Info\" msg=\"Added downstream server 127.0.0.1:53\"
-
-          And with ``level_prefix: level`` and ``time_format: numeric``)::
-
-              ts=\"1699268815.133\" level=\"Info\" msg=\"Added downstream server 127.0.0.1:53\"
-
+        Set whether log messages should be in structured-logging format."
+      changes:
+        - version: "2.1.0"
+          content: "This setting is now enabled by default"
     - name: "level_prefix"
       type: "String"
       default: "prio"
       description: "Set the key name for the log level. There is unfortunately no standard name for this key, so in some setups it might be useful to set this value to a different name to have consistency across products"
+      changes:
+        - version: "2.1.0"
+          content: "This setting has been removed"
     - name: "time_format"
       type: "String"
       default: "numeric"
@@ -1799,6 +1797,9 @@ structured_logging:
       supported-values:
         - "ISO8601"
         - "numeric"
+      changes:
+        - version: "2.1.0"
+          content: "This setting has been removed"
     - name: "backend"
       type: "String"
       default: ""
index 74059197db59bc1e0f547911f2a3c35883f662a8..f24be0b3a59e01d8121578ed84ad25a2c96d8285 100644 (file)
 namespace dnsdist::logging
 {
 std::optional<std::ofstream> LoggingConfiguration::s_verboseStream{std::nullopt};
-std::string LoggingConfiguration::s_structuredLevelPrefix{"prio"};
-LoggingConfiguration::TimeFormat LoggingConfiguration::s_structuredTimeFormat{LoggingConfiguration::TimeFormat::Numeric};
-bool LoggingConfiguration::s_structuredLogging{false};
 bool LoggingConfiguration::s_logTimestamps{false};
 bool LoggingConfiguration::s_syslog{true};
 
-namespace
-{
-  const char* getTimeFormat()
-  {
-    if (!dnsdist::logging::LoggingConfiguration::getStructuredLogging()) {
-      return "%b %d %H:%M:%S ";
-    }
-
-    auto format = dnsdist::logging::LoggingConfiguration::getStructuredLoggingTimeFormat();
-    if (format == dnsdist::logging::LoggingConfiguration::TimeFormat::ISO8601) {
-      return "%FT%H:%M:%S%z";
-    }
-    return nullptr;
-  }
-}
-
 void logTime(std::ostream& stream)
 {
   std::array<char, 50> buffer{""};
 
-  if (LoggingConfiguration::getStructuredLogging() && LoggingConfiguration::getStructuredLoggingTimeFormat() == LoggingConfiguration::TimeFormat::Numeric) {
-    struct timeval now{};
-    gettimeofday(&now, nullptr);
-    snprintf(buffer.data(), buffer.size(), "%lld.%03ld", static_cast<long long>(now.tv_sec), static_cast<long>(now.tv_usec / 1000));
-  }
-  else {
-    const auto* timeFormat = getTimeFormat();
-    if (timeFormat == nullptr) {
-      return;
-    }
-
-    time_t now{0};
-    time(&now);
-    struct tm localNow{};
-    localtime_r(&now, &localNow);
+  time_t now{};
+  time(&now);
+  struct tm localNow{};
+  localtime_r(&now, &localNow);
 
-    {
-      // strftime is not thread safe, it can access locale information
-      static std::mutex mutex;
-      auto lock = std::scoped_lock(mutex);
+  {
+    // strftime is not thread safe, it can access locale information
+    static std::mutex mutex;
+    auto lock = std::scoped_lock(mutex);
 
-      if (strftime(buffer.data(), buffer.size(), timeFormat, &localNow) == 0) {
-        buffer[0] = '\0';
-      }
+    if (strftime(buffer.data(), buffer.size(), "%b %d %H:%M:%S ", &localNow) == 0) {
+      buffer[0] = '\0';
     }
   }
 
-  if (dnsdist::logging::LoggingConfiguration::getStructuredLogging()) {
-    stream << "ts=" << std::quoted(buffer.data()) << " ";
-  }
-  else {
-    stream << buffer.data();
-  }
+  stream << buffer.data();
 }
 
 }
index 2552db568439fd92be1be17cc8f512c2234e9ec5..e2e6785636ef68762520aadbd51846824145067f 100644 (file)
@@ -87,31 +87,14 @@ namespace dnsdist::logging
 class LoggingConfiguration
 {
 public:
-  enum class TimeFormat
-  {
-    Numeric,
-    ISO8601
-  };
-
   static void setSyslog(bool value = true)
   {
     s_syslog = value;
   }
-  static void setStructuredLogging(bool value = true, std::string levelPrefix = "")
-  {
-    s_structuredLogging = value;
-    if (value) {
-      s_structuredLevelPrefix = levelPrefix.empty() ? "prio" : std::move(levelPrefix);
-    }
-  }
   static void setLogTimestamps(bool value = true)
   {
     s_logTimestamps = value;
   }
-  static void setStructuredTimeFormat(TimeFormat format)
-  {
-    s_structuredTimeFormat = format;
-  }
   static void setVerboseStream(std::ofstream&& stream)
   {
     s_verboseStream = std::move(stream);
@@ -128,25 +111,9 @@ public:
   {
     return s_verboseStream;
   }
-  static bool getStructuredLogging()
-  {
-    return s_structuredLogging;
-  }
-  static const std::string& getStructuredLoggingLevelPrefix()
-  {
-    return s_structuredLevelPrefix;
-  }
-
-  static TimeFormat getStructuredLoggingTimeFormat()
-  {
-    return s_structuredTimeFormat;
-  }
 
 private:
   static std::optional<std::ofstream> s_verboseStream;
-  static std::string s_structuredLevelPrefix;
-  static TimeFormat s_structuredTimeFormat;
-  static bool s_structuredLogging;
   static bool s_logTimestamps;
   static bool s_syslog;
 };
@@ -197,16 +164,8 @@ void genlog(std::ostream& stream, [[maybe_unused]] int level, [[maybe_unused]] b
     dnsdist::logging::logTime(stream);
   }
 
-  if (dnsdist::logging::LoggingConfiguration::getStructuredLogging()) {
-    stream << dnsdist::logging::LoggingConfiguration::getStructuredLoggingLevelPrefix() << "=\"" << syslogLevelToStr(level) << "\" ";
-    stream << "msg=" << std::quoted(output) << std::endl;
-  }
-  else {
-    stream << output << std::endl;
-  }
-#else
-  stream << output << std::endl;
 #endif
+  stream << output << std::endl;
 }
 
 template <typename... Args>
index c781319e1b3a52df4d63a51cd460ea487a279f62..7c721fa438ea81c03ec4d844dda643e91f8b59fc 100644 (file)
@@ -224,12 +224,20 @@ constexpr bool g_slogStructured = true;
   do {                           \
     slogCall;                    \
   } while (0)
-#else // No structured logging (e.g. auth)
+
+#else // DNSdist
 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
-#define SLOG(oldStyle, slogCall) \
-  do {                           \
-    oldStyle;                    \
-  } while (0)
+#define SLOG(nonStructured, structured)                     \
+  do {                                                      \
+    if (dnsdist::logging::doStructuredLogging()) {          \
+      structured;                                           \
+    }                                                       \
+    else {                                                  \
+      nonStructured;                                        \
+    }                                                       \
+  }                                                         \
+  while (0)
+
 #endif /* ! DNSDIST */
 
 #endif // RECURSOR || DNSDIST
index 3708de46ee8dd198f7d230bef6a2f085419aa40f..979e0c9af1a9ebdc79b8adaf68f7d73c08c36147 100644 (file)
@@ -7,9 +7,12 @@
 #endif
 #ifdef RECURSOR
 #include "logger.hh"
-#else
+#else /* !RECURSOR */
 #include "dolog.hh"
-#endif
+#if defined(DNSDIST)
+#include "dnsdist-logging.hh"
+#endif /* DNSDIST */
+#endif /* !RECURSOR */
 #include "logging.hh"
 
 bool CircularWriteBuffer::hasRoomFor(const std::string& str) const
@@ -135,7 +138,9 @@ bool RemoteLogger::reconnect()
     SLOG(g_log<<Logger::Warning<<"Error connecting to remote logger "<<d_remote.toStringWithPort()<<": "<<e.what()<<std::endl,
          g_slog->withName("protobuf")->error(Logr::Error, e.what(), "Exception while connecting to remote logger", "address", Logging::Loggable(d_remote)));
 #else
-    warnlog("Error connecting to remote logger %s: %s", d_remote.toStringWithPort(), e.what());
+    SLOG(warnlog("Error connecting to remote logger %s: %s", d_remote.toStringWithPort(), e.what()),
+         dnsdist::logging::getTopLogger()->withName("protobuf")->error(e.what(), "Exception while connecting to remote logger", "address", Logging::Loggable(d_remote))
+      );
 #endif
 
     return false;
@@ -244,12 +249,24 @@ void RemoteLogger::maintenanceThread()
   }
   catch (const std::exception& e)
   {
+#ifdef RECURSOR
     SLOG(cerr << "Remote Logger's maintenance thread died on: " << e.what() << endl,
          g_slog->withName("protobuf")->error(Logr::Error, e.what(), "Remote Logger's maintenance thread died"));
+#else
+    SLOG(errlog("Remote Logger's maintenance thread died on: %s", e.what()),
+         dnsdist::logging::getTopLogger()->withName("protobuf")->error(e.what(), "Remote Logger's maintenance thread died")
+      );
+#endif
   }
   catch (...) {
+#ifdef RECURSOR
     SLOG(cerr << "Remote Logger's maintenance thread died on unknown exception" << endl,
          g_slog->withName("protobuf")->info(Logr::Error, "Remote Logger's maintenance thread died"));
+#else
+    SLOG(errlog("Remote Logger's maintenance thread died on: %s"),
+         dnsdist::logging::getTopLogger()->withName("protobuf")->info(Logr::Error, "Remote Logger's maintenance thread died")
+      );
+#endif
   }
 }
 
@@ -259,4 +276,3 @@ RemoteLogger::~RemoteLogger()
 
   d_thread.join();
 }
-