TrinityCore
Loading...
Searching...
No Matches
Metric.h
Go to the documentation of this file.
1/*
2 * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#ifndef TRINITYCORE_METRIC_H
19#define TRINITYCORE_METRIC_H
20
21#include "AsioHacksFwd.h"
22#include "Define.h"
23#include "Duration.h"
24#include "Hash.h"
25#include "MPSCQueue.h"
26#include <functional>
27#include <memory>
28#include <string>
29#include <unordered_map>
30#include <utility>
31#include <variant>
32
38
39using MetricTag = std::pair<std::string, std::string>;
40using MetricTags = std::variant<std::monostate, std::array<MetricTag, 2>, std::vector<MetricTag>>;
41
43{
44 std::string Category;
47
48 // LogValue-specific fields
50
51 // LogEvent-specific fields
52 std::string Title;
53
54 std::string ValueOrEventText;
55
56 // intrusive queue link
57 std::atomic<MetricData*> QueueLink;
58};
59
61{
62private:
64
65 iostream& GetDataStream() { return *_dataStream; }
66 std::unique_ptr<iostream> _dataStream;
68 std::unique_ptr<Trinity::Asio::DeadlineTimer> _batchTimer;
69 std::unique_ptr<Trinity::Asio::DeadlineTimer> _overallStatusTimer;
70 int32 _updateInterval = 0;
71 int32 _overallStatusTimerInterval = 0;
72 bool _enabled = false;
73 bool _overallStatusTimerTriggered = false;
74 std::string _hostname;
75 std::string _port;
76 std::string _databaseName;
77 std::function<void()> _overallStatusLogger;
78 std::string _realmName;
79 std::unordered_map<std::string, int64, Trinity::TransparentHash<std::string_view>, std::equal_to<>> _thresholds;
80
81 bool Connect();
82 void SendBatch();
83 void ScheduleSend();
84 void ScheduleOverallStatusLog();
85
86 static std::string FormatInfluxDBValue(bool value);
87 template <class T> requires std::integral<T> && (!std::same_as<T, bool>)
88 static std::string FormatInfluxDBValue(T value);
89 static std::string FormatInfluxDBValue(std::string const& value);
90 static std::string FormatInfluxDBValue(char const* value);
91 static std::string FormatInfluxDBValue(double value);
92 static std::string FormatInfluxDBValue(float value);
93 static std::string FormatInfluxDBValue(std::chrono::nanoseconds value);
94
95 static std::string FormatInfluxDBTagValue(std::string const& value);
96
97 // ToDo: should format TagKey and FieldKey too in the same way as TagValue
98
99public:
100 Metric();
101 ~Metric();
102 Metric(Metric const&) = delete;
103 Metric(Metric&&) = delete;
104 Metric& operator=(Metric const&) = delete;
105 Metric& operator=(Metric&&) = delete;
106 static Metric* instance();
107
108 void Initialize(std::string const& realmName, Trinity::Asio::IoContext& ioContext, std::function<void()> overallStatusLogger);
109 void LoadFromConfigs();
110 void Update();
111 bool ShouldLog(std::string_view category, int64 value) const;
112
113 template<class T, class... TagsList>
114 void LogValue(std::string_view category, T value, TagsList&&... tags) noexcept
115 {
116 using TagsType = std::conditional_t<(sizeof...(tags) > 2),
117 std::vector<MetricTag>,
118 std::conditional_t<(sizeof...(tags) > 0),
119 std::array<MetricTag, 2>,
120 std::monostate>>;
121
122 MetricData* data = new MetricData
123 {
124 .Category = std::string(category),
125 .Timestamp = std::chrono::system_clock::now(),
126 .Type = METRIC_DATA_VALUE,
127 .Tags = MetricTags{ std::in_place_type<TagsType> },
128 .ValueOrEventText = FormatInfluxDBValue(value)
129 };
130 if constexpr (sizeof...(tags) > 2)
131 {
132 TagsType& tagsVector = std::get<TagsType>(data->Tags);
133 (tagsVector.emplace_back(std::forward<TagsList>(tags)), ...);
134 }
135 else if constexpr (sizeof...(tags) == 2)
136 {
137 [](TagsType& tagsArray, auto const& tag1, auto const& tag2)
138 {
139 tagsArray[0] = tag1;
140 tagsArray[1] = tag2;
141 }(std::get<TagsType>(data->Tags), std::forward<TagsList>(tags)...);
142 }
143 else if constexpr (sizeof...(tags) == 1)
144 {
145 [](TagsType& tagsArray, auto const& tag1)
146 {
147 tagsArray[0] = tag1;
148 }(std::get<TagsType>(data->Tags), std::forward<TagsList>(tags)...);
149 }
150
151 _queuedData.Enqueue(data);
152 }
153
154 void LogEvent(std::string_view category, std::string_view title, std::string description);
155
156 void Unload();
157 bool IsEnabled() const { return _enabled; }
158};
159
160#define sMetric Metric::instance()
161
163{
164 void Enable(Metric* metric) noexcept
165 {
166 MetricInstance = metric;
167 StartTime = std::chrono::steady_clock::now();
168 }
169
172};
173
174template<typename LoggerType>
175struct MetricStopWatch : public LoggerType, public MetricStopWatchBase
176{
178 {
179 if (MetricInstance)
180 LoggerType::operator()(MetricInstance, StartTime);
181 }
182};
183
184template<typename LoggerType>
186
187#define TC_METRIC_TAG(name, value) std::pair<std::string_view, std::string_view>(name, value)
188
189#define TC_METRIC_DO_CONCAT(a, b) a ## b
190#define TC_METRIC_CONCAT(a, b) TC_METRIC_DO_CONCAT(a, b)
191#define TC_METRIC_UNIQUE_NAME(name) TC_METRIC_CONCAT(name, __LINE__)
192
193#if defined PERFORMANCE_PROFILING || defined WITHOUT_METRICS
194#define TC_METRIC_EVENT(category, title, description) ((void)0)
195#define TC_METRIC_VALUE(category, value, ...) ((void)0)
196#define TC_METRIC_TIMER(category, ...) ((void)0)
197#define TC_METRIC_DETAILED_EVENT(category, title, description) ((void)0)
198#define TC_METRIC_DETAILED_TIMER(category, ...) ((void)0)
199#define TC_METRIC_DETAILED_NO_THRESHOLD_TIMER(category, ...) ((void)0)
200#else
201#define TC_METRIC_EVENT(category, title, description) \
202 do { \
203 if (Metric* metric = sMetric; metric->IsEnabled()) \
204 metric->LogEvent(category, title, description); \
205 } while (false)
206#define TC_METRIC_VALUE(category, value, ...) \
207 do { \
208 if (Metric* metric = sMetric; metric->IsEnabled()) \
209 metric->LogValue(category, value, ## __VA_ARGS__); \
210 } while (false)
211#define TC_METRIC_TIMER_IMPL(variable, category, ...) \
212 MetricStopWatch variable{ [&](Metric* metric, TimePoint start) \
213 { \
214 metric->LogValue(category, std::chrono::steady_clock::now() - start, ## __VA_ARGS__); \
215 } }; \
216 do \
217 { \
218 if (Metric* metric = sMetric; metric->IsEnabled()) \
219 variable.Enable(metric); \
220 } while (false)
221#define TC_METRIC_TIMER(category, ...) TC_METRIC_TIMER_IMPL(TC_METRIC_UNIQUE_NAME(tc_metric_stop_watch_), category, ## __VA_ARGS__)
222# if defined WITH_DETAILED_METRICS
223#define TC_METRIC_DETAILED_TIMER_IMPL(variable, category, ...) \
224 MetricStopWatch variable{ [&](Metric* metric, TimePoint start) \
225 { \
226 int64 duration = int64(duration_cast<Milliseconds>(std::chrono::steady_clock::now() - start).count()); \
227 if (metric->ShouldLog(category, duration)) \
228 metric->LogValue(category, duration, ## __VA_ARGS__); \
229 } }; \
230 do \
231 { \
232 if (Metric* metric = sMetric; metric->IsEnabled()) \
233 variable.Enable(metric); \
234 } while (false)
235#define TC_METRIC_DETAILED_TIMER(category, ...) TC_METRIC_DETAILED_TIMER_IMPL(TC_METRIC_UNIQUE_NAME(tc_metric_stop_watch_), category, ## __VA_ARGS__)
236#define TC_METRIC_DETAILED_NO_THRESHOLD_TIMER(category, ...) TC_METRIC_TIMER(category, ## __VA_ARGS__)
237#define TC_METRIC_DETAILED_EVENT(category, title, description) TC_METRIC_EVENT(category, title, description)
238# else
239#define TC_METRIC_DETAILED_EVENT(category, title, description) ((void)0)
240#define TC_METRIC_DETAILED_TIMER(category, ...) ((void)0)
241#define TC_METRIC_DETAILED_NO_THRESHOLD_TIMER(category, ...) ((void)0)
242# endif
243
244#endif
245
246#endif // TRINITYCORE_METRIC_H
int64_t int64
Definition Define.h:149
#define TC_COMMON_API
Definition Define.h:99
int32_t int32
Definition Define.h:150
std::chrono::system_clock::time_point SystemTimePoint
Definition Duration.h:41
std::chrono::steady_clock::time_point TimePoint
time_point shorthand typedefs
Definition Duration.h:40
std::conditional_t< IntrusiveLink !=nullptr, Trinity::Impl::MPSCQueueIntrusive< T, IntrusiveLink >, Trinity::Impl::MPSCQueueNonIntrusive< T > > MPSCQueue
Definition MPSCQueue.h:173
MetricDataType
Definition Metric.h:34
@ METRIC_DATA_EVENT
Definition Metric.h:36
@ METRIC_DATA_VALUE
Definition Metric.h:35
std::pair< std::string, std::string > MetricTag
Definition Metric.h:39
std::variant< std::monostate, std::array< MetricTag, 2 >, std::vector< MetricTag > > MetricTags
Definition Metric.h:40
std::string _hostname
Definition Metric.h:74
Metric(Metric const &)=delete
std::string _port
Definition Metric.h:75
Metric(Metric &&)=delete
std::string _databaseName
Definition Metric.h:76
std::string _realmName
Definition Metric.h:78
Metric & operator=(Metric const &)=delete
std::unique_ptr< Trinity::Asio::DeadlineTimer > _overallStatusTimer
Definition Metric.h:69
std::function< void()> _overallStatusLogger
Definition Metric.h:77
std::unique_ptr< iostream > _dataStream
Definition Metric.h:66
Metric & operator=(Metric &&)=delete
void LogValue(std::string_view category, T value, TagsList &&... tags) noexcept
Definition Metric.h:114
MPSCQueue< MetricData, &MetricData::QueueLink > _queuedData
Definition Metric.h:67
std::unordered_map< std::string, int64, Trinity::TransparentHash< std::string_view >, std::equal_to<> > _thresholds
Definition Metric.h:79
std::unique_ptr< Trinity::Asio::DeadlineTimer > _batchTimer
Definition Metric.h:68
bool IsEnabled() const
Definition Metric.h:157
iostream & GetDataStream()
Definition Metric.h:65
std::string Category
Definition Metric.h:44
SystemTimePoint Timestamp
Definition Metric.h:45
std::string Title
Definition Metric.h:52
std::string ValueOrEventText
Definition Metric.h:54
MetricTags Tags
Definition Metric.h:49
MetricDataType Type
Definition Metric.h:46
std::atomic< MetricData * > QueueLink
Definition Metric.h:57
Metric * MetricInstance
Definition Metric.h:170
TimePoint StartTime
Definition Metric.h:171
void Enable(Metric *metric) noexcept
Definition Metric.h:164