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 METRIC_H__
19#define METRIC_H__
20
21#include "Define.h"
22#include "Duration.h"
23#include "MPSCQueue.h"
24#include "Optional.h"
25#include <boost/container/small_vector.hpp>
26#include <functional>
27#include <iosfwd>
28#include <memory>
29#include <string>
30#include <unordered_map>
31#include <utility>
32
33namespace Trinity
34{
35 namespace Asio
36 {
37 class IoContext;
38 class DeadlineTimer;
39 }
40}
41
47
48using MetricTag = std::pair<std::string, std::string>;
49using MetricTagsVector = boost::container::small_vector<MetricTag, 2>;
50
52{
53 std::string Category;
56
57 // LogValue-specific fields
59
60 // LogEvent-specific fields
61 std::string Title;
62
63 std::string ValueOrEventText;
64
65 // intrusive queue link
66 std::atomic<MetricData*> QueueLink;
67};
68
70{
71private:
72 std::iostream& GetDataStream() { return *_dataStream; }
73 std::unique_ptr<std::iostream> _dataStream;
75 std::unique_ptr<Trinity::Asio::DeadlineTimer> _batchTimer;
76 std::unique_ptr<Trinity::Asio::DeadlineTimer> _overallStatusTimer;
77 int32 _updateInterval = 0;
78 int32 _overallStatusTimerInterval = 0;
79 bool _enabled = false;
80 bool _overallStatusTimerTriggered = false;
81 std::string _hostname;
82 std::string _port;
83 std::string _databaseName;
84 std::function<void()> _overallStatusLogger;
85 std::string _realmName;
86 std::unordered_map<std::string, int64> _thresholds;
87
88 bool Connect();
89 void SendBatch();
90 void ScheduleSend();
91 void ScheduleOverallStatusLog();
92
93 static std::string FormatInfluxDBValue(bool value);
94 template <class T>
95 static std::string FormatInfluxDBValue(T value);
96 static std::string FormatInfluxDBValue(std::string const& value);
97 static std::string FormatInfluxDBValue(char const* value);
98 static std::string FormatInfluxDBValue(double value);
99 static std::string FormatInfluxDBValue(float value);
100 static std::string FormatInfluxDBValue(std::chrono::nanoseconds value);
101
102 static std::string FormatInfluxDBTagValue(std::string const& value);
103
104 // ToDo: should format TagKey and FieldKey too in the same way as TagValue
105
106public:
107 Metric();
108 ~Metric();
109 static Metric* instance();
110
111 void Initialize(std::string const& realmName, Trinity::Asio::IoContext& ioContext, std::function<void()> overallStatusLogger);
112 void LoadFromConfigs();
113 void Update();
114 bool ShouldLog(std::string const& category, int64 value) const;
115
116 template<class T, class... Tags>
117 void LogValue(std::string category, T value, Tags&&... tags)
118 {
119 using namespace std::chrono;
120
121 MetricData* data = new MetricData;
122 data->Category = std::move(category);
123 data->Timestamp = system_clock::now();
124 data->Type = METRIC_DATA_VALUE;
125 data->ValueOrEventText = FormatInfluxDBValue(value);
126 if constexpr (sizeof...(tags) > 0)
127 (data->Tags.emplace_back(std::move(tags)), ...);
128
129 _queuedData.Enqueue(data);
130 }
131
132 void LogEvent(std::string category, std::string title, std::string description);
133
134 void Unload();
135 bool IsEnabled() const { return _enabled; }
136};
137
138#define sMetric Metric::instance()
139
140template<typename LoggerType>
142{
143public:
144 MetricStopWatch(LoggerType&& loggerFunc) :
145 _logger(std::forward<LoggerType>(loggerFunc)),
146 _startTime(std::chrono::steady_clock::now())
147 {
148 }
149
154
155private:
156 LoggerType _logger;
158};
159
160template<typename LoggerType>
162{
163 if (!sMetric->IsEnabled())
164 return {};
165
166 return Optional<MetricStopWatch<LoggerType>>(std::in_place, std::forward<LoggerType>(loggerFunc));
167}
168
169#define TC_METRIC_TAG(name, value) MetricTag(name, value)
170
171#define TC_METRIC_DO_CONCAT(a, b) a ## b
172#define TC_METRIC_CONCAT(a, b) TC_METRIC_DO_CONCAT(a, b)
173#define TC_METRIC_UNIQUE_NAME(name) TC_METRIC_CONCAT(name, __LINE__)
174
175#if defined PERFORMANCE_PROFILING || defined WITHOUT_METRICS
176#define TC_METRIC_EVENT(category, title, description) ((void)0)
177#define TC_METRIC_VALUE(category, value, ...) ((void)0)
178#define TC_METRIC_TIMER(category, ...) ((void)0)
179#define TC_METRIC_DETAILED_EVENT(category, title, description) ((void)0)
180#define TC_METRIC_DETAILED_TIMER(category, ...) ((void)0)
181#define TC_METRIC_DETAILED_NO_THRESHOLD_TIMER(category, ...) ((void)0)
182#else
183# if TRINITY_PLATFORM != TRINITY_PLATFORM_WINDOWS
184#define TC_METRIC_EVENT(category, title, description) \
185 do { \
186 if (sMetric->IsEnabled()) \
187 sMetric->LogEvent(category, title, description); \
188 } while (0)
189#define TC_METRIC_VALUE(category, value, ...) \
190 do { \
191 if (sMetric->IsEnabled()) \
192 sMetric->LogValue(category, value, ##__VA_ARGS__); \
193 } while (0)
194# else
195#define TC_METRIC_EVENT(category, title, description) \
196 __pragma(warning(push)) \
197 __pragma(warning(disable:4127)) \
198 do { \
199 if (sMetric->IsEnabled()) \
200 sMetric->LogEvent(category, title, description); \
201 } while (0) \
202 __pragma(warning(pop))
203#define TC_METRIC_VALUE(category, value, ...) \
204 __pragma(warning(push)) \
205 __pragma(warning(disable:4127)) \
206 do { \
207 if (sMetric->IsEnabled()) \
208 sMetric->LogValue(category, value, ##__VA_ARGS__); \
209 } while (0) \
210 __pragma(warning(pop))
211# endif
212#define TC_METRIC_TIMER(category, ...) \
213 auto TC_METRIC_UNIQUE_NAME(__tc_metric_stop_watch) = MakeMetricStopWatch([&](TimePoint start) \
214 { \
215 sMetric->LogValue(category, std::chrono::steady_clock::now() - start, ##__VA_ARGS__); \
216 });
217# if defined WITH_DETAILED_METRICS
218#define TC_METRIC_DETAILED_TIMER(category, ...) \
219 auto TC_METRIC_UNIQUE_NAME(__tc_metric_stop_watch) = MakeMetricStopWatch([&](TimePoint start) \
220 { \
221 int64 duration = int64(std::chrono::duration_cast<Milliseconds>(std::chrono::steady_clock::now() - start).count()); \
222 std::string category2 = category; \
223 if (sMetric->ShouldLog(category2, duration)) \
224 sMetric->LogValue(std::move(category2), duration, ##__VA_ARGS__); \
225 });
226#define TC_METRIC_DETAILED_NO_THRESHOLD_TIMER(category, ...) TC_METRIC_TIMER(category, ##__VA_ARGS__)
227#define TC_METRIC_DETAILED_EVENT(category, title, description) TC_METRIC_EVENT(category, title, description)
228# else
229#define TC_METRIC_DETAILED_EVENT(category, title, description) ((void)0)
230#define TC_METRIC_DETAILED_TIMER(category, ...) ((void)0)
231#define TC_METRIC_DETAILED_NO_THRESHOLD_TIMER(category, ...) ((void)0)
232# endif
233
234#endif
235
236#endif // METRIC_H__
int64_t int64
Definition Define.h:128
#define TC_COMMON_API
Definition Define.h:96
int32_t int32
Definition Define.h:129
std::chrono::system_clock::time_point SystemTimePoint
Definition Duration.h:37
std::chrono::steady_clock::time_point TimePoint
time_point shorthand typedefs
Definition Duration.h:36
std::conditional_t< IntrusiveLink !=nullptr, Trinity::Impl::MPSCQueueIntrusive< T, IntrusiveLink >, Trinity::Impl::MPSCQueueNonIntrusive< T > > MPSCQueue
Definition MPSCQueue.h:167
MetricDataType
Definition Metric.h:43
@ METRIC_DATA_EVENT
Definition Metric.h:45
@ METRIC_DATA_VALUE
Definition Metric.h:44
Optional< MetricStopWatch< LoggerType > > MakeMetricStopWatch(LoggerType &&loggerFunc)
Definition Metric.h:161
std::pair< std::string, std::string > MetricTag
Definition Metric.h:48
#define sMetric
Definition Metric.h:138
boost::container::small_vector< MetricTag, 2 > MetricTagsVector
Definition Metric.h:49
std::optional< T > Optional
Optional helper class to wrap optional values within.
Definition Optional.h:25
MetricStopWatch(LoggerType &&loggerFunc)
Definition Metric.h:144
LoggerType _logger
Definition Metric.h:156
TimePoint _startTime
Definition Metric.h:157
std::string _hostname
Definition Metric.h:81
std::unique_ptr< std::iostream > _dataStream
Definition Metric.h:73
void LogValue(std::string category, T value, Tags &&... tags)
Definition Metric.h:117
std::string _port
Definition Metric.h:82
std::string _databaseName
Definition Metric.h:83
std::string _realmName
Definition Metric.h:85
std::unique_ptr< Trinity::Asio::DeadlineTimer > _overallStatusTimer
Definition Metric.h:76
std::iostream & GetDataStream()
Definition Metric.h:72
std::function< void()> _overallStatusLogger
Definition Metric.h:84
MPSCQueue< MetricData, &MetricData::QueueLink > _queuedData
Definition Metric.h:74
std::unique_ptr< Trinity::Asio::DeadlineTimer > _batchTimer
Definition Metric.h:75
bool IsEnabled() const
Definition Metric.h:135
std::unordered_map< std::string, int64 > _thresholds
Definition Metric.h:86
STL namespace.
std::string Category
Definition Metric.h:53
SystemTimePoint Timestamp
Definition Metric.h:54
std::string Title
Definition Metric.h:61
std::string ValueOrEventText
Definition Metric.h:63
MetricTagsVector Tags
Definition Metric.h:58
MetricDataType Type
Definition Metric.h:55
std::atomic< MetricData * > QueueLink
Definition Metric.h:66