24#include <boost/algorithm/string/replace.hpp>
25#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);
39 auto& stream =
static_cast<boost::asio::ip::tcp::iostream&
>(
GetDataStream());
41 auto error = stream.error();
44 TC_LOG_ERROR(
"metric",
"Error connecting to '{}:{}', disabling Metric. Error message : {}",
72 std::vector<std::string> thresholdSettings =
sConfigMgr->GetKeysByString(
"Metric.Threshold.");
73 for (std::string
const& thresholdSetting : thresholdSettings)
75 int thresholdValue =
sConfigMgr->GetIntDefault(thresholdSetting, 0);
76 std::string thresholdName = thresholdSetting.substr(strlen(
"Metric.Threshold."));
84 std::string connectionInfo =
sConfigMgr->GetStringDefault(
"Metric.ConnectionInfo",
"");
85 if (connectionInfo.empty())
87 TC_LOG_ERROR(
"metric",
"'Metric.ConnectionInfo' not specified in configuration file.");
91 std::vector<std::string_view> tokens =
Trinity::Tokenize(connectionInfo,
';',
true);
92 if (tokens.size() != 3)
94 TC_LOG_ERROR(
"metric",
"'Metric.ConnectionInfo' specified with wrong format in configuration file.");
99 _port.assign(tokens[1]);
122 return value >= threshold->second;
127 using namespace std::chrono;
130 data->
Category = std::move(category);
133 data->
Title = std::move(title);
141 using namespace std::chrono;
143 std::stringstream batchedData;
145 bool firstLoop =
true;
157 auto begin = std::visit([](
auto&& value) {
return value.data(); }, *data->
Tags);
158 auto end = std::visit([](
auto&& value) {
return value.data() + value.size(); }, *data->
Tags);
159 for (
auto itr = begin; itr != end; ++itr)
160 if (!itr->first.empty())
178 batchedData << std::to_string(duration_cast<nanoseconds>(data->
Timestamp.time_since_epoch()).count());
185 if (batchedData.tellp() == std::streampos(0))
197 GetDataStream() <<
"Content-Type: application/octet-stream\r\n";
200 GetDataStream() <<
"Content-Length: " << std::to_string(batchedData.tellp()) <<
"\r\n\r\n";
203 std::string http_version;
205 unsigned int status_code = 0;
207 if (status_code != 204)
209 TC_LOG_ERROR(
"metric",
"Error sending data, returned HTTP code: {}", status_code);
213 std::string status_description;
217 while (std::getline(
GetDataStream(), header) && header !=
"\r")
218 if (header ==
"Connection: close\r")
219 static_cast<boost::asio::ip::tcp::iostream&
>(
GetDataStream()).close();
233 static_cast<boost::asio::ip::tcp::iostream&
>(
GetDataStream()).close();
269 return value ?
"t" :
"f";
275 return std::to_string(value) +
'i';
280 return '"' + boost::replace_all_copy(value,
"\"",
"\\\"") +
'"';
290 return std::to_string(value);
301 return boost::replace_all_copy(value,
" ",
"\\ ");
#define TC_LOG_ERROR(filterType__,...)
std::unique_ptr< std::iostream > _dataStream
static std::string FormatInfluxDBTagValue(std::string const &value)
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::iostream & GetDataStream()
std::function< void()> _overallStatusLogger
MPSCQueue< MetricData, &MetricData::QueueLink > _queuedData
bool ShouldLog(std::string const &category, int64 value) const
static std::string FormatInfluxDBValue(bool value)
std::unique_ptr< Trinity::Asio::DeadlineTimer > _batchTimer
std::unordered_map< std::string, int64 > _thresholds
void LogEvent(std::string category, std::string title, std::string description)
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
Optional< std::variant< std::array< MetricTag, 2 >, std::vector< MetricTag > > > Tags