add dictionary status on prometheus server

This commit is contained in:
Guillaume Tassery 2020-03-11 16:30:02 +01:00
parent 64e77f3b99
commit 36d4f40d58
5 changed files with 145 additions and 1 deletions

View File

@ -3,6 +3,7 @@
#include <algorithm>
#include <IO/WriteHelpers.h>
#include <Common/CurrentStatusInfo.h>
namespace
{
@ -40,6 +41,7 @@ PrometheusMetricsWriter::PrometheusMetricsWriter(
, 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))
, send_status_info(config.getBool(config_name + ".status_info", true))
{
}
@ -86,7 +88,7 @@ void PrometheusMetricsWriter::write(WriteBuffer & wb) const
auto async_metrics_values = async_metrics.getValues();
for (const auto & name_value : async_metrics_values)
{
std::string key{asynchronous_metrics_prefix + name_value.first};
std::string key{current_status_prefix + name_value.first};
replaceInvalidChars(key);
auto value = name_value.second;
@ -96,6 +98,38 @@ void PrometheusMetricsWriter::write(WriteBuffer & wb) const
writeOutLine(wb, key, value);
}
}
if (send_status_info)
{
for (size_t i = 0, end = CurrentStatusInfo::end(); i < end; ++i)
{
std::string metric_name{CurrentStatusInfo::getName(static_cast<CurrentStatusInfo::Metric>(i))};
std::string metric_doc{CurrentStatusInfo::getDocumentation(static_cast<CurrentStatusInfo::Metric>(i))};
replaceInvalidChars(metric_name);
std::string key{current_status_prefix + metric_name};
writeOutLine(wb, "# HELP", key, metric_doc);
writeOutLine(wb, "# TYPE", key, "gauge");
for (const auto & value: CurrentStatusInfo::values[i])
{
for (const auto & enum_value: CurrentStatusInfo::getAllPossibleValues(static_cast<CurrentStatusInfo::Metric>(i)))
{
DB::writeText(key, wb);
DB::writeChar('{', wb);
DB::writeText(key, wb);
DB::writeText("=\"", wb);
DB::writeText(enum_value.first, wb);
DB::writeText("\",name=\"", wb);
DB::writeText(value.first, wb);
DB::writeText("\"} ", wb);
DB::writeText(value.second == enum_value.first, wb);
DB::writeChar('\n', wb);
}
}
}
}
}
}

View File

@ -27,10 +27,12 @@ private:
const bool send_events;
const bool send_metrics;
const bool send_asynchronous_metrics;
const bool send_status_info;
static inline constexpr auto profile_events_prefix = "ClickHouseProfileEvents_";
static inline constexpr auto current_metrics_prefix = "ClickHouseMetrics_";
static inline constexpr auto asynchronous_metrics_prefix = "ClickHouseAsyncMetrics_";
static inline constexpr auto current_status_prefix = "ClickHouseStatusInfo_";
};
}

View File

@ -0,0 +1,58 @@
#include <Common/CurrentStatusInfo.h>
#include <Interpreters/ExternalLoader.h>
/// Available status. Add something here as you wish.
#define APPLY_FOR_STATUS(M) \
M(DictionaryStatus, "Dictionary Status.", DB::ExternalLoader::getStatusEnumAllPossibleValues()) \
namespace CurrentStatusInfo
{
#define M(NAME, DOCUMENTATION, ENUM) extern const Metric NAME = __COUNTER__;
APPLY_FOR_STATUS(M)
#undef M
constexpr Metric END = __COUNTER__;
std::mutex locks[END] {};
std::unordered_map<String, String> values[END] {};
const char * getName(Metric event)
{
static const char * strings[] =
{
#define M(NAME, DOCUMENTATION, ENUM) #NAME,
APPLY_FOR_STATUS(M)
#undef M
};
return strings[event];
}
const char * getDocumentation(Metric event)
{
static const char * strings[] =
{
#define M(NAME, DOCUMENTATION, ENUM) DOCUMENTATION,
APPLY_FOR_STATUS(M)
#undef M
};
return strings[event];
}
const std::vector<std::pair<String, Int8>> & getAllPossibleValues(Metric event)
{
static const std::vector<std::pair<String, Int8>> enum_values [] =
{
#define M(NAME, DOCUMENTATION, ENUM) ENUM,
APPLY_FOR_STATUS(M)
#undef M
};
return enum_values[event];
}
Metric end() { return END; }
}
#undef APPLY_FOR_STATUS

View File

@ -0,0 +1,42 @@
#pragma once
#include <stddef.h>
#include <cstdint>
#include <utility>
#include <atomic>
#include <Core/Types.h>
#include <mutex>
#include <unordered_map>
namespace CurrentStatusInfo
{
/// Metric identifier (index in array).
using Metric = size_t;
using Key = std::string;
/// Get name of metric by identifier. Returns statically allocated string.
const char * getName(Metric event);
/// Get text description of metric by identifier. Returns statically allocated string.
const char * getDocumentation(Metric event);
const std::vector<std::pair<String, Int8>> & getAllPossibleValues(Metric event);
extern std::unordered_map<String, String> values[];
extern std::mutex locks[];
/// Get index just after last metric identifier.
Metric end();
/// Set status of specified.
inline void set(Metric metric, Key key, String value)
{
std::lock_guard<std::mutex> lock(locks[metric]);
values[metric][key] = value;
}
inline void unset(Metric metric, Key key)
{
std::lock_guard<std::mutex> lock(locks[metric]);
values[metric].erase(key);
}
}

View File

@ -8,6 +8,7 @@
#include <Common/ThreadPool.h>
#include <Common/randomSeed.h>
#include <Common/setThreadName.h>
#include <Common/CurrentStatusInfo.h>
#include <ext/chrono_io.h>
#include <ext/scope_guard.h>
#include <boost/range/adaptor/map.hpp>
@ -15,6 +16,12 @@
#include <unordered_set>
namespace CurrentStatusInfo
{
extern const Metric DictionaryStatus;
}
namespace DB
{
namespace ErrorCodes
@ -1035,6 +1042,7 @@ private:
it->second.detach();
loading_threads.erase(it);
}
CurrentStatusInfo::set(CurrentStatusInfo::DictionaryStatus, name, toString(info->status()));
}
/// Calculate next update time for loaded_object. Can be called without mutex locking,