24#include <boost/asio/ip/tcp.hpp>
29 _dataStream = std::make_unique<boost::asio::ip::tcp::iostream>();
31 _batchTimer = std::make_unique<Trinity::Asio::DeadlineTimer>(ioContext);
40 if (boost::system::error_code
const& error =
GetDataStream().error())
42 TC_LOG_ERROR(
"metric",
"Error connecting to '{}:{}', disabling Metric. Error message : {}",
70 std::vector<std::string> thresholdSettings =
sConfigMgr->GetKeysByString(
"Metric.Threshold.");
71 for (std::string& thresholdSetting : thresholdSettings)
74 std::string thresholdName = thresholdSetting.substr(strlen(
"Metric.Threshold."));
75 _thresholds.emplace(std::move(thresholdName), thresholdValue);
82 std::string connectionInfo =
sConfigMgr->GetStringDefault(
"Metric.ConnectionInfo",
"");
83 if (connectionInfo.empty())
85 TC_LOG_ERROR(
"metric",
"'Metric.ConnectionInfo' not specified in configuration file.");
89 std::vector<std::string_view> tokens =
Trinity::Tokenize(connectionInfo,
';',
true);
90 if (tokens.size() != 3)
92 TC_LOG_ERROR(
"metric",
"'Metric.ConnectionInfo' specified with wrong format in configuration file.");
97 _port.assign(tokens[1]);
120 return value >= threshold->second;
123void Metric::LogEvent(std::string_view category, std::string_view title, std::string description)
128 .Timestamp = std::chrono::system_clock::now(),
130 .Title = std::string(title),
131 .ValueOrEventText = std::move(description)
139 using namespace std::chrono;
141 std::stringstream batchedData;
143 bool firstLoop =
true;
153 auto tags = [](
MetricTags const& tags) -> std::span<MetricTag const>
155 switch (tags.index())
157 case 1:
return std::get<1>(tags);
158 case 2:
return std::get<2>(tags);
165 for (
auto const& [tagName, tagValue] : tags)
166 if (!tagName.empty())
183 batchedData << duration_cast<nanoseconds>(data->
Timestamp.time_since_epoch()).count();
190 std::streamoff batchedDataSize = batchedData.tellp();
191 if (batchedDataSize <= 0)
203 GetDataStream() <<
"Content-Type: application/octet-stream\r\n";
206 GetDataStream() <<
"Content-Length: " << batchedDataSize <<
"\r\n\r\n";
209 std::string http_version;
211 unsigned int status_code = 0;
213 if (status_code != 204)
215 TC_LOG_ERROR(
"metric",
"Error sending data, returned HTTP code: {}", status_code);
219 std::string status_description;
223 while (std::getline(
GetDataStream(), header) && header !=
"\r")
224 if (header ==
"Connection: close\r")
275 return std::string(1, value ?
't' :
'f');
278template<
class T>
requires std::integral<T> && (!std::same_as<T, bool>)
281 std::string result = std::to_string(value);
289 result.insert(result.begin(),
'"');
290 result.append(1,
'"');
301 return std::to_string(value);
#define TC_LOG_ERROR(filterType__, message__,...)
std::variant< std::monostate, std::array< MetricTag, 2 >, std::vector< MetricTag > > MetricTags
void StringReplaceAll(std::string *str, std::string_view text, std::string_view replacement)
static std::string FormatInfluxDBTagValue(std::string const &value)
bool ShouldLog(std::string_view category, int64 value) const
std::string _databaseName
static Metric * instance()
void ScheduleOverallStatusLog()
bool _overallStatusTimerTriggered
int32 _overallStatusTimerInterval
void Initialize(std::string const &realmName, Trinity::Asio::IoContext &ioContext, std::function< void()> overallStatusLogger)
std::unique_ptr< Trinity::Asio::DeadlineTimer > _overallStatusTimer
std::function< void()> _overallStatusLogger
std::unique_ptr< iostream > _dataStream
MPSCQueue< MetricData, &MetricData::QueueLink > _queuedData
std::unordered_map< std::string, int64, Trinity::TransparentHash< std::string_view >, std::equal_to<> > _thresholds
static std::string FormatInfluxDBValue(bool value)
std::unique_ptr< Trinity::Asio::DeadlineTimer > _batchTimer
void LogEvent(std::string_view category, std::string_view title, std::string description)
iostream & GetDataStream()
decltype(auto) get_io_context(T &&ioObject)
TC_COMMON_API std::vector< std::string_view > Tokenize(std::string_view str, char sep, bool keepEmpty)
SystemTimePoint Timestamp
std::string ValueOrEventText