forked from Mirrorlandia_minetest/minetest
Add MetricsBackend with prometheus counter support
This commit is contained in:
parent
a36c9c3e93
commit
56bababcdf
22
Dockerfile
22
Dockerfile
@ -21,15 +21,29 @@ WORKDIR /usr/src/minetest
|
|||||||
RUN apk add --no-cache git build-base irrlicht-dev cmake bzip2-dev libpng-dev \
|
RUN apk add --no-cache git build-base irrlicht-dev cmake bzip2-dev libpng-dev \
|
||||||
jpeg-dev libxxf86vm-dev mesa-dev sqlite-dev libogg-dev \
|
jpeg-dev libxxf86vm-dev mesa-dev sqlite-dev libogg-dev \
|
||||||
libvorbis-dev openal-soft-dev curl-dev freetype-dev zlib-dev \
|
libvorbis-dev openal-soft-dev curl-dev freetype-dev zlib-dev \
|
||||||
gmp-dev jsoncpp-dev postgresql-dev && \
|
gmp-dev jsoncpp-dev postgresql-dev ca-certificates && \
|
||||||
git clone --depth=1 -b ${MINETEST_GAME_VERSION} https://github.com/minetest/minetest_game.git ./games/minetest_game && \
|
git clone --depth=1 -b ${MINETEST_GAME_VERSION} https://github.com/minetest/minetest_game.git ./games/minetest_game && \
|
||||||
rm -fr ./games/minetest_game/.git && \
|
rm -fr ./games/minetest_game/.git
|
||||||
mkdir build && \
|
|
||||||
|
WORKDIR /usr/src/
|
||||||
|
RUN git clone --recursive https://github.com/jupp0r/prometheus-cpp/ && \
|
||||||
|
mkdir prometheus-cpp/build && \
|
||||||
|
cd prometheus-cpp/build && \
|
||||||
|
cmake .. \
|
||||||
|
-DCMAKE_INSTALL_PREFIX=/usr/local \
|
||||||
|
-DCMAKE_BUILD_TYPE=Release \
|
||||||
|
-DENABLE_TESTING=0 && \
|
||||||
|
make -j2 && \
|
||||||
|
make install
|
||||||
|
|
||||||
|
WORKDIR /usr/src/minetest
|
||||||
|
RUN mkdir build && \
|
||||||
cd build && \
|
cd build && \
|
||||||
cmake .. \
|
cmake .. \
|
||||||
-DCMAKE_INSTALL_PREFIX=/usr/local \
|
-DCMAKE_INSTALL_PREFIX=/usr/local \
|
||||||
-DCMAKE_BUILD_TYPE=Release \
|
-DCMAKE_BUILD_TYPE=Release \
|
||||||
-DBUILD_SERVER=TRUE \
|
-DBUILD_SERVER=TRUE \
|
||||||
|
-DENABLE_PROMETHEUS=TRUE \
|
||||||
-DBUILD_UNITTESTS=FALSE \
|
-DBUILD_UNITTESTS=FALSE \
|
||||||
-DBUILD_CLIENT=FALSE && \
|
-DBUILD_CLIENT=FALSE && \
|
||||||
make -j2 && \
|
make -j2 && \
|
||||||
@ -49,6 +63,6 @@ COPY --from=0 /usr/local/share/doc/minetest/minetest.conf.example /etc/minetest/
|
|||||||
|
|
||||||
USER minetest:minetest
|
USER minetest:minetest
|
||||||
|
|
||||||
EXPOSE 30000/udp
|
EXPOSE 30000/udp 30000/tcp
|
||||||
|
|
||||||
CMD ["/usr/local/bin/minetestserver", "--config", "/etc/minetest/minetest.conf"]
|
CMD ["/usr/local/bin/minetestserver", "--config", "/etc/minetest/minetest.conf"]
|
||||||
|
@ -236,6 +236,7 @@ General options and their default values:
|
|||||||
ENABLE_SPATIAL=ON - Build with LibSpatial; Speeds up AreaStores
|
ENABLE_SPATIAL=ON - Build with LibSpatial; Speeds up AreaStores
|
||||||
ENABLE_SOUND=ON - Build with OpenAL, libogg & libvorbis; in-game sounds
|
ENABLE_SOUND=ON - Build with OpenAL, libogg & libvorbis; in-game sounds
|
||||||
ENABLE_LUAJIT=ON - Build with LuaJIT (much faster than non-JIT Lua)
|
ENABLE_LUAJIT=ON - Build with LuaJIT (much faster than non-JIT Lua)
|
||||||
|
ENABLE_PROMETHEUS=OFF - Build with Prometheus metrics exporter (listens on tcp/30000 by default)
|
||||||
ENABLE_SYSTEM_GMP=ON - Use GMP from system (much faster than bundled mini-gmp)
|
ENABLE_SYSTEM_GMP=ON - Use GMP from system (much faster than bundled mini-gmp)
|
||||||
ENABLE_SYSTEM_JSONCPP=OFF - Use JsonCPP from system
|
ENABLE_SYSTEM_JSONCPP=OFF - Use JsonCPP from system
|
||||||
OPENGL_GL_PREFERENCE=LEGACY - Linux client build only; See CMake Policy CMP0072 for reference
|
OPENGL_GL_PREFERENCE=LEGACY - Linux client build only; See CMake Policy CMP0072 for reference
|
||||||
|
@ -955,6 +955,12 @@ address (Server address) string
|
|||||||
# Note that the port field in the main menu overrides this setting.
|
# Note that the port field in the main menu overrides this setting.
|
||||||
remote_port (Remote port) int 30000 1 65535
|
remote_port (Remote port) int 30000 1 65535
|
||||||
|
|
||||||
|
# Prometheus listener address.
|
||||||
|
# If minetest is compiled with ENABLE_PROMETHEUS option enabled,
|
||||||
|
# enable metrics listener for Prometheus on that address.
|
||||||
|
# Metrics can be fetch on http://127.0.0.1:30000/metrics
|
||||||
|
prometheus_listener_address (Prometheus listener address) string 127.0.0.1:30000
|
||||||
|
|
||||||
# Save the map received by the client on disk.
|
# Save the map received by the client on disk.
|
||||||
enable_local_map_saving (Saving map received from server) bool false
|
enable_local_map_saving (Saving map received from server) bool false
|
||||||
|
|
||||||
|
@ -217,6 +217,26 @@ endif(ENABLE_REDIS)
|
|||||||
|
|
||||||
find_package(SQLite3 REQUIRED)
|
find_package(SQLite3 REQUIRED)
|
||||||
|
|
||||||
|
OPTION(ENABLE_PROMETHEUS "Enable prometheus client support" FALSE)
|
||||||
|
set(USE_PROMETHEUS FALSE)
|
||||||
|
|
||||||
|
if(ENABLE_PROMETHEUS)
|
||||||
|
find_path(PROMETHEUS_CPP_INCLUDE_DIR NAMES prometheus/counter.h)
|
||||||
|
find_library(PROMETHEUS_PULL_LIBRARY NAMES prometheus-cpp-pull)
|
||||||
|
find_library(PROMETHEUS_CORE_LIBRARY NAMES prometheus-cpp-core)
|
||||||
|
if(PROMETHEUS_CPP_INCLUDE_DIR AND PROMETHEUS_PULL_LIBRARY AND PROMETHEUS_CORE_LIBRARY)
|
||||||
|
set(PROMETHEUS_LIBRARIES ${PROMETHEUS_PULL_LIBRARY} ${PROMETHEUS_CORE_LIBRARY})
|
||||||
|
set(USE_PROMETHEUS TRUE)
|
||||||
|
include_directories(${PROMETHEUS_CPP_INCLUDE_DIR})
|
||||||
|
endif(PROMETHEUS_CPP_INCLUDE_DIR AND PROMETHEUS_PULL_LIBRARY AND PROMETHEUS_CORE_LIBRARY)
|
||||||
|
endif(ENABLE_PROMETHEUS)
|
||||||
|
|
||||||
|
if(USE_PROMETHEUS)
|
||||||
|
message(STATUS "Prometheus client enabled.")
|
||||||
|
else(USE_PROMETHEUS)
|
||||||
|
message(STATUS "Prometheus client disabled.")
|
||||||
|
endif(USE_PROMETHEUS)
|
||||||
|
|
||||||
OPTION(ENABLE_SPATIAL "Enable SpatialIndex AreaStore backend" TRUE)
|
OPTION(ENABLE_SPATIAL "Enable SpatialIndex AreaStore backend" TRUE)
|
||||||
set(USE_SPATIAL FALSE)
|
set(USE_SPATIAL FALSE)
|
||||||
|
|
||||||
@ -597,6 +617,9 @@ if(BUILD_CLIENT)
|
|||||||
if (USE_REDIS)
|
if (USE_REDIS)
|
||||||
target_link_libraries(${PROJECT_NAME} ${REDIS_LIBRARY})
|
target_link_libraries(${PROJECT_NAME} ${REDIS_LIBRARY})
|
||||||
endif()
|
endif()
|
||||||
|
if (USE_PROMETHEUS)
|
||||||
|
target_link_libraries(${PROJECT_NAME} ${PROMETHEUS_LIBRARIES})
|
||||||
|
endif()
|
||||||
if (USE_SPATIAL)
|
if (USE_SPATIAL)
|
||||||
target_link_libraries(${PROJECT_NAME} ${SPATIAL_LIBRARY})
|
target_link_libraries(${PROJECT_NAME} ${SPATIAL_LIBRARY})
|
||||||
endif()
|
endif()
|
||||||
@ -632,6 +655,9 @@ if(BUILD_SERVER)
|
|||||||
if (USE_REDIS)
|
if (USE_REDIS)
|
||||||
target_link_libraries(${PROJECT_NAME}server ${REDIS_LIBRARY})
|
target_link_libraries(${PROJECT_NAME}server ${REDIS_LIBRARY})
|
||||||
endif()
|
endif()
|
||||||
|
if (USE_PROMETHEUS)
|
||||||
|
target_link_libraries(${PROJECT_NAME}server ${PROMETHEUS_LIBRARIES})
|
||||||
|
endif()
|
||||||
if (USE_SPATIAL)
|
if (USE_SPATIAL)
|
||||||
target_link_libraries(${PROJECT_NAME}server ${SPATIAL_LIBRARY})
|
target_link_libraries(${PROJECT_NAME}server ${SPATIAL_LIBRARY})
|
||||||
endif()
|
endif()
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
#cmakedefine01 USE_LEVELDB
|
#cmakedefine01 USE_LEVELDB
|
||||||
#cmakedefine01 USE_LUAJIT
|
#cmakedefine01 USE_LUAJIT
|
||||||
#cmakedefine01 USE_POSTGRESQL
|
#cmakedefine01 USE_POSTGRESQL
|
||||||
|
#cmakedefine01 USE_PROMETHEUS
|
||||||
#cmakedefine01 USE_SPATIAL
|
#cmakedefine01 USE_SPATIAL
|
||||||
#cmakedefine01 USE_SYSTEM_GMP
|
#cmakedefine01 USE_SYSTEM_GMP
|
||||||
#cmakedefine01 USE_REDIS
|
#cmakedefine01 USE_REDIS
|
||||||
|
@ -334,6 +334,9 @@ void set_default_settings(Settings *settings)
|
|||||||
// Server
|
// Server
|
||||||
settings->setDefault("disable_escape_sequences", "false");
|
settings->setDefault("disable_escape_sequences", "false");
|
||||||
settings->setDefault("strip_color_codes", "false");
|
settings->setDefault("strip_color_codes", "false");
|
||||||
|
#if USE_PROMETHEUS
|
||||||
|
settings->setDefault("prometheus_listener_address", "127.0.0.1:30000");
|
||||||
|
#endif
|
||||||
|
|
||||||
// Network
|
// Network
|
||||||
settings->setDefault("enable_ipv6", "true");
|
settings->setDefault("enable_ipv6", "true");
|
||||||
|
@ -1187,7 +1187,7 @@ bool Map::isBlockOccluded(MapBlock *block, v3s16 cam_pos_nodes)
|
|||||||
ServerMap
|
ServerMap
|
||||||
*/
|
*/
|
||||||
ServerMap::ServerMap(const std::string &savedir, IGameDef *gamedef,
|
ServerMap::ServerMap(const std::string &savedir, IGameDef *gamedef,
|
||||||
EmergeManager *emerge):
|
EmergeManager *emerge, MetricsBackend *mb):
|
||||||
Map(dout_server, gamedef),
|
Map(dout_server, gamedef),
|
||||||
settings_mgr(g_settings, savedir + DIR_DELIM + "map_meta.txt"),
|
settings_mgr(g_settings, savedir + DIR_DELIM + "map_meta.txt"),
|
||||||
m_emerge(emerge)
|
m_emerge(emerge)
|
||||||
@ -1221,6 +1221,8 @@ ServerMap::ServerMap(const std::string &savedir, IGameDef *gamedef,
|
|||||||
m_savedir = savedir;
|
m_savedir = savedir;
|
||||||
m_map_saving_enabled = false;
|
m_map_saving_enabled = false;
|
||||||
|
|
||||||
|
m_save_time_counter = mb->addCounter("minetest_core_map_save_time", "Map save time (in nanoseconds)");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// If directory exists, check contents and load if possible
|
// If directory exists, check contents and load if possible
|
||||||
if (fs::PathExists(m_savedir)) {
|
if (fs::PathExists(m_savedir)) {
|
||||||
@ -1777,6 +1779,8 @@ void ServerMap::save(ModifiedState save_level)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u64 start_time = porting::getTimeNs();
|
||||||
|
|
||||||
if(save_level == MOD_STATE_CLEAN)
|
if(save_level == MOD_STATE_CLEAN)
|
||||||
infostream<<"ServerMap: Saving whole map, this can take time."
|
infostream<<"ServerMap: Saving whole map, this can take time."
|
||||||
<<std::endl;
|
<<std::endl;
|
||||||
@ -1835,6 +1839,9 @@ void ServerMap::save(ModifiedState save_level)
|
|||||||
infostream<<"Blocks modified by: "<<std::endl;
|
infostream<<"Blocks modified by: "<<std::endl;
|
||||||
modprofiler.print(infostream);
|
modprofiler.print(infostream);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto end_time = porting::getTimeNs();
|
||||||
|
m_save_time_counter->increment(end_time - start_time);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ServerMap::listAllLoadableBlocks(std::vector<v3s16> &dst)
|
void ServerMap::listAllLoadableBlocks(std::vector<v3s16> &dst)
|
||||||
|
@ -31,6 +31,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include "voxel.h"
|
#include "voxel.h"
|
||||||
#include "modifiedstate.h"
|
#include "modifiedstate.h"
|
||||||
#include "util/container.h"
|
#include "util/container.h"
|
||||||
|
#include "util/metricsbackend.h"
|
||||||
#include "nodetimer.h"
|
#include "nodetimer.h"
|
||||||
#include "map_settings_manager.h"
|
#include "map_settings_manager.h"
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
@ -45,6 +46,7 @@ class NodeMetadata;
|
|||||||
class IGameDef;
|
class IGameDef;
|
||||||
class IRollbackManager;
|
class IRollbackManager;
|
||||||
class EmergeManager;
|
class EmergeManager;
|
||||||
|
class MetricsBackend;
|
||||||
class ServerEnvironment;
|
class ServerEnvironment;
|
||||||
struct BlockMakeData;
|
struct BlockMakeData;
|
||||||
|
|
||||||
@ -324,7 +326,7 @@ public:
|
|||||||
/*
|
/*
|
||||||
savedir: directory to which map data should be saved
|
savedir: directory to which map data should be saved
|
||||||
*/
|
*/
|
||||||
ServerMap(const std::string &savedir, IGameDef *gamedef, EmergeManager *emerge);
|
ServerMap(const std::string &savedir, IGameDef *gamedef, EmergeManager *emerge, MetricsBackend *mb);
|
||||||
~ServerMap();
|
~ServerMap();
|
||||||
|
|
||||||
s32 mapType() const
|
s32 mapType() const
|
||||||
@ -449,6 +451,8 @@ private:
|
|||||||
bool m_map_metadata_changed = true;
|
bool m_map_metadata_changed = true;
|
||||||
MapDatabase *dbase = nullptr;
|
MapDatabase *dbase = nullptr;
|
||||||
MapDatabase *dbase_ro = nullptr;
|
MapDatabase *dbase_ro = nullptr;
|
||||||
|
|
||||||
|
MetricCounterPtr m_save_time_counter;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -229,18 +229,46 @@ Server::Server(
|
|||||||
m_nodedef(createNodeDefManager()),
|
m_nodedef(createNodeDefManager()),
|
||||||
m_craftdef(createCraftDefManager()),
|
m_craftdef(createCraftDefManager()),
|
||||||
m_thread(new ServerThread(this)),
|
m_thread(new ServerThread(this)),
|
||||||
m_uptime(0),
|
|
||||||
m_clients(m_con),
|
m_clients(m_con),
|
||||||
m_admin_chat(iface),
|
m_admin_chat(iface),
|
||||||
m_modchannel_mgr(new ModChannelMgr())
|
m_modchannel_mgr(new ModChannelMgr())
|
||||||
{
|
{
|
||||||
m_lag = g_settings->getFloat("dedicated_server_step");
|
|
||||||
|
|
||||||
if (m_path_world.empty())
|
if (m_path_world.empty())
|
||||||
throw ServerError("Supplied empty world path");
|
throw ServerError("Supplied empty world path");
|
||||||
|
|
||||||
if (!gamespec.isValid())
|
if (!gamespec.isValid())
|
||||||
throw ServerError("Supplied invalid gamespec");
|
throw ServerError("Supplied invalid gamespec");
|
||||||
|
|
||||||
|
#if USE_PROMETHEUS
|
||||||
|
m_metrics_backend = std::unique_ptr<MetricsBackend>(createPrometheusMetricsBackend());
|
||||||
|
#else
|
||||||
|
m_metrics_backend = std::unique_ptr<MetricsBackend>(new MetricsBackend());
|
||||||
|
#endif
|
||||||
|
|
||||||
|
m_uptime_counter = m_metrics_backend->addCounter("minetest_core_server_uptime", "Server uptime (in seconds)");
|
||||||
|
m_player_gauge = m_metrics_backend->addGauge("minetest_core_player_number", "Number of connected players");
|
||||||
|
|
||||||
|
m_timeofday_gauge = m_metrics_backend->addGauge(
|
||||||
|
"minetest_core_timeofday",
|
||||||
|
"Time of day value");
|
||||||
|
|
||||||
|
m_lag_gauge = m_metrics_backend->addGauge(
|
||||||
|
"minetest_core_latency",
|
||||||
|
"Latency value (in seconds)");
|
||||||
|
|
||||||
|
m_aom_buffer_counter = m_metrics_backend->addCounter(
|
||||||
|
"minetest_core_aom_generated_count",
|
||||||
|
"Number of active object messages generated");
|
||||||
|
|
||||||
|
m_packet_recv_counter = m_metrics_backend->addCounter(
|
||||||
|
"minetest_core_server_packet_recv",
|
||||||
|
"Processable packets received");
|
||||||
|
|
||||||
|
m_packet_recv_processed_counter = m_metrics_backend->addCounter(
|
||||||
|
"minetest_core_server_packet_recv_processed",
|
||||||
|
"Valid received packets processed");
|
||||||
|
|
||||||
|
m_lag_gauge->set(g_settings->getFloat("dedicated_server_step"));
|
||||||
}
|
}
|
||||||
|
|
||||||
Server::~Server()
|
Server::~Server()
|
||||||
@ -353,7 +381,7 @@ void Server::init()
|
|||||||
MutexAutoLock envlock(m_env_mutex);
|
MutexAutoLock envlock(m_env_mutex);
|
||||||
|
|
||||||
// Create the Map (loads map_meta.txt, overriding configured mapgen params)
|
// Create the Map (loads map_meta.txt, overriding configured mapgen params)
|
||||||
ServerMap *servermap = new ServerMap(m_path_world, this, m_emerge);
|
ServerMap *servermap = new ServerMap(m_path_world, this, m_emerge, m_metrics_backend.get());
|
||||||
|
|
||||||
// Initialize scripting
|
// Initialize scripting
|
||||||
infostream << "Server: Initializing Lua" << std::endl;
|
infostream << "Server: Initializing Lua" << std::endl;
|
||||||
@ -511,9 +539,7 @@ void Server::AsyncRunStep(bool initial_step)
|
|||||||
/*
|
/*
|
||||||
Update uptime
|
Update uptime
|
||||||
*/
|
*/
|
||||||
{
|
m_uptime_counter->increment(dtime);
|
||||||
m_uptime.set(m_uptime.get() + dtime);
|
|
||||||
}
|
|
||||||
|
|
||||||
handlePeerChanges();
|
handlePeerChanges();
|
||||||
|
|
||||||
@ -527,11 +553,13 @@ void Server::AsyncRunStep(bool initial_step)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
m_time_of_day_send_timer -= dtime;
|
m_time_of_day_send_timer -= dtime;
|
||||||
if(m_time_of_day_send_timer < 0.0) {
|
if (m_time_of_day_send_timer < 0.0) {
|
||||||
m_time_of_day_send_timer = g_settings->getFloat("time_send_interval");
|
m_time_of_day_send_timer = g_settings->getFloat("time_send_interval");
|
||||||
u16 time = m_env->getTimeOfDay();
|
u16 time = m_env->getTimeOfDay();
|
||||||
float time_speed = g_settings->getFloat("time_speed");
|
float time_speed = g_settings->getFloat("time_speed");
|
||||||
SendTimeOfDay(PEER_ID_INEXISTENT, time, time_speed);
|
SendTimeOfDay(PEER_ID_INEXISTENT, time, time_speed);
|
||||||
|
|
||||||
|
m_timeofday_gauge->set(time);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -603,7 +631,7 @@ void Server::AsyncRunStep(bool initial_step)
|
|||||||
}
|
}
|
||||||
m_clients.step(dtime);
|
m_clients.step(dtime);
|
||||||
|
|
||||||
m_lag += (m_lag > dtime ? -1 : 1) * dtime/100;
|
m_lag_gauge->increment((m_lag_gauge->get() > dtime ? -1 : 1) * dtime/100);
|
||||||
#if USE_CURL
|
#if USE_CURL
|
||||||
// send masterserver announce
|
// send masterserver announce
|
||||||
{
|
{
|
||||||
@ -614,9 +642,9 @@ void Server::AsyncRunStep(bool initial_step)
|
|||||||
ServerList::AA_START,
|
ServerList::AA_START,
|
||||||
m_bind_addr.getPort(),
|
m_bind_addr.getPort(),
|
||||||
m_clients.getPlayerNames(),
|
m_clients.getPlayerNames(),
|
||||||
m_uptime.get(),
|
m_uptime_counter->get(),
|
||||||
m_env->getGameTime(),
|
m_env->getGameTime(),
|
||||||
m_lag,
|
m_lag_gauge->get(),
|
||||||
m_gamespec.id,
|
m_gamespec.id,
|
||||||
Mapgen::getMapgenName(m_emerge->mgparams->mgtype),
|
Mapgen::getMapgenName(m_emerge->mgparams->mgtype),
|
||||||
m_modmgr->getMods(),
|
m_modmgr->getMods(),
|
||||||
@ -638,6 +666,7 @@ void Server::AsyncRunStep(bool initial_step)
|
|||||||
const RemoteClientMap &clients = m_clients.getClientList();
|
const RemoteClientMap &clients = m_clients.getClientList();
|
||||||
ScopeProfiler sp(g_profiler, "Server: update objects within range");
|
ScopeProfiler sp(g_profiler, "Server: update objects within range");
|
||||||
|
|
||||||
|
m_player_gauge->set(clients.size());
|
||||||
for (const auto &client_it : clients) {
|
for (const auto &client_it : clients) {
|
||||||
RemoteClient *client = client_it.second;
|
RemoteClient *client = client_it.second;
|
||||||
|
|
||||||
@ -703,6 +732,8 @@ void Server::AsyncRunStep(bool initial_step)
|
|||||||
message_list->push_back(aom);
|
message_list->push_back(aom);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_aom_buffer_counter->increment(buffered_messages.size());
|
||||||
|
|
||||||
m_clients.lock();
|
m_clients.lock();
|
||||||
const RemoteClientMap &clients = m_clients.getClientList();
|
const RemoteClientMap &clients = m_clients.getClientList();
|
||||||
// Route data to every client
|
// Route data to every client
|
||||||
@ -943,7 +974,9 @@ void Server::Receive()
|
|||||||
}
|
}
|
||||||
|
|
||||||
peer_id = pkt.getPeerId();
|
peer_id = pkt.getPeerId();
|
||||||
|
m_packet_recv_counter->increment();
|
||||||
ProcessData(&pkt);
|
ProcessData(&pkt);
|
||||||
|
m_packet_recv_processed_counter->increment();
|
||||||
} catch (const con::InvalidIncomingDataException &e) {
|
} catch (const con::InvalidIncomingDataException &e) {
|
||||||
infostream << "Server::Receive(): InvalidIncomingDataException: what()="
|
infostream << "Server::Receive(): InvalidIncomingDataException: what()="
|
||||||
<< e.what() << std::endl;
|
<< e.what() << std::endl;
|
||||||
@ -3127,7 +3160,7 @@ std::wstring Server::getStatusString()
|
|||||||
// Version
|
// Version
|
||||||
os << L"version=" << narrow_to_wide(g_version_string);
|
os << L"version=" << narrow_to_wide(g_version_string);
|
||||||
// Uptime
|
// Uptime
|
||||||
os << L", uptime=" << m_uptime.get();
|
os << L", uptime=" << m_uptime_counter->get();
|
||||||
// Max lag estimate
|
// Max lag estimate
|
||||||
os << L", max_lag=" << (m_env ? m_env->getMaxLagEstimate() : 0);
|
os << L", max_lag=" << (m_env ? m_env->getMaxLagEstimate() : 0);
|
||||||
|
|
||||||
|
21
src/server.h
21
src/server.h
@ -33,6 +33,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include "util/numeric.h"
|
#include "util/numeric.h"
|
||||||
#include "util/thread.h"
|
#include "util/thread.h"
|
||||||
#include "util/basic_macros.h"
|
#include "util/basic_macros.h"
|
||||||
|
#include "util/metricsbackend.h"
|
||||||
#include "serverenvironment.h"
|
#include "serverenvironment.h"
|
||||||
#include "clientiface.h"
|
#include "clientiface.h"
|
||||||
#include "chatmessage.h"
|
#include "chatmessage.h"
|
||||||
@ -203,7 +204,7 @@ public:
|
|||||||
|
|
||||||
// Connection must be locked when called
|
// Connection must be locked when called
|
||||||
std::wstring getStatusString();
|
std::wstring getStatusString();
|
||||||
inline double getUptime() const { return m_uptime.m_value; }
|
inline double getUptime() const { return m_uptime_counter->get(); }
|
||||||
|
|
||||||
// read shutdown state
|
// read shutdown state
|
||||||
inline bool isShutdownRequested() const { return m_shutdown_state.is_requested; }
|
inline bool isShutdownRequested() const { return m_shutdown_state.is_requested; }
|
||||||
@ -591,9 +592,6 @@ private:
|
|||||||
float m_step_dtime = 0.0f;
|
float m_step_dtime = 0.0f;
|
||||||
std::mutex m_step_dtime_mutex;
|
std::mutex m_step_dtime_mutex;
|
||||||
|
|
||||||
// current server step lag counter
|
|
||||||
float m_lag;
|
|
||||||
|
|
||||||
// The server mainly operates in this thread
|
// The server mainly operates in this thread
|
||||||
ServerThread *m_thread = nullptr;
|
ServerThread *m_thread = nullptr;
|
||||||
|
|
||||||
@ -602,8 +600,6 @@ private:
|
|||||||
*/
|
*/
|
||||||
// Timer for sending time of day over network
|
// Timer for sending time of day over network
|
||||||
float m_time_of_day_send_timer = 0.0f;
|
float m_time_of_day_send_timer = 0.0f;
|
||||||
// Uptime of server in seconds
|
|
||||||
MutexedVariable<double> m_uptime;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Client interface
|
Client interface
|
||||||
@ -677,6 +673,19 @@ private:
|
|||||||
|
|
||||||
// ModChannel manager
|
// ModChannel manager
|
||||||
std::unique_ptr<ModChannelMgr> m_modchannel_mgr;
|
std::unique_ptr<ModChannelMgr> m_modchannel_mgr;
|
||||||
|
|
||||||
|
// Global server metrics backend
|
||||||
|
std::unique_ptr<MetricsBackend> m_metrics_backend;
|
||||||
|
|
||||||
|
// Server metrics
|
||||||
|
MetricCounterPtr m_uptime_counter;
|
||||||
|
MetricGaugePtr m_player_gauge;
|
||||||
|
MetricGaugePtr m_timeofday_gauge;
|
||||||
|
// current server step lag
|
||||||
|
MetricGaugePtr m_lag_gauge;
|
||||||
|
MetricCounterPtr m_aom_buffer_counter;
|
||||||
|
MetricCounterPtr m_packet_recv_counter;
|
||||||
|
MetricCounterPtr m_packet_recv_processed_counter;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -23,6 +23,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include "scripting_server.h"
|
#include "scripting_server.h"
|
||||||
#include "content/subgames.h"
|
#include "content/subgames.h"
|
||||||
#include "porting.h"
|
#include "porting.h"
|
||||||
|
#include "util/metricsbackend.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Manage server mods
|
* Manage server mods
|
||||||
|
@ -20,7 +20,10 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "content/mods.h"
|
#include "content/mods.h"
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
class MetricsBackend;
|
||||||
|
class MetricCounter;
|
||||||
class ServerScripting;
|
class ServerScripting;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -5,6 +5,7 @@ set(UTIL_SRCS
|
|||||||
${CMAKE_CURRENT_SOURCE_DIR}/directiontables.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/directiontables.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/enriched_string.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/enriched_string.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/ieee_float.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/ieee_float.cpp
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/metricsbackend.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/numeric.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/numeric.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/pointedthing.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/pointedthing.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/quicktune.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/quicktune.cpp
|
||||||
|
140
src/util/metricsbackend.cpp
Normal file
140
src/util/metricsbackend.cpp
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
/*
|
||||||
|
Minetest
|
||||||
|
Copyright (C) 2013-2020 Minetest core developers team
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License along
|
||||||
|
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "metricsbackend.h"
|
||||||
|
#if USE_PROMETHEUS
|
||||||
|
#include <prometheus/exposer.h>
|
||||||
|
#include <prometheus/registry.h>
|
||||||
|
#include <prometheus/counter.h>
|
||||||
|
#include <prometheus/gauge.h>
|
||||||
|
#include "log.h"
|
||||||
|
#include "settings.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
MetricCounterPtr MetricsBackend::addCounter(
|
||||||
|
const std::string &name, const std::string &help_str)
|
||||||
|
{
|
||||||
|
return std::make_shared<SimpleMetricCounter>(name, help_str);
|
||||||
|
}
|
||||||
|
|
||||||
|
MetricGaugePtr MetricsBackend::addGauge(
|
||||||
|
const std::string &name, const std::string &help_str)
|
||||||
|
{
|
||||||
|
return std::make_shared<SimpleMetricGauge>(name, help_str);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if USE_PROMETHEUS
|
||||||
|
|
||||||
|
class PrometheusMetricCounter : public MetricCounter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PrometheusMetricCounter() = delete;
|
||||||
|
|
||||||
|
PrometheusMetricCounter(const std::string &name, const std::string &help_str,
|
||||||
|
std::shared_ptr<prometheus::Registry> registry) :
|
||||||
|
MetricCounter(),
|
||||||
|
m_family(prometheus::BuildCounter()
|
||||||
|
.Name(name)
|
||||||
|
.Help(help_str)
|
||||||
|
.Register(*registry)),
|
||||||
|
m_counter(m_family.Add({}))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~PrometheusMetricCounter() {}
|
||||||
|
|
||||||
|
virtual void increment(double number) { m_counter.Increment(number); }
|
||||||
|
virtual double get() const { return m_counter.Value(); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
prometheus::Family<prometheus::Counter> &m_family;
|
||||||
|
prometheus::Counter &m_counter;
|
||||||
|
};
|
||||||
|
|
||||||
|
class PrometheusMetricGauge : public MetricGauge
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PrometheusMetricGauge() = delete;
|
||||||
|
|
||||||
|
PrometheusMetricGauge(const std::string &name, const std::string &help_str,
|
||||||
|
std::shared_ptr<prometheus::Registry> registry) :
|
||||||
|
MetricGauge(),
|
||||||
|
m_family(prometheus::BuildGauge()
|
||||||
|
.Name(name)
|
||||||
|
.Help(help_str)
|
||||||
|
.Register(*registry)),
|
||||||
|
m_gauge(m_family.Add({}))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~PrometheusMetricGauge() {}
|
||||||
|
|
||||||
|
virtual void increment(double number) { m_gauge.Increment(number); }
|
||||||
|
virtual void decrement(double number) { m_gauge.Decrement(number); }
|
||||||
|
virtual void set(double number) { m_gauge.Set(number); }
|
||||||
|
virtual double get() const { return m_gauge.Value(); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
prometheus::Family<prometheus::Gauge> &m_family;
|
||||||
|
prometheus::Gauge &m_gauge;
|
||||||
|
};
|
||||||
|
|
||||||
|
class PrometheusMetricsBackend : public MetricsBackend
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PrometheusMetricsBackend(const std::string &addr) :
|
||||||
|
MetricsBackend(), m_exposer(std::unique_ptr<prometheus::Exposer>(
|
||||||
|
new prometheus::Exposer(addr))),
|
||||||
|
m_registry(std::make_shared<prometheus::Registry>())
|
||||||
|
{
|
||||||
|
m_exposer->RegisterCollectable(m_registry);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~PrometheusMetricsBackend() {}
|
||||||
|
|
||||||
|
virtual MetricCounterPtr addCounter(
|
||||||
|
const std::string &name, const std::string &help_str);
|
||||||
|
virtual MetricGaugePtr addGauge(
|
||||||
|
const std::string &name, const std::string &help_str);
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::unique_ptr<prometheus::Exposer> m_exposer;
|
||||||
|
std::shared_ptr<prometheus::Registry> m_registry;
|
||||||
|
};
|
||||||
|
|
||||||
|
MetricCounterPtr PrometheusMetricsBackend::addCounter(
|
||||||
|
const std::string &name, const std::string &help_str)
|
||||||
|
{
|
||||||
|
return std::make_shared<PrometheusMetricCounter>(name, help_str, m_registry);
|
||||||
|
}
|
||||||
|
|
||||||
|
MetricGaugePtr PrometheusMetricsBackend::addGauge(
|
||||||
|
const std::string &name, const std::string &help_str)
|
||||||
|
{
|
||||||
|
return std::make_shared<PrometheusMetricGauge>(name, help_str, m_registry);
|
||||||
|
}
|
||||||
|
|
||||||
|
MetricsBackend *createPrometheusMetricsBackend()
|
||||||
|
{
|
||||||
|
std::string addr;
|
||||||
|
g_settings->getNoEx("prometheus_listener_address", addr);
|
||||||
|
return new PrometheusMetricsBackend(addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
140
src/util/metricsbackend.h
Normal file
140
src/util/metricsbackend.h
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
/*
|
||||||
|
Minetest
|
||||||
|
Copyright (C) 2013-2020 Minetest core developers team
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License along
|
||||||
|
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include <memory>
|
||||||
|
#include "config.h"
|
||||||
|
#include "util/thread.h"
|
||||||
|
|
||||||
|
class MetricCounter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MetricCounter() = default;
|
||||||
|
|
||||||
|
virtual ~MetricCounter() {}
|
||||||
|
|
||||||
|
virtual void increment(double number = 1.0) = 0;
|
||||||
|
virtual double get() const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef std::shared_ptr<MetricCounter> MetricCounterPtr;
|
||||||
|
|
||||||
|
class SimpleMetricCounter : public MetricCounter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SimpleMetricCounter() = delete;
|
||||||
|
|
||||||
|
virtual ~SimpleMetricCounter() {}
|
||||||
|
|
||||||
|
SimpleMetricCounter(const std::string &name, const std::string &help_str) :
|
||||||
|
MetricCounter(), m_name(name), m_help_str(help_str),
|
||||||
|
m_counter(0.0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void increment(double number)
|
||||||
|
{
|
||||||
|
MutexAutoLock lock(m_mutex);
|
||||||
|
m_counter += number;
|
||||||
|
}
|
||||||
|
virtual double get() const
|
||||||
|
{
|
||||||
|
MutexAutoLock lock(m_mutex);
|
||||||
|
return m_counter;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string m_name;
|
||||||
|
std::string m_help_str;
|
||||||
|
|
||||||
|
mutable std::mutex m_mutex;
|
||||||
|
double m_counter;
|
||||||
|
};
|
||||||
|
|
||||||
|
class MetricGauge
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MetricGauge() = default;
|
||||||
|
virtual ~MetricGauge() {}
|
||||||
|
|
||||||
|
virtual void increment(double number = 1.0) = 0;
|
||||||
|
virtual void decrement(double number = 1.0) = 0;
|
||||||
|
virtual void set(double number) = 0;
|
||||||
|
virtual double get() const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef std::shared_ptr<MetricGauge> MetricGaugePtr;
|
||||||
|
|
||||||
|
class SimpleMetricGauge : public MetricGauge
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SimpleMetricGauge() = delete;
|
||||||
|
|
||||||
|
SimpleMetricGauge(const std::string &name, const std::string &help_str) :
|
||||||
|
MetricGauge(), m_name(name), m_help_str(help_str), m_gauge(0.0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~SimpleMetricGauge() {}
|
||||||
|
|
||||||
|
virtual void increment(double number)
|
||||||
|
{
|
||||||
|
MutexAutoLock lock(m_mutex);
|
||||||
|
m_gauge += number;
|
||||||
|
}
|
||||||
|
virtual void decrement(double number)
|
||||||
|
{
|
||||||
|
MutexAutoLock lock(m_mutex);
|
||||||
|
m_gauge -= number;
|
||||||
|
}
|
||||||
|
virtual void set(double number)
|
||||||
|
{
|
||||||
|
MutexAutoLock lock(m_mutex);
|
||||||
|
m_gauge = number;
|
||||||
|
}
|
||||||
|
virtual double get() const
|
||||||
|
{
|
||||||
|
MutexAutoLock lock(m_mutex);
|
||||||
|
return m_gauge;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string m_name;
|
||||||
|
std::string m_help_str;
|
||||||
|
|
||||||
|
mutable std::mutex m_mutex;
|
||||||
|
double m_gauge;
|
||||||
|
};
|
||||||
|
|
||||||
|
class MetricsBackend
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MetricsBackend() = default;
|
||||||
|
|
||||||
|
virtual ~MetricsBackend() {}
|
||||||
|
|
||||||
|
virtual MetricCounterPtr addCounter(
|
||||||
|
const std::string &name, const std::string &help_str);
|
||||||
|
virtual MetricGaugePtr addGauge(
|
||||||
|
const std::string &name, const std::string &help_str);
|
||||||
|
};
|
||||||
|
|
||||||
|
#if USE_PROMETHEUS
|
||||||
|
MetricsBackend *createPrometheusMetricsBackend();
|
||||||
|
#endif
|
13
util/ci/build_prometheus_cpp.sh
Executable file
13
util/ci/build_prometheus_cpp.sh
Executable file
@ -0,0 +1,13 @@
|
|||||||
|
#! /bin/bash -eu
|
||||||
|
|
||||||
|
cd /tmp
|
||||||
|
git clone --recursive https://github.com/jupp0r/prometheus-cpp
|
||||||
|
mkdir prometheus-cpp/build
|
||||||
|
cd prometheus-cpp/build
|
||||||
|
cmake .. \
|
||||||
|
-DCMAKE_INSTALL_PREFIX=/usr/local \
|
||||||
|
-DCMAKE_BUILD_TYPE=Release \
|
||||||
|
-DENABLE_TESTING=0
|
||||||
|
make -j2
|
||||||
|
sudo make install
|
||||||
|
|
Loading…
Reference in New Issue
Block a user