From: Remi Gacogne Date: Fri, 12 Dec 2025 13:42:29 +0000 (+0100) Subject: dnsdist: More structured logging (yaml config, carbon export) X-Git-Tag: rec-5.4.0-beta1~33^2~40 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a1f34c5d889393a1bf618f54a4f0af22efba42bc;p=thirdparty%2Fpdns.git dnsdist: More structured logging (yaml config, carbon export) Signed-off-by: Remi Gacogne --- diff --git a/pdns/dnsdistdist/dnsdist-carbon.cc b/pdns/dnsdistdist/dnsdist-carbon.cc index 43020c585a..72d894b898 100644 --- a/pdns/dnsdistdist/dnsdist-carbon.cc +++ b/pdns/dnsdistdist/dnsdist-carbon.cc @@ -39,7 +39,7 @@ namespace dnsdist { -static bool doOneCarbonExport(const Carbon::Endpoint& endpoint) +static bool doOneCarbonExport(const Carbon::Endpoint& endpoint, const Logr::Logger& logger) { const auto& server = endpoint.server; const std::string& namespace_name = endpoint.namespace_name; @@ -286,14 +286,17 @@ static bool doOneCarbonExport(const Carbon::Endpoint& endpoint) int ret = waitForRWData(carbonSock.getHandle(), false, 1, 0); if (ret <= 0) { - vinfolog("Unable to write data to carbon server on %s: %s", server.toStringWithPort(), (ret < 0 ? stringerror() : "Timeout")); + int savederror = errno; + VERBOSESLOG(infolog("Unable to write data to carbon server on %s: %s", server.toStringWithPort(), (ret < 0 ? stringerror(savederror) : "Timeout")), + logger.info(Logr::Info, "Unable to write data to carbon server", "error", Logging::Loggable(ret < 0 ? stringerror(savederror) : "Timeout"))); return false; } carbonSock.setBlocking(); writen2(carbonSock.getHandle(), msg.c_str(), msg.size()); } catch (const std::exception& e) { - warnlog("Problem sending carbon data to %s: %s", server.toStringWithPort(), e.what()); + SLOG(warnlog("Problem sending carbon data to %s: %s", server.toStringWithPort(), e.what()), + logger.error(Logr::Warning, e.what(), "Problem sending carbon data")); return false; } @@ -303,6 +306,9 @@ static bool doOneCarbonExport(const Carbon::Endpoint& endpoint) static void carbonHandler(const Carbon::Endpoint& endpoint) { setThreadName("dnsdist/carbon"); + const auto ourName = endpoint.getOurName(); + auto logger = dnsdist::logging::getTopLogger()->withName("carbon-exporter")->withValues("address", Logging::Loggable(endpoint.server), "our-name", Logging::Loggable(ourName)); + const auto intervalUSec = endpoint.interval * 1000 * 1000; /* maximum interval between two attempts is 10 minutes */ const ExponentialBackOffTimer backOffTimer(10 * 60); @@ -314,14 +320,15 @@ static void carbonHandler(const Carbon::Endpoint& endpoint) DTime dtimer; dtimer.set(); - if (doOneCarbonExport(endpoint)) { + if (doOneCarbonExport(endpoint, *logger)) { const auto elapsedUSec = dtimer.udiff(); if (elapsedUSec < 0 || static_cast(elapsedUSec) <= intervalUSec) { useconds_t toSleepUSec = intervalUSec - elapsedUSec; usleep(toSleepUSec); } else { - vinfolog("Carbon export for %s took longer (%s us) than the configured interval (%d us)", endpoint.server.toStringWithPort(), elapsedUSec, intervalUSec); + VERBOSESLOG(infolog("Carbon export for %s took longer (%s us) than the configured interval (%d us)", endpoint.server.toStringWithPort(), elapsedUSec, intervalUSec), + logger->info("Carbon export took longer than the configured interval", "elapsed-usec", Logging::Loggable(elapsedUSec), "interval-usec", Logging::Loggable(intervalUSec))); } consecutiveFailures = 0; } @@ -330,16 +337,23 @@ static void carbonHandler(const Carbon::Endpoint& endpoint) if (consecutiveFailures < std::numeric_limits::max()) { consecutiveFailures++; } - vinfolog("Run for %s - %s failed, next attempt in %d", endpoint.server.toStringWithPort(), endpoint.getOurName(), backOff); + VERBOSESLOG(infolog("Run for %s - %s failed, next attempt in %d", endpoint.server.toStringWithPort(), endpoint.getOurName(), backOff), + logger->info("Carbon export failed", "next-attempt-seconds", Logging::Loggable(backOff))); std::this_thread::sleep_for(std::chrono::seconds(backOff)); } } while (true); } + catch (const std::exception& exp) { + SLOG(errlog("Carbon thread for %s died, exception: %s", endpoint.server.toStringWithPort(), exp.what()), + logger->error(Logr::Error, exp.what(), "Carbon thread died")); + } catch (const PDNSException& e) { - errlog("Carbon thread for %s died, PDNSException: %s", endpoint.server.toStringWithPort(), e.reason); + SLOG(errlog("Carbon thread for %s died, PDNSException: %s", endpoint.server.toStringWithPort(), e.reason), + logger->error(Logr::Error, e.reason, "Carbon thread died")); } catch (...) { - errlog("Carbon thread for %s died", endpoint.server.toStringWithPort()); + SLOG(errlog("Carbon thread for %s died", endpoint.server.toStringWithPort()), + logger->info(Logr::Error, "Carbon thread died")); } } diff --git a/pdns/dnsdistdist/dnsdist-concurrent-connections.cc b/pdns/dnsdistdist/dnsdist-concurrent-connections.cc index ddd2350f20..cc8e4b34be 100644 --- a/pdns/dnsdistdist/dnsdist-concurrent-connections.cc +++ b/pdns/dnsdistdist/dnsdist-concurrent-connections.cc @@ -187,16 +187,19 @@ IncomingConcurrentTCPConnectionsManager::NewConnectionResult IncomingConcurrentT auto checkConnectionAllowed = [now, from, maxConnsPerClient, threshold, tcpRate, tlsNewRate, tlsResumedRate, interval, isTLS, &immutable](const ClientEntry& entry) { if (entry.d_bannedUntil != 0 && entry.d_bannedUntil >= now) { - vinfolog("Refusing TCP connection from %s: banned", from.toStringWithPort()); + VERBOSESLOG(infolog("Refusing TCP connection from %s: banned", from.toStringWithPort()), + dnsdist::logging::getTopLogger()->info(Logr::Info, "Refusing TCP connection", "reason", Logging::Loggable("banned"), "address", Logging::Loggable(from))); return NewConnectionResult::Denied; } if (maxConnsPerClient > 0 && entry.d_concurrentConnections >= maxConnsPerClient) { - vinfolog("Refusing TCP connection from %s: too many connections", from.toStringWithPort()); + VERBOSESLOG(infolog("Refusing TCP connection from %s: too many connections", from.toStringWithPort()), + dnsdist::logging::getTopLogger()->info(Logr::Info, "Refusing TCP connection", "reason", Logging::Loggable("too many connections"), "address", Logging::Loggable(from))); return NewConnectionResult::Denied; } if (!checkTCPConnectionsRate(entry.d_activity, now, tcpRate, tlsNewRate, tlsResumedRate, interval, isTLS)) { entry.d_bannedUntil = now + immutable.d_tcpBanDurationForExceedingTCPTLSRate; - vinfolog("Banning TCP connections from %s for %d seconds: too many new TCP/TLS connections per second", from.toStringWithPort(), immutable.d_tcpBanDurationForExceedingTCPTLSRate); + VERBOSESLOG(infolog("Banning TCP connections from %s for %d seconds: too many new TCP/TLS connections per second", from.toStringWithPort(), immutable.d_tcpBanDurationForExceedingTCPTLSRate), + dnsdist::logging::getTopLogger()->info(Logr::Info, "Banning TCP connections from this client", "reason", Logging::Loggable("too many new TCP/TLS connections per second"), "address", Logging::Loggable(from), "duration-seconds", Logging::Loggable(immutable.d_tcpBanDurationForExceedingTCPTLSRate))); return NewConnectionResult::Denied; } @@ -208,7 +211,8 @@ IncomingConcurrentTCPConnectionsManager::NewConnectionResult IncomingConcurrentT if (current < threshold) { return NewConnectionResult::Allowed; } - vinfolog("Restricting TCP connection from %s: nearly reaching the maximum number of concurrent TCP connections", from.toStringWithPort()); + VERBOSESLOG(infolog("Restricting TCP connection from %s: nearly reaching the maximum number of concurrent TCP connections", from.toStringWithPort()), + dnsdist::logging::getTopLogger()->info(Logr::Info, "Restricting TCP connections from this client", "reason", Logging::Loggable("nearly reaching the maximum number of concurrent TCP connections"), "address", Logging::Loggable(from))); return NewConnectionResult::Restricted; }; @@ -273,7 +277,8 @@ void IncomingConcurrentTCPConnectionsManager::banClientFor(const ComboAddress& f entry.d_bannedUntil = now + seconds; }); } - vinfolog("Banned TCP client %s for %d seconds", from.toStringWithPort(), seconds); + VERBOSESLOG(infolog("Banned TCP client %s for %d seconds", from.toStringWithPort(), seconds), + dnsdist::logging::getTopLogger()->info(Logr::Info, "Banned TCP connections from this client", "address", Logging::Loggable(from), "duration-seconds", Logging::Loggable(seconds))); } static void editEntryIfPresent(const ComboAddress& from, const std::function& callback) diff --git a/pdns/dnsdistdist/dnsdist-configuration-yaml.cc b/pdns/dnsdistdist/dnsdist-configuration-yaml.cc index 78294da020..9142b3cb38 100644 --- a/pdns/dnsdistdist/dnsdist-configuration-yaml.cc +++ b/pdns/dnsdistdist/dnsdist-configuration-yaml.cc @@ -61,6 +61,11 @@ namespace dnsdist::configuration::yaml { #if defined(HAVE_YAML_CONFIGURATION) +struct Context +{ + std::shared_ptr logger; +}; + using XSKMap = std::vector>; using RegisteredTypes = std::variant, std::shared_ptr, std::shared_ptr, std::shared_ptr, std::shared_ptr, std::shared_ptr, std::shared_ptr, std::shared_ptr, std::shared_ptr, std::shared_ptr, std::shared_ptr>; @@ -244,7 +249,7 @@ static std::set getCPUPiningFromStr(const std::string& context, const std:: return cpus; } -static TLSConfig getTLSConfigFromRustIncomingTLS(const dnsdist::rust::settings::IncomingTlsConfiguration& incomingTLSConfig) +static TLSConfig getTLSConfigFromRustIncomingTLS([[maybe_unused]] const Context& context, const dnsdist::rust::settings::IncomingTlsConfiguration& incomingTLSConfig) { TLSConfig out; for (const auto& certConfig : incomingTLSConfig.certificates) { @@ -266,7 +271,8 @@ static TLSConfig getTLSConfigFromRustIncomingTLS(const dnsdist::rust::settings:: out.d_minTLSVersion = libssl_tls_version_from_string(std::string(incomingTLSConfig.minimum_version)); #else /* HAVE_LIBSSL */ if (!incomingTLSConfig.minimum_version.empty()) { - warnlog("bind.tls.minimum_version has no effect with the chosen TLS library"); + SLOG(warnlog("bind.tls.minimum_version has no effect with the chosen TLS library"), + context.logger->info(Logr::Warning, "bind.tls.minimum_version has no effect with the chosen TLS library")); } #endif /* HAVE_LIBSSL */ out.d_ticketKeyFile = std::string(incomingTLSConfig.ticket_key_file); @@ -285,7 +291,7 @@ static TLSConfig getTLSConfigFromRustIncomingTLS(const dnsdist::rust::settings:: return out; } -static bool validateTLSConfiguration(const dnsdist::rust::settings::BindConfiguration& bind, [[maybe_unused]] const TLSConfig& tlsConfig) +static bool validateTLSConfiguration(const Context& context, const dnsdist::rust::settings::BindConfiguration& bind, [[maybe_unused]] const TLSConfig& tlsConfig) { if (!bind.tls.ignore_configuration_errors) { return true; @@ -298,7 +304,8 @@ static bool validateTLSConfiguration(const dnsdist::rust::settings::BindConfigur auto ctx = libssl_init_server_context(tlsConfig); } catch (const std::runtime_error& e) { - errlog("Ignoring %s frontend: '%s'", bind.protocol, e.what()); + SLOG(errlog("Ignoring %s frontend: '%s'", bind.protocol, e.what()), + context.logger->error(Logr::Error, e.what(), "Ignoring frontend because of an invalid TLS configuration", "protocol", Logging::Loggable(std::string(bind.protocol)))); return false; } #endif /* HAVE_LIBSSL */ @@ -306,10 +313,10 @@ static bool validateTLSConfiguration(const dnsdist::rust::settings::BindConfigur return true; } -static bool handleTLSConfiguration(const dnsdist::rust::settings::BindConfiguration& bind, ClientState& state, const std::shared_ptr& parent) +static bool handleTLSConfiguration(const Context& context, const dnsdist::rust::settings::BindConfiguration& bind, ClientState& state, const std::shared_ptr& parent) { - auto tlsConfig = getTLSConfigFromRustIncomingTLS(bind.tls); - if (!validateTLSConfiguration(bind, tlsConfig)) { + auto tlsConfig = getTLSConfigFromRustIncomingTLS(context, bind.tls); + if (!validateTLSConfiguration(context, bind, tlsConfig)) { return false; } @@ -361,12 +368,14 @@ static bool handleTLSConfiguration(const dnsdist::rust::settings::BindConfigurat frontend->d_library = std::string(bind.doh.provider); if (frontend->d_library == "nghttp2") { #ifndef HAVE_NGHTTP2 - errlog("DOH bind %s is configured to use nghttp2 but the library is not available", bind.listen_address); + SLOG(errlog("DOH bind %s is configured to use nghttp2 but the library is not available", bind.listen_address), + context.logger->error(Logr::Error, "DoH frontend is configured to use nhgttp2 but the library is not available", "listen-address", Logging::Loggable(bind.listen_address))); return false; #endif /* HAVE_NGHTTP2 */ } else { - errlog("DOH bind %s is configured to use an unknown library ('%s')", bind.listen_address, frontend->d_library); + SLOG(errlog("DOH bind %s is configured to use an unknown library ('%s')", bind.listen_address, frontend->d_library), + context.logger->error(Logr::Error, "DoH frontend is configured to use an unknown library", "listen-address", Logging::Loggable(bind.listen_address), "library", Logging::Loggable(frontend->d_library))); return false; } @@ -404,11 +413,13 @@ static bool handleTLSConfiguration(const dnsdist::rust::settings::BindConfigurat if (!tlsConfig.d_certKeyPairs.empty()) { tlsContext->d_addr = ComboAddress(std::string(bind.listen_address), 443); - infolog("DNS over HTTPS configured"); + SLOG(infolog("DNS over HTTPS configured"), + context.logger->info(Logr::Info, "DNS over HTTPS frontend configured", "listening-address", Logging::Loggable(tlsContext->d_addr))); } else { tlsContext->d_addr = ComboAddress(std::string(bind.listen_address), 80); - infolog("No certificate provided for DoH endpoint %s, running in DNS over HTTP mode instead of DNS over HTTPS", tlsContext->d_addr.toStringWithPort()); + SLOG(infolog("No certificate provided for DoH endpoint %s, running in DNS over HTTP mode instead of DNS over HTTPS", tlsContext->d_addr.toStringWithPort()), + context.logger->info(Logr::Info, "No certificate provided for DoH frontend, running in DNS over HTTP mode instead of DNS over HTTPS", "listening-address", Logging::Loggable(tlsContext->d_addr))); } tlsContext->d_proxyProtocolOutsideTLS = bind.tls.proxy_protocol_outside_tls; @@ -418,14 +429,15 @@ static bool handleTLSConfiguration(const dnsdist::rust::settings::BindConfigurat } #endif /* defined(HAVE_DNS_OVER_HTTPS) */ else if (protocol != "do53") { - errlog("Bind %s is configured to use an unknown protocol ('%s')", bind.listen_address, protocol); + SLOG(errlog("Bind %s is configured to use an unknown protocol ('%s')", bind.listen_address, protocol), + context.logger->info(Logr::Error, "Frontend is configured to use an unknown protocol", "listening-address", Logging::Loggable(bind.listen_address), "protocol", Logging::Loggable(protocol))); return false; } return true; } -static std::shared_ptr createBackendFromConfiguration(const dnsdist::rust::settings::BackendConfiguration& config, bool configCheck) +static std::shared_ptr createBackendFromConfiguration(const Context& context, const dnsdist::rust::settings::BackendConfiguration& config, bool configCheck) { DownstreamState::Config backendConfig; std::shared_ptr tlsCtx; @@ -489,7 +501,8 @@ static std::shared_ptr createBackendFromConfiguration(const dns backendConfig.d_lazyHealthCheckMode = DownstreamState::LazyHealthCheckMode::TimeoutOrServFail; } else if (!hcConf.lazy.mode.empty()) { - warnlog("Ignoring unknown value '%s' for 'lazy.mode' on backend %s", hcConf.lazy.mode, std::string(config.address)); + SLOG(warnlog("Ignoring unknown value '%s' for 'lazy.mode' on backend %s", hcConf.lazy.mode, std::string(config.address)), + context.logger->info(Logr::Warning, "Ignoring unknown value for 'lazy.mode' on backend", "backend-address", Logging::Loggable("config.address"), "value", Logging::Loggable(hcConf.lazy.mode))); } backendConfig.d_upgradeToLazyHealthChecks = config.auto_upgrade.use_lazy_health_check; @@ -527,7 +540,8 @@ static std::shared_ptr createBackendFromConfiguration(const dns backendConfig.d_tlsSubjectIsAddr = true; } catch (const std::exception&) { - errlog("Error creating new server: downstream subject_address value must be a valid IP address"); + SLOG(errlog("Error creating new server: downstream subject_address value must be a valid IP address"), + context.logger->info(Logr::Error, "Error creating new backend server: downstream subject_address value must be a valid IP address", "backend-address", Logging::Loggable(config.address), "value", Logging::Loggable(tlsConf.subject_address))); } } if (backendConfig.d_tlsParams.d_validateCertificates && backendConfig.d_tlsSubjectName.empty()) { @@ -571,7 +585,8 @@ static std::shared_ptr createBackendFromConfiguration(const dns } if (!configCheck) { downstream->registerXsk(*xskMap); - infolog("Added downstream server %s via XSK in %s mode", std::string(config.address), xskMap->at(0)->getXDPMode()); + SLOG(infolog("Added downstream server %s via XSK in %s mode", std::string(config.address), xskMap->at(0)->getXDPMode()), + context.logger->info(Logr::Info, "Added backend server using XSK", "listening-address", Logging::Loggable(config.address), "xsk-mode", Logging::Loggable(xskMap->at(0)->getXDPMode()))); } } #endif /* defined(HAVE_XSK) */ @@ -731,7 +746,7 @@ static void loadDynamicBlockConfiguration(const dnsdist::rust::settings::Dynamic } } -static void handleAdditionalAddressesForFrontend(const std::shared_ptr& state, const std::string& protocol, const ::rust::Vec<::rust::String>& additionalAddresses) +static void handleAdditionalAddressesForFrontend(const Context& context, const std::shared_ptr& state, const std::string& protocol, const ::rust::Vec<::rust::String>& additionalAddresses) { if (protocol == "dot" || protocol == "doh") { for (const auto& addr : additionalAddresses) { @@ -740,7 +755,8 @@ static void handleAdditionalAddressesForFrontend(const std::shared_ptrd_additionalAddresses.emplace_back(address, -1); } catch (const PDNSException& e) { - errlog("Unable to parse additional address %s for %s bind: %s", std::string(addr), protocol, e.reason); + SLOG(errlog("Unable to parse additional address %s for %s bind: %s", std::string(addr), protocol, e.reason), + context.logger->error(Logr::Error, e.reason, "Unable to parse additional address for frontend", "address", Logging::Loggable(addr), "protocol", Logging::Loggable(protocol))); } } } @@ -749,10 +765,10 @@ static void handleAdditionalAddressesForFrontend(const std::shared_ptr& binds) +static void loadBinds(const Context& context, const ::rust::Vec& binds) { for (const auto& bind : binds) { - updateImmutableConfiguration([&bind](ImmutableConfiguration& config) { + updateImmutableConfiguration([&bind,&context](ImmutableConfiguration& config) { auto protocol = boost::to_lower_copy(std::string(bind.protocol)); uint16_t defaultPort = 53; if (protocol == "dot" || protocol == "doq") { @@ -792,7 +808,7 @@ static void loadBinds(const ::rust::Vecd_tcpConcurrentConnectionsLimit = bind.tcp.max_concurrent_connections; } - handleAdditionalAddressesForFrontend(state, protocol, bind.additional_addresses); + handleAdditionalAddressesForFrontend(context, state, protocol, bind.additional_addresses); if (protocol == "dnscrypt") { #if defined(HAVE_DNSCRYPT) @@ -805,7 +821,7 @@ static void loadBinds(const ::rust::VecaddWorkerRoute(state->xskInfo, listeningAddress); state->xskInfoResponder = XskWorker::create(XskWorker::Type::OutgoingOnly, xsk->sharedEmptyFrameOffset); xsk->addWorker(state->xskInfoResponder); - vinfolog("Enabling XSK in %s mode for incoming UDP packets to %s", xsk->getXDPMode(), listeningAddress.toStringWithPort()); + VERBOSESLOG(infolog("Enabling XSK in %s mode for incoming UDP packets to %s", xsk->getXDPMode(), listeningAddress.toStringWithPort()), + context.logger->info(Logr::Info, "Enabling XSK for incoming UDP packet", "listening-address", Logging::Loggable(listeningAddress), "xsk-mode", Logging::Loggable(xsk->getXDPMode()))); } #endif /* defined(HAVE_XSK) */ config.d_frontends.emplace_back(std::move(state)); @@ -838,9 +855,9 @@ static void loadBinds(const ::rust::Vec(std::string(webConfig.password), webConfig.hash_plaintext_credentials); if (!holder->wasHashed() && holder->isHashingAvailable()) { - infolog("Passing a plain-text password via the 'webserver.password' parameter to is not advised, please consider generating a hashed one using 'hashPassword()' instead."); + SLOG(infolog("Passing a plain-text password via the 'webserver.password' parameter is not advised, please consider generating a hashed one using 'hashPassword()' instead."), + context.logger->info(Logr::Info, "Passing a plain-text password via the 'webserver.password' parameter is not advised, please generating a hashed one using 'hashPassword()' instead")); } config.d_webPassword = std::move(holder); } if (!webConfig.api_key.empty()) { auto holder = std::make_shared(std::string(webConfig.api_key), webConfig.hash_plaintext_credentials); if (!holder->wasHashed() && holder->isHashingAvailable()) { - infolog("Passing a plain-text API key via the 'webserver.api_key' parameter to is not advised, please consider generating a hashed one using 'hashPassword()' instead."); + SLOG(infolog("Passing a plain-text API key via the 'webserver.api_key' parameter is not advised, please consider generating a hashed one using 'hashPassword()' instead."), + context.logger->info(Logr::Info, "Passing a plain-text API key via the 'webserver.api_key' parameter is not advised, please generating a hashed one using 'hashPassword()' instead")); } config.d_webAPIKey = std::move(holder); } @@ -918,16 +937,18 @@ static void loadCustomPolicies(const ::rust::Vec(engine.default_string) : std::nullopt); if (!success) { - warnlog("Error while trying to load TLS engine '%s': %s", std::string(engine.name), error); + SLOG(warnlog("Error while trying to load TLS engine '%s': %s", std::string(engine.name), error), + context.logger->error(Logr::Warning, "Error while trying to load TLS engine", "engine", Logging::Loggable(engine.name), "error", Logging::Loggable(error))); } #else - warnlog("Ignoring TLS engine '%s' because OpenSSL engine support is not compiled in", std::string(engine.name)); + SLOG(warnlog("Ignoring TLS engine '%s' because OpenSSL engine support is not compiled in", std::string(engine.name)), + context.logger->info(Logr::Warning, "Ignoring TLS engine because OpenSSL engine support is not compiled in", "engine", Logging::Loggable(engine.name))); #endif /* HAVE_LIBSSL && !HAVE_TLS_PROVIDERS */ } @@ -935,15 +956,17 @@ static void handleOpenSSLSettings(const dnsdist::rust::settings::TlsTuningConfig #if defined(HAVE_LIBSSL) && OPENSSL_VERSION_MAJOR >= 3 && defined(HAVE_TLS_PROVIDERS) auto [success, error] = libssl_load_provider(std::string(provider)); if (!success) { - warnlog("Error while trying to load TLS provider '%s': %s", std::string(provider), error); + SLOG(warnlog("Error while trying to load TLS provider '%s': %s", std::string(provider), error), + context.logger->error(Logr::Warning, error, "Error while trying to load TLS provider", "provider", Logging::Loggable(provider))); } #else - warnlog("Ignoring TLS provider '%s' because OpenSSL provider support is not compiled in", std::string(provider)); + SLOG(warnlog("Ignoring TLS provider '%s' because OpenSSL provider support is not compiled in", std::string(provider)), + context.logger->info(Logr::Warning, "Ignoring TLS provider because OpenSSL provider support is not compiled in", "provider", Logging::Loggable(provider))); #endif /* HAVE_LIBSSL && OPENSSL_VERSION_MAJOR >= 3 && HAVE_TLS_PROVIDERS */ } } -static void handleLoggingConfiguration(const dnsdist::rust::settings::LoggingConfiguration& settings) +static void handleLoggingConfiguration(const Context& context, const dnsdist::rust::settings::LoggingConfiguration& settings) { if (!settings.verbose_log_destination.empty()) { auto dest = std::string(settings.verbose_log_destination); @@ -952,14 +975,16 @@ static void handleLoggingConfiguration(const dnsdist::rust::settings::LoggingCon dnsdist::logging::LoggingConfiguration::setVerboseStream(std::move(stream)); } catch (const std::exception& e) { - errlog("Error while opening the verbose logging destination file %s: %s", dest, e.what()); + SLOG(errlog("Error while opening the verbose logging destination file %s: %s", dest, e.what()), + context.logger->error(Logr::Error, e.what(), "Error while opening the verbose logging destination file", "filename", Logging::Loggable(dest))); } } if (!settings.syslog_facility.empty()) { auto facilityLevel = logFacilityFromString(std::string(settings.syslog_facility)); if (!facilityLevel) { - warnlog("Unknown facility '%s' passed to logging.syslog_facility", std::string(settings.syslog_facility)); + SLOG(warnlog("Unknown facility '%s' passed to logging.syslog_facility", std::string(settings.syslog_facility)), + context.logger->info(Logr::Warning, "Unknown facility passed to logging.syslog_facility", "facility", Logging::Loggable(settings.syslog_facility))); } else { setSyslogFacility(*facilityLevel); @@ -1090,10 +1115,16 @@ bool loadConfigurationFromFile(const std::string& fileName, [[maybe_unused]] boo // Rust code would be quite cumbersome so for now let's settle for this s_inConfigCheckMode.store(configCheck); s_inClientMode.store(isClient); + auto logger = dnsdist::logging::getTopLogger()->withName("yaml-configuration")->withValues("configuration-file", Logging::Loggable(fileName), "client-mode", Logging::Loggable(isClient), "configuration-check", Logging::Loggable(configCheck)); + Context context{ + .logger = logger, + }; auto data = loadContentFromConfigurationFile(fileName); if (!data) { - errlog("Unable to open YAML file %s: %s", fileName, stringerror(errno)); + int savederror = errno; + SLOG(errlog("Unable to open YAML file %s: %s", fileName, stringerror(savederror)), + logger->error(Logr::Error, savederror, "Unable to open YAML file")); return false; } @@ -1113,7 +1144,7 @@ bool loadConfigurationFromFile(const std::string& fileName, [[maybe_unused]] boo convertRuntimeFlatSettingsFromRust(globalConfig, config); }); - handleLoggingConfiguration(globalConfig.logging); + handleLoggingConfiguration(context, globalConfig.logging); handleConsoleConfiguration(globalConfig.console); @@ -1130,7 +1161,7 @@ bool loadConfigurationFromFile(const std::string& fileName, [[maybe_unused]] boo }); } - handleOpenSSLSettings(globalConfig.tuning.tls); + handleOpenSSLSettings(context, globalConfig.tuning.tls); handleEBPFConfiguration(globalConfig.ebpf, configCheck); @@ -1146,10 +1177,10 @@ bool loadConfigurationFromFile(const std::string& fileName, [[maybe_unused]] boo } #endif /* defined(HAVE_XSK) */ - loadBinds(globalConfig.binds); + loadBinds(context, globalConfig.binds); for (const auto& backend : globalConfig.backends) { - auto downstream = createBackendFromConfiguration(backend, configCheck); + auto downstream = createBackendFromConfiguration(context, backend, configCheck); if (!downstream->d_config.pools.empty()) { for (const auto& poolName : downstream->d_config.pools) { @@ -1176,7 +1207,7 @@ bool loadConfigurationFromFile(const std::string& fileName, [[maybe_unused]] boo if (!globalConfig.webserver.listen_addresses.empty()) { const auto& webConfig = globalConfig.webserver; - loadWebServer(webConfig); + loadWebServer(context, webConfig); } if (globalConfig.query_count.enabled) { @@ -1228,10 +1259,11 @@ bool loadConfigurationFromFile(const std::string& fileName, [[maybe_unused]] boo } for (const auto& pool : globalConfig.pools) { - dnsdist::configuration::updateRuntimeConfiguration([&pool](dnsdist::configuration::RuntimeConfiguration& config) { + dnsdist::configuration::updateRuntimeConfiguration([&context, &pool](dnsdist::configuration::RuntimeConfiguration& config) { auto [poolIt, inserted] = config.d_pools.emplace(std::string(pool.name), ServerPool()); if (inserted) { - vinfolog("Creating pool %s", pool.name); + VERBOSESLOG(infolog("Creating pool %s", pool.name), + context.logger->info(Logr::Info, "Creating pool", "pool-name", Logging::Loggable(pool.name))); } if (!pool.packet_cache.empty()) { @@ -1257,13 +1289,16 @@ bool loadConfigurationFromFile(const std::string& fileName, [[maybe_unused]] boo return true; } catch (const ::rust::Error& exp) { - errlog("Error while parsing YAML file %s: %s", fileName, exp.what()); + SLOG(errlog("Error while parsing YAML file %s: %s", fileName, exp.what()), + logger->error(Logr::Error, exp.what(), "Error while parsing YAML file", "configuration-file", Logging::Loggable(fileName))); } catch (const PDNSException& exp) { - errlog("Error while processing YAML configuration from file %s: %s", fileName, exp.reason); + SLOG(errlog("Error while processing YAML configuration from file %s: %s", fileName, exp.reason), + logger->error(Logr::Error, exp.reason, "Error while processing YAML file", "configuration-file", Logging::Loggable(fileName))); } catch (const std::exception& exp) { - errlog("Error while processing YAML configuration from file %s: %s", fileName, exp.what()); + SLOG(errlog("Error while processing YAML configuration from file %s: %s", fileName, exp.what()), + logger->error(Logr::Error, exp.what(), "Error while processing YAML file", "configuration-file", Logging::Loggable(fileName))); } return false; #else