1#include "PrometheusMetricsWriter.h"
2
3#include <algorithm>
4
5#include <IO/WriteHelpers.h>
6
7namespace
8{
9
10template <typename T>
11void writeOutLine(DB::WriteBuffer & wb, T && val)
12{
13 DB::writeText(std::forward<T>(val), wb);
14 DB::writeChar('\n', wb);
15}
16
17template <typename T, typename... TArgs>
18void writeOutLine(DB::WriteBuffer & wb, T && val, TArgs &&... args)
19{
20 DB::writeText(std::forward<T>(val), wb);
21 DB::writeChar(' ', wb);
22 writeOutLine(wb, std::forward<TArgs>(args)...);
23}
24
25void replaceInvalidChars(std::string & metric_name)
26{
27 std::replace(metric_name.begin(), metric_name.end(), '.', '_');
28}
29
30}
31
32
33namespace DB
34{
35
36PrometheusMetricsWriter::PrometheusMetricsWriter(
37 const Poco::Util::AbstractConfiguration & config, const std::string & config_name,
38 const AsynchronousMetrics & async_metrics_)
39 : async_metrics(async_metrics_)
40 , send_events(config.getBool(config_name + ".events", true))
41 , send_metrics(config.getBool(config_name + ".metrics", true))
42 , send_asynchronous_metrics(config.getBool(config_name + ".asynchronous_metrics", true))
43{
44}
45
46void PrometheusMetricsWriter::write(WriteBuffer & wb) const
47{
48 if (send_events)
49 {
50 for (size_t i = 0, end = ProfileEvents::end(); i < end; ++i)
51 {
52 const auto counter = ProfileEvents::global_counters[i].load(std::memory_order_relaxed);
53
54 std::string metric_name{ProfileEvents::getName(static_cast<ProfileEvents::Event>(i))};
55 std::string metric_doc{ProfileEvents::getDocumentation(static_cast<ProfileEvents::Event>(i))};
56
57 replaceInvalidChars(metric_name);
58 std::string key{profile_events_prefix + metric_name};
59
60 writeOutLine(wb, "# HELP", key, metric_doc);
61 writeOutLine(wb, "# TYPE", key, "counter");
62 writeOutLine(wb, key, counter);
63 }
64 }
65
66 if (send_metrics)
67 {
68 for (size_t i = 0, end = CurrentMetrics::end(); i < end; ++i)
69 {
70 const auto value = CurrentMetrics::values[i].load(std::memory_order_relaxed);
71
72 std::string metric_name{CurrentMetrics::getName(static_cast<CurrentMetrics::Metric>(i))};
73 std::string metric_doc{CurrentMetrics::getDocumentation(static_cast<CurrentMetrics::Metric>(i))};
74
75 replaceInvalidChars(metric_name);
76 std::string key{current_metrics_prefix + metric_name};
77
78 writeOutLine(wb, "# HELP", key, metric_doc);
79 writeOutLine(wb, "# TYPE", key, "gauge");
80 writeOutLine(wb, key, value);
81 }
82 }
83
84 if (send_asynchronous_metrics)
85 {
86 auto async_metrics_values = async_metrics.getValues();
87 for (const auto & name_value : async_metrics_values)
88 {
89 std::string key{asynchronous_metrics_prefix + name_value.first};
90
91 replaceInvalidChars(key);
92 auto value = name_value.second;
93
94 // TODO: add HELP section? asynchronous_metrics contains only key and value
95 writeOutLine(wb, "# TYPE", key, "gauge");
96 writeOutLine(wb, key, value);
97 }
98 }
99}
100
101}
102