Skip to content

Commit c7e7757

Browse files
committed
Core/Metric: Reduce number of string copies in metric and eliminate them entirely when metric is disabled in config
1 parent 8d31f00 commit c7e7757

File tree

3 files changed

+133
-132
lines changed

3 files changed

+133
-132
lines changed

src/common/Collision/Maps/MapTree.cpp

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -365,8 +365,7 @@ namespace VMAP
365365
}
366366
else
367367
iLoadedTiles[packTileID(tileX, tileY)] = false;
368-
TC_METRIC_EVENT("map_events", "LoadMapTile",
369-
"Map: " + std::to_string(iMapID) + " TileX: " + std::to_string(tileX) + " TileY: " + std::to_string(tileY));
368+
TC_METRIC_EVENT("map_events", "LoadMapTile", Trinity::StringFormat("Map: {} TileX: {} TileY: {}", iMapID, tileX, tileY));
370369
return result;
371370
}
372371

@@ -432,8 +431,7 @@ namespace VMAP
432431
}
433432
}
434433
iLoadedTiles.erase(tile);
435-
TC_METRIC_EVENT("map_events", "UnloadMapTile",
436-
"Map: " + std::to_string(iMapID) + " TileX: " + std::to_string(tileX) + " TileY: " + std::to_string(tileY));
434+
TC_METRIC_EVENT("map_events", "UnloadMapTile", Trinity::StringFormat("Map: {} TileX: {} TileY: {}", iMapID, tileX, tileY));
437435
}
438436

439437
std::span<ModelInstance const> StaticMapTree::getModelInstances() const

src/common/Metric/Metric.cpp

Lines changed: 39 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -22,29 +22,29 @@
2222
#include "Log.h"
2323
#include "Util.h"
2424
#include <boost/asio/ip/tcp.hpp>
25+
#include <span>
2526

2627
void Metric::Initialize(std::string const& realmName, Trinity::Asio::IoContext& ioContext, std::function<void()> overallStatusLogger)
2728
{
2829
_dataStream = std::make_unique<boost::asio::ip::tcp::iostream>();
2930
_realmName = FormatInfluxDBTagValue(realmName);
3031
_batchTimer = std::make_unique<Trinity::Asio::DeadlineTimer>(ioContext);
3132
_overallStatusTimer = std::make_unique<Trinity::Asio::DeadlineTimer>(ioContext);
32-
_overallStatusLogger = overallStatusLogger;
33+
_overallStatusLogger = std::move(overallStatusLogger);
3334
LoadFromConfigs();
3435
}
3536

3637
bool Metric::Connect()
3738
{
38-
auto& stream = static_cast<boost::asio::ip::tcp::iostream&>(GetDataStream());
39-
stream.connect(_hostname, _port);
40-
if (boost::system::error_code const& error = stream.error())
39+
GetDataStream().connect(_hostname, _port);
40+
if (boost::system::error_code const& error = GetDataStream().error())
4141
{
4242
TC_LOG_ERROR("metric", "Error connecting to '{}:{}', disabling Metric. Error message : {}",
4343
_hostname, _port, error.message());
4444
_enabled = false;
4545
return false;
4646
}
47-
stream.clear();
47+
GetDataStream().clear();
4848
return true;
4949
}
5050

@@ -68,11 +68,11 @@ void Metric::LoadFromConfigs()
6868

6969
_thresholds.clear();
7070
std::vector<std::string> thresholdSettings = sConfigMgr->GetKeysByString("Metric.Threshold.");
71-
for (std::string const& thresholdSetting : thresholdSettings)
71+
for (std::string& thresholdSetting : thresholdSettings)
7272
{
73-
int thresholdValue = sConfigMgr->GetIntDefault(thresholdSetting, 0);
73+
int64 thresholdValue = sConfigMgr->GetIntDefault(thresholdSetting, 0);
7474
std::string thresholdName = thresholdSetting.substr(strlen("Metric.Threshold."));
75-
_thresholds[thresholdName] = thresholdValue;
75+
_thresholds.emplace(std::move(thresholdName), thresholdValue);
7676
}
7777

7878
// Schedule a send at this point only if the config changed from Disabled to Enabled.
@@ -112,24 +112,24 @@ void Metric::Update()
112112
}
113113
}
114114

115-
bool Metric::ShouldLog(std::string const& category, int64 value) const
115+
bool Metric::ShouldLog(std::string_view category, int64 value) const
116116
{
117117
auto threshold = _thresholds.find(category);
118118
if (threshold == _thresholds.end())
119119
return false;
120120
return value >= threshold->second;
121121
}
122122

123-
void Metric::LogEvent(std::string category, std::string title, std::string description)
123+
void Metric::LogEvent(std::string_view category, std::string_view title, std::string description)
124124
{
125-
using namespace std::chrono;
126-
127-
MetricData* data = new MetricData;
128-
data->Category = std::move(category);
129-
data->Timestamp = system_clock::now();
130-
data->Type = METRIC_DATA_EVENT;
131-
data->Title = std::move(title);
132-
data->ValueOrEventText = std::move(description);
125+
MetricData* data = new MetricData
126+
{
127+
.Category = std::string(category),
128+
.Timestamp = std::chrono::system_clock::now(),
129+
.Type = METRIC_DATA_EVENT,
130+
.Title = std::string(title),
131+
.ValueOrEventText = std::move(description)
132+
};
133133

134134
_queuedData.Enqueue(data);
135135
}
@@ -150,14 +150,21 @@ void Metric::SendBatch()
150150
if (!_realmName.empty())
151151
batchedData << ",realm=" << _realmName;
152152

153-
if (data->Tags)
153+
auto tags = [](MetricTags const& tags) -> std::span<MetricTag const>
154154
{
155-
auto begin = std::visit([](auto&& value) { return value.data(); }, *data->Tags);
156-
auto end = std::visit([](auto&& value) { return value.data() + value.size(); }, *data->Tags);
157-
for (auto itr = begin; itr != end; ++itr)
158-
if (!itr->first.empty())
159-
batchedData << "," << itr->first << "=" << FormatInfluxDBTagValue(itr->second);
160-
}
155+
switch (tags.index())
156+
{
157+
case 1: return std::get<1>(tags);
158+
case 2: return std::get<2>(tags);
159+
default:
160+
break;
161+
}
162+
return {};
163+
}(data->Tags);
164+
165+
for (auto const& [tagName, tagValue] : tags)
166+
if (!tagName.empty())
167+
batchedData << "," << tagName << "=" << FormatInfluxDBTagValue(tagValue);
161168

162169
batchedData << " ";
163170

@@ -173,14 +180,15 @@ void Metric::SendBatch()
173180

174181
batchedData << " ";
175182

176-
batchedData << std::to_string(duration_cast<nanoseconds>(data->Timestamp.time_since_epoch()).count());
183+
batchedData << duration_cast<nanoseconds>(data->Timestamp.time_since_epoch()).count();
177184

178185
firstLoop = false;
179186
delete data;
180187
}
181188

182189
// Check if there's any data to send
183-
if (batchedData.tellp() == std::streampos(0))
190+
std::streamoff batchedDataSize = batchedData.tellp();
191+
if (batchedDataSize <= 0)
184192
{
185193
ScheduleSend();
186194
return;
@@ -195,7 +203,7 @@ void Metric::SendBatch()
195203
GetDataStream() << "Content-Type: application/octet-stream\r\n";
196204
GetDataStream() << "Content-Transfer-Encoding: binary\r\n";
197205

198-
GetDataStream() << "Content-Length: " << std::to_string(batchedData.tellp()) << "\r\n\r\n";
206+
GetDataStream() << "Content-Length: " << batchedDataSize << "\r\n\r\n";
199207
GetDataStream() << batchedData.rdbuf();
200208

201209
std::string http_version;
@@ -214,7 +222,7 @@ void Metric::SendBatch()
214222
std::string header;
215223
while (std::getline(GetDataStream(), header) && header != "\r")
216224
if (header == "Connection: close\r")
217-
static_cast<boost::asio::ip::tcp::iostream&>(GetDataStream()).close();
225+
GetDataStream().close();
218226

219227
ScheduleSend();
220228
}
@@ -228,7 +236,7 @@ void Metric::ScheduleSend()
228236
}
229237
else
230238
{
231-
static_cast<boost::asio::ip::tcp::iostream&>(GetDataStream()).close();
239+
GetDataStream().close();
232240
MetricData* data;
233241
// Clear the queue
234242
while (_queuedData.Dequeue(data))
@@ -267,7 +275,7 @@ std::string Metric::FormatInfluxDBValue(bool value)
267275
return std::string(1, value ? 't' : 'f');
268276
}
269277

270-
template<class T>
278+
template<class T> requires std::integral<T> && (!std::same_as<T, bool>)
271279
std::string Metric::FormatInfluxDBValue(T value)
272280
{
273281
std::string result = std::to_string(value);

0 commit comments

Comments
 (0)