1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
|
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "mtasker.hh"
#include "syncres.hh"
#include "rec_channel.hh"
#include "iputils.hh"
#include "logger.hh"
#include "logging.hh"
#include "arguments.hh"
#include "lock.hh"
GlobalStateHolder<CarbonConfig> g_carbonConfig;
void doCarbonDump(void*)
{
auto log = g_slog->withName("carbon");
try {
static thread_local auto configHolder = g_carbonConfig.getLocal();
auto config = *configHolder;
if (config.servers.empty()) {
return;
}
if (config.namespace_name.empty()) {
config.namespace_name = "pdns";
}
if (config.hostname.empty()) {
try {
config.hostname = getCarbonHostName();
}
catch (const std::exception& e) {
throw std::runtime_error(std::string("The 'carbon-ourname' setting has not been set and we are unable to determine the system's hostname: ") + e.what());
}
}
if (config.instance_name.empty()) {
config.instance_name = "recursor";
}
registerAllStats();
PacketBuffer msg;
for (const auto& carbonServer : config.servers) {
ComboAddress remote(carbonServer, 2003);
Socket s(remote.sin4.sin_family, SOCK_STREAM);
s.setNonBlocking();
std::shared_ptr<TLSCtx> tlsCtx{nullptr};
const struct timeval timeout
{
g_networkTimeoutMsec / 1000, static_cast<suseconds_t>(g_networkTimeoutMsec) % 1000 * 1000
};
auto handler = std::make_shared<TCPIOHandler>("", false, s.releaseHandle(), timeout, tlsCtx, time(nullptr));
handler->tryConnect(SyncRes::s_tcp_fast_open_connect, remote); // we do the connect so the first attempt happens while we gather stats
if (msg.empty()) {
auto all = getAllStatsMap(StatComponent::Carbon);
ostringstream str;
time_t now = time(0);
for (const auto& val : all) {
str << config.namespace_name << '.' << config.hostname << '.' << config.instance_name << '.' << val.first << ' ' << val.second.d_value << ' ' << now << "\r\n";
}
const string& x = str.str();
msg.insert(msg.end(), x.cbegin(), x.cend());
}
auto ret = asendtcp(msg, handler); // this will actually do the right thing waiting on the connect
if (ret == LWResult::Result::Timeout) {
SLOG(g_log << Logger::Warning << "Timeout connecting/writing carbon data to " << remote.toStringWithPort() << endl,
log->info(Logr::Warning, "Timeout connecting/writing carbon data", "address", Logging::Loggable(remote)));
}
else if (ret != LWResult::Result::Success) {
int err = errno;
SLOG(g_log << Logger::Warning << "Error writing carbon data to " << remote.toStringWithPort() << ": " << stringerror(err) << endl,
log->error(Logr::Warning, err, "Error writing carbon data", "address", Logging::Loggable(remote)));
}
handler->close();
}
}
catch (const PDNSException& e) {
SLOG(g_log << Logger::Error << "Error in carbon thread: " << e.reason << endl,
log->error(Logr::Error, e.reason, "Error in carbon thread", "exception", Logging::Loggable("PDNSException")));
}
catch (const std::exception& e) {
SLOG(g_log << Logger::Error << "Error in carbon thread: " << e.what() << endl,
log->error(Logr::Error, e.what(), "Error in carbon thread", "exception", Logging::Loggable("std::exception")));
}
catch (...) {
SLOG(g_log << Logger::Error << "Unknown error in carbon thread" << endl,
log->info(Logr::Error, "Error in carbon thread"));
}
}
|