Merge pull request #11972 from ClickHouse/aku/cpu-freq

Add CPU frequencies to system.asynchronous_metrics
This commit is contained in:
Alexander Kuzmenkov 2020-06-26 20:45:58 +03:00 committed by GitHub
commit 58bf6f7adc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 83 additions and 35 deletions

View File

@ -861,7 +861,8 @@ int Server::main(const std::vector<std::string> & /*args*/)
}; };
/// This object will periodically calculate some metrics. /// This object will periodically calculate some metrics.
AsynchronousMetrics async_metrics(*global_context); AsynchronousMetrics async_metrics(*global_context,
config().getUInt("asynchronous_metrics_update_period_s", 60));
attachSystemTablesAsync(*DatabaseCatalog::instance().getSystemDatabase(), async_metrics); attachSystemTablesAsync(*DatabaseCatalog::instance().getSystemDatabase(), async_metrics);
for (const auto & listen_host : listen_hosts) for (const auto & listen_host : listen_hosts)

View File

@ -454,6 +454,9 @@ void readBackQuotedString(String & s, ReadBuffer & buf);
void readBackQuotedStringWithSQLStyle(String & s, ReadBuffer & buf); void readBackQuotedStringWithSQLStyle(String & s, ReadBuffer & buf);
void readStringUntilEOF(String & s, ReadBuffer & buf); void readStringUntilEOF(String & s, ReadBuffer & buf);
// Reads the line until EOL, unescaping backslash escape sequences.
// Buffer pointer is left at EOL, don't forget to advance it.
void readEscapedStringUntilEOL(String & s, ReadBuffer & buf); void readEscapedStringUntilEOL(String & s, ReadBuffer & buf);

View File

@ -58,21 +58,10 @@ AsynchronousMetricValues AsynchronousMetrics::getValues() const
return values; return values;
} }
static auto get_next_update_time(std::chrono::seconds update_period)
void AsynchronousMetrics::run()
{
setThreadName("AsyncMetrics");
const auto get_next_update_time = []
{ {
using namespace std::chrono; using namespace std::chrono;
// The period doesn't really have to be configurable, but sometimes you
// need to change it by recompilation to debug something. The generic
// code is left here so that you don't have to ruin your mood by touching
// std::chrono.
const seconds period(60);
const auto now = time_point_cast<seconds>(system_clock::now()); const auto now = time_point_cast<seconds>(system_clock::now());
// Use seconds since the start of the hour, because we don't know when // Use seconds since the start of the hour, because we don't know when
@ -84,23 +73,30 @@ void AsynchronousMetrics::run()
// we'll collect metrics on start of minute + 30 seconds. This is to // we'll collect metrics on start of minute + 30 seconds. This is to
// achieve temporal separation with MetricTransmitter. Don't forget to // achieve temporal separation with MetricTransmitter. Don't forget to
// rotate it back. // rotate it back.
const auto rotation = period / 2; const auto rotation = update_period / 2;
const auto periods_passed = (seconds_passed + rotation) / period; const auto periods_passed = (seconds_passed + rotation) / update_period;
const auto seconds_next = (periods_passed + 1) * period - rotation; const auto seconds_next = (periods_passed + 1) * update_period - rotation;
const auto time_next = start_of_hour + seconds_next; const auto time_next = start_of_hour + seconds_next;
return time_next; return time_next;
}; }
void AsynchronousMetrics::run()
{
setThreadName("AsyncMetrics");
while (true) while (true)
{ {
{ {
// Wait first, so that the first metric collection is also on even time. // Wait first, so that the first metric collection is also on even time.
std::unique_lock lock{mutex}; std::unique_lock lock{mutex};
if (wait_cond.wait_until(lock, get_next_update_time(), [this] { return quit; })) if (wait_cond.wait_until(lock, get_next_update_time(update_period),
[this] { return quit; }))
{
break; break;
} }
}
try try
{ {
@ -329,6 +325,48 @@ void AsynchronousMetrics::update()
saveAllArenasMetric<size_t>(new_values, "muzzy_purged"); saveAllArenasMetric<size_t>(new_values, "muzzy_purged");
#endif #endif
// Try to add processor frequencies, ignoring errors.
try
{
ReadBufferFromFile buf("/proc/cpuinfo", 32768 /* buf_size */);
// We need the following lines:
// core id : 4
// cpu MHz : 4052.941
// They contain tabs and are interspersed with other info.
int core_id = 0;
while (!buf.eof())
{
std::string s;
// We don't have any backslash escape sequences in /proc/cpuinfo, so
// this function will read the line until EOL, which is exactly what
// we need.
readEscapedStringUntilEOL(s, buf);
// It doesn't read the EOL itself.
++buf.position();
if (s.rfind("core id", 0) == 0)
{
if (auto colon = s.find_first_of(':'))
{
core_id = std::stoi(s.substr(colon + 2));
}
}
else if (s.rfind("cpu MHz", 0) == 0)
{
if (auto colon = s.find_first_of(':'))
{
auto mhz = std::stod(s.substr(colon + 2));
new_values[fmt::format("CPUFrequencyMHz_{}", core_id)] = mhz;
}
}
}
}
catch (...)
{
tryLogCurrentException(__PRETTY_FUNCTION__);
}
/// Add more metrics as you wish. /// Add more metrics as you wish.
// Log the new metrics. // Log the new metrics.

View File

@ -18,15 +18,20 @@ typedef double AsynchronousMetricValue;
typedef std::unordered_map<std::string, AsynchronousMetricValue> AsynchronousMetricValues; typedef std::unordered_map<std::string, AsynchronousMetricValue> AsynchronousMetricValues;
/** Periodically (each minute, starting at 30 seconds offset) /** Periodically (by default, each minute, starting at 30 seconds offset)
* calculates and updates some metrics, * calculates and updates some metrics,
* that are not updated automatically (so, need to be asynchronously calculated). * that are not updated automatically (so, need to be asynchronously calculated).
*/ */
class AsynchronousMetrics class AsynchronousMetrics
{ {
public: public:
AsynchronousMetrics(Context & context_) // The default value of update_period_seconds is for ClickHouse-over-YT
: context(context_), thread([this] { run(); }) // in Arcadia -- it uses its own server implementation that also uses these
// metrics.
AsynchronousMetrics(Context & context_, int update_period_seconds = 60)
: context(context_),
update_period(update_period_seconds),
thread([this] { run(); })
{ {
} }
@ -38,6 +43,7 @@ public:
private: private:
Context & context; Context & context;
const std::chrono::seconds update_period;
mutable std::mutex mutex; mutable std::mutex mutex;
std::condition_variable wait_cond; std::condition_variable wait_cond;