Skip to content

Commit

Permalink
Add MetricsBackend with prometheus counter support
Browse files Browse the repository at this point in the history
  • Loading branch information
nerzhul committed Apr 29, 2020
1 parent a36c9c3 commit 56babab
Show file tree
Hide file tree
Showing 16 changed files with 427 additions and 25 deletions.
22 changes: 18 additions & 4 deletions Dockerfile
Expand Up @@ -21,15 +21,29 @@ WORKDIR /usr/src/minetest
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 \
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 && \
rm -fr ./games/minetest_game/.git && \
mkdir build && \
rm -fr ./games/minetest_game/.git

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 && \
cmake .. \
-DCMAKE_INSTALL_PREFIX=/usr/local \
-DCMAKE_BUILD_TYPE=Release \
-DBUILD_SERVER=TRUE \
-DENABLE_PROMETHEUS=TRUE \
-DBUILD_UNITTESTS=FALSE \
-DBUILD_CLIENT=FALSE && \
make -j2 && \
Expand All @@ -49,6 +63,6 @@ COPY --from=0 /usr/local/share/doc/minetest/minetest.conf.example /etc/minetest/

USER minetest:minetest

EXPOSE 30000/udp
EXPOSE 30000/udp 30000/tcp

CMD ["/usr/local/bin/minetestserver", "--config", "/etc/minetest/minetest.conf"]
1 change: 1 addition & 0 deletions README.md
Expand Up @@ -236,6 +236,7 @@ General options and their default values:
ENABLE_SPATIAL=ON - Build with LibSpatial; Speeds up AreaStores
ENABLE_SOUND=ON - Build with OpenAL, libogg & libvorbis; in-game sounds
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_JSONCPP=OFF - Use JsonCPP from system
OPENGL_GL_PREFERENCE=LEGACY - Linux client build only; See CMake Policy CMP0072 for reference
Expand Down
6 changes: 6 additions & 0 deletions builtin/settingtypes.txt
Expand Up @@ -955,6 +955,12 @@ address (Server address) string
# Note that the port field in the main menu overrides this setting.
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.
enable_local_map_saving (Saving map received from server) bool false

Expand Down
26 changes: 26 additions & 0 deletions src/CMakeLists.txt
Expand Up @@ -217,6 +217,26 @@ endif(ENABLE_REDIS)

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)
set(USE_SPATIAL FALSE)

Expand Down Expand Up @@ -597,6 +617,9 @@ if(BUILD_CLIENT)
if (USE_REDIS)
target_link_libraries(${PROJECT_NAME} ${REDIS_LIBRARY})
endif()
if (USE_PROMETHEUS)
target_link_libraries(${PROJECT_NAME} ${PROMETHEUS_LIBRARIES})
endif()
if (USE_SPATIAL)
target_link_libraries(${PROJECT_NAME} ${SPATIAL_LIBRARY})
endif()
Expand Down Expand Up @@ -632,6 +655,9 @@ if(BUILD_SERVER)
if (USE_REDIS)
target_link_libraries(${PROJECT_NAME}server ${REDIS_LIBRARY})
endif()
if (USE_PROMETHEUS)
target_link_libraries(${PROJECT_NAME}server ${PROMETHEUS_LIBRARIES})
endif()
if (USE_SPATIAL)
target_link_libraries(${PROJECT_NAME}server ${SPATIAL_LIBRARY})
endif()
Expand Down
1 change: 1 addition & 0 deletions src/cmake_config.h.in
Expand Up @@ -23,6 +23,7 @@
#cmakedefine01 USE_LEVELDB
#cmakedefine01 USE_LUAJIT
#cmakedefine01 USE_POSTGRESQL
#cmakedefine01 USE_PROMETHEUS
#cmakedefine01 USE_SPATIAL
#cmakedefine01 USE_SYSTEM_GMP
#cmakedefine01 USE_REDIS
Expand Down
3 changes: 3 additions & 0 deletions src/defaultsettings.cpp
Expand Up @@ -334,6 +334,9 @@ void set_default_settings(Settings *settings)
// Server
settings->setDefault("disable_escape_sequences", "false");
settings->setDefault("strip_color_codes", "false");
#if USE_PROMETHEUS
settings->setDefault("prometheus_listener_address", "127.0.0.1:30000");
#endif

// Network
settings->setDefault("enable_ipv6", "true");
Expand Down
11 changes: 9 additions & 2 deletions src/map.cpp
Expand Up @@ -144,7 +144,7 @@ bool Map::isNodeUnderground(v3s16 p)
{
v3s16 blockpos = getNodeBlockPos(p);
MapBlock *block = getBlockNoCreateNoEx(blockpos);
return block && block->getIsUnderground();
return block && block->getIsUnderground();
}

bool Map::isValidPosition(v3s16 p)
Expand Down Expand Up @@ -1187,7 +1187,7 @@ bool Map::isBlockOccluded(MapBlock *block, v3s16 cam_pos_nodes)
ServerMap
*/
ServerMap::ServerMap(const std::string &savedir, IGameDef *gamedef,
EmergeManager *emerge):
EmergeManager *emerge, MetricsBackend *mb):
Map(dout_server, gamedef),
settings_mgr(g_settings, savedir + DIR_DELIM + "map_meta.txt"),
m_emerge(emerge)
Expand Down Expand Up @@ -1221,6 +1221,8 @@ ServerMap::ServerMap(const std::string &savedir, IGameDef *gamedef,
m_savedir = savedir;
m_map_saving_enabled = false;

m_save_time_counter = mb->addCounter("minetest_core_map_save_time", "Map save time (in nanoseconds)");

try {
// If directory exists, check contents and load if possible
if (fs::PathExists(m_savedir)) {
Expand Down Expand Up @@ -1777,6 +1779,8 @@ void ServerMap::save(ModifiedState save_level)
return;
}

u64 start_time = porting::getTimeNs();

if(save_level == MOD_STATE_CLEAN)
infostream<<"ServerMap: Saving whole map, this can take time."
<<std::endl;
Expand Down Expand Up @@ -1835,6 +1839,9 @@ void ServerMap::save(ModifiedState save_level)
infostream<<"Blocks modified by: "<<std::endl;
modprofiler.print(infostream);
}

auto end_time = porting::getTimeNs();
m_save_time_counter->increment(end_time - start_time);
}

void ServerMap::listAllLoadableBlocks(std::vector<v3s16> &dst)
Expand Down
6 changes: 5 additions & 1 deletion src/map.h
Expand Up @@ -31,6 +31,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "voxel.h"
#include "modifiedstate.h"
#include "util/container.h"
#include "util/metricsbackend.h"
#include "nodetimer.h"
#include "map_settings_manager.h"
#include "debug.h"
Expand All @@ -45,6 +46,7 @@ class NodeMetadata;
class IGameDef;
class IRollbackManager;
class EmergeManager;
class MetricsBackend;
class ServerEnvironment;
struct BlockMakeData;

Expand Down Expand Up @@ -324,7 +326,7 @@ class ServerMap : public Map
/*
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();

s32 mapType() const
Expand Down Expand Up @@ -449,6 +451,8 @@ class ServerMap : public Map
bool m_map_metadata_changed = true;
MapDatabase *dbase = nullptr;
MapDatabase *dbase_ro = nullptr;

MetricCounterPtr m_save_time_counter;
};


Expand Down
57 changes: 45 additions & 12 deletions src/server.cpp
Expand Up @@ -229,18 +229,46 @@ Server::Server(
m_nodedef(createNodeDefManager()),
m_craftdef(createCraftDefManager()),
m_thread(new ServerThread(this)),
m_uptime(0),
m_clients(m_con),
m_admin_chat(iface),
m_modchannel_mgr(new ModChannelMgr())
{
m_lag = g_settings->getFloat("dedicated_server_step");

if (m_path_world.empty())
throw ServerError("Supplied empty world path");

if (!gamespec.isValid())
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()
Expand Down Expand Up @@ -353,7 +381,7 @@ void Server::init()
MutexAutoLock envlock(m_env_mutex);

// 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
infostream << "Server: Initializing Lua" << std::endl;
Expand Down Expand Up @@ -511,9 +539,7 @@ void Server::AsyncRunStep(bool initial_step)
/*
Update uptime
*/
{
m_uptime.set(m_uptime.get() + dtime);
}
m_uptime_counter->increment(dtime);

handlePeerChanges();

Expand All @@ -527,11 +553,13 @@ void Server::AsyncRunStep(bool initial_step)
*/

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");
u16 time = m_env->getTimeOfDay();
float time_speed = g_settings->getFloat("time_speed");
SendTimeOfDay(PEER_ID_INEXISTENT, time, time_speed);

m_timeofday_gauge->set(time);
}

{
Expand Down Expand Up @@ -603,7 +631,7 @@ void Server::AsyncRunStep(bool initial_step)
}
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
// send masterserver announce
{
Expand All @@ -614,9 +642,9 @@ void Server::AsyncRunStep(bool initial_step)
ServerList::AA_START,
m_bind_addr.getPort(),
m_clients.getPlayerNames(),
m_uptime.get(),
m_uptime_counter->get(),
m_env->getGameTime(),
m_lag,
m_lag_gauge->get(),
m_gamespec.id,
Mapgen::getMapgenName(m_emerge->mgparams->mgtype),
m_modmgr->getMods(),
Expand All @@ -638,6 +666,7 @@ void Server::AsyncRunStep(bool initial_step)
const RemoteClientMap &clients = m_clients.getClientList();
ScopeProfiler sp(g_profiler, "Server: update objects within range");

m_player_gauge->set(clients.size());
for (const auto &client_it : clients) {
RemoteClient *client = client_it.second;

Expand Down Expand Up @@ -703,6 +732,8 @@ void Server::AsyncRunStep(bool initial_step)
message_list->push_back(aom);
}

m_aom_buffer_counter->increment(buffered_messages.size());

m_clients.lock();
const RemoteClientMap &clients = m_clients.getClientList();
// Route data to every client
Expand Down Expand Up @@ -943,7 +974,9 @@ void Server::Receive()
}

peer_id = pkt.getPeerId();
m_packet_recv_counter->increment();
ProcessData(&pkt);
m_packet_recv_processed_counter->increment();
} catch (const con::InvalidIncomingDataException &e) {
infostream << "Server::Receive(): InvalidIncomingDataException: what()="
<< e.what() << std::endl;
Expand Down Expand Up @@ -3127,7 +3160,7 @@ std::wstring Server::getStatusString()
// Version
os << L"version=" << narrow_to_wide(g_version_string);
// Uptime
os << L", uptime=" << m_uptime.get();
os << L", uptime=" << m_uptime_counter->get();
// Max lag estimate
os << L", max_lag=" << (m_env ? m_env->getMaxLagEstimate() : 0);

Expand Down

0 comments on commit 56babab

Please sign in to comment.