ClickHouse/dbms/programs/server/PrometheusMetricsWriter.cpp

102 lines
3.0 KiB
C++

#include "PrometheusMetricsWriter.h"
#include <algorithm>
#include <IO/WriteHelpers.h>
namespace
{
template <typename T>
void writeOutLine(DB::WriteBuffer & wb, T && val)
{
DB::writeText(std::forward<T>(val), wb);
DB::writeChar('\n', wb);
}
template <typename T, typename... TArgs>
void writeOutLine(DB::WriteBuffer & wb, T && val, TArgs &&... args)
{
DB::writeText(std::forward<T>(val), wb);
DB::writeChar(' ', wb);
writeOutLine(wb, std::forward<TArgs>(args)...);
}
void replaceInvalidChars(std::string & metric_name)
{
std::replace(metric_name.begin(), metric_name.end(), '.', '_');
}
}
namespace DB
{
PrometheusMetricsWriter::PrometheusMetricsWriter(
const Poco::Util::AbstractConfiguration & config, const std::string & config_name,
const AsynchronousMetrics & async_metrics_)
: async_metrics(async_metrics_)
, send_events(config.getBool(config_name + ".events", true))
, send_metrics(config.getBool(config_name + ".metrics", true))
, send_asynchronous_metrics(config.getBool(config_name + ".asynchronous_metrics", true))
{
}
void PrometheusMetricsWriter::write(WriteBuffer & wb) const
{
if (send_events)
{
for (size_t i = 0, end = ProfileEvents::end(); i < end; ++i)
{
const auto counter = ProfileEvents::global_counters[i].load(std::memory_order_relaxed);
std::string metric_name{ProfileEvents::getName(static_cast<ProfileEvents::Event>(i))};
std::string metric_doc{ProfileEvents::getDocumentation(static_cast<ProfileEvents::Event>(i))};
replaceInvalidChars(metric_name);
std::string key{profile_events_prefix + metric_name};
writeOutLine(wb, "# HELP", key, metric_doc);
writeOutLine(wb, "# TYPE", key, "counter");
writeOutLine(wb, key, counter);
}
}
if (send_metrics)
{
for (size_t i = 0, end = CurrentMetrics::end(); i < end; ++i)
{
const auto value = CurrentMetrics::values[i].load(std::memory_order_relaxed);
std::string metric_name{CurrentMetrics::getName(static_cast<CurrentMetrics::Metric>(i))};
std::string metric_doc{CurrentMetrics::getDocumentation(static_cast<CurrentMetrics::Metric>(i))};
replaceInvalidChars(metric_name);
std::string key{current_metrics_prefix + metric_name};
writeOutLine(wb, "# HELP", key, metric_doc);
writeOutLine(wb, "# TYPE", key, "gauge");
writeOutLine(wb, key, value);
}
}
if (send_asynchronous_metrics)
{
auto async_metrics_values = async_metrics.getValues();
for (const auto & name_value : async_metrics_values)
{
std::string key{asynchronous_metrics_prefix + name_value.first};
replaceInvalidChars(key);
auto value = name_value.second;
// TODO: add HELP section? asynchronous_metrics contains only key and value
writeOutLine(wb, "# TYPE", key, "gauge");
writeOutLine(wb, key, value);
}
}
}
}