Skip to content

Commit 56babab

Browse files
committedApr 29, 2020
Add MetricsBackend with prometheus counter support
1 parent a36c9c3 commit 56babab

16 files changed

+427
-25
lines changed
 

Diff for: ‎Dockerfile

+18-4
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,29 @@ WORKDIR /usr/src/minetest
2121
RUN apk add --no-cache git build-base irrlicht-dev cmake bzip2-dev libpng-dev \
2222
jpeg-dev libxxf86vm-dev mesa-dev sqlite-dev libogg-dev \
2323
libvorbis-dev openal-soft-dev curl-dev freetype-dev zlib-dev \
24-
gmp-dev jsoncpp-dev postgresql-dev && \
24+
gmp-dev jsoncpp-dev postgresql-dev ca-certificates && \
2525
git clone --depth=1 -b ${MINETEST_GAME_VERSION} https://github.com/minetest/minetest_game.git ./games/minetest_game && \
26-
rm -fr ./games/minetest_game/.git && \
27-
mkdir build && \
26+
rm -fr ./games/minetest_game/.git
27+
28+
WORKDIR /usr/src/
29+
RUN git clone --recursive https://github.com/jupp0r/prometheus-cpp/ && \
30+
mkdir prometheus-cpp/build && \
31+
cd prometheus-cpp/build && \
32+
cmake .. \
33+
-DCMAKE_INSTALL_PREFIX=/usr/local \
34+
-DCMAKE_BUILD_TYPE=Release \
35+
-DENABLE_TESTING=0 && \
36+
make -j2 && \
37+
make install
38+
39+
WORKDIR /usr/src/minetest
40+
RUN mkdir build && \
2841
cd build && \
2942
cmake .. \
3043
-DCMAKE_INSTALL_PREFIX=/usr/local \
3144
-DCMAKE_BUILD_TYPE=Release \
3245
-DBUILD_SERVER=TRUE \
46+
-DENABLE_PROMETHEUS=TRUE \
3347
-DBUILD_UNITTESTS=FALSE \
3448
-DBUILD_CLIENT=FALSE && \
3549
make -j2 && \
@@ -49,6 +63,6 @@ COPY --from=0 /usr/local/share/doc/minetest/minetest.conf.example /etc/minetest/
4963

5064
USER minetest:minetest
5165

52-
EXPOSE 30000/udp
66+
EXPOSE 30000/udp 30000/tcp
5367

5468
CMD ["/usr/local/bin/minetestserver", "--config", "/etc/minetest/minetest.conf"]

Diff for: ‎README.md

+1
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,7 @@ General options and their default values:
236236
ENABLE_SPATIAL=ON - Build with LibSpatial; Speeds up AreaStores
237237
ENABLE_SOUND=ON - Build with OpenAL, libogg & libvorbis; in-game sounds
238238
ENABLE_LUAJIT=ON - Build with LuaJIT (much faster than non-JIT Lua)
239+
ENABLE_PROMETHEUS=OFF - Build with Prometheus metrics exporter (listens on tcp/30000 by default)
239240
ENABLE_SYSTEM_GMP=ON - Use GMP from system (much faster than bundled mini-gmp)
240241
ENABLE_SYSTEM_JSONCPP=OFF - Use JsonCPP from system
241242
OPENGL_GL_PREFERENCE=LEGACY - Linux client build only; See CMake Policy CMP0072 for reference

Diff for: ‎builtin/settingtypes.txt

+6
Original file line numberDiff line numberDiff line change
@@ -955,6 +955,12 @@ address (Server address) string
955955
# Note that the port field in the main menu overrides this setting.
956956
remote_port (Remote port) int 30000 1 65535
957957

958+
# Prometheus listener address.
959+
# If minetest is compiled with ENABLE_PROMETHEUS option enabled,
960+
# enable metrics listener for Prometheus on that address.
961+
# Metrics can be fetch on http://127.0.0.1:30000/metrics
962+
prometheus_listener_address (Prometheus listener address) string 127.0.0.1:30000
963+
958964
# Save the map received by the client on disk.
959965
enable_local_map_saving (Saving map received from server) bool false
960966

Diff for: ‎src/CMakeLists.txt

+26
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,26 @@ endif(ENABLE_REDIS)
217217

218218
find_package(SQLite3 REQUIRED)
219219

220+
OPTION(ENABLE_PROMETHEUS "Enable prometheus client support" FALSE)
221+
set(USE_PROMETHEUS FALSE)
222+
223+
if(ENABLE_PROMETHEUS)
224+
find_path(PROMETHEUS_CPP_INCLUDE_DIR NAMES prometheus/counter.h)
225+
find_library(PROMETHEUS_PULL_LIBRARY NAMES prometheus-cpp-pull)
226+
find_library(PROMETHEUS_CORE_LIBRARY NAMES prometheus-cpp-core)
227+
if(PROMETHEUS_CPP_INCLUDE_DIR AND PROMETHEUS_PULL_LIBRARY AND PROMETHEUS_CORE_LIBRARY)
228+
set(PROMETHEUS_LIBRARIES ${PROMETHEUS_PULL_LIBRARY} ${PROMETHEUS_CORE_LIBRARY})
229+
set(USE_PROMETHEUS TRUE)
230+
include_directories(${PROMETHEUS_CPP_INCLUDE_DIR})
231+
endif(PROMETHEUS_CPP_INCLUDE_DIR AND PROMETHEUS_PULL_LIBRARY AND PROMETHEUS_CORE_LIBRARY)
232+
endif(ENABLE_PROMETHEUS)
233+
234+
if(USE_PROMETHEUS)
235+
message(STATUS "Prometheus client enabled.")
236+
else(USE_PROMETHEUS)
237+
message(STATUS "Prometheus client disabled.")
238+
endif(USE_PROMETHEUS)
239+
220240
OPTION(ENABLE_SPATIAL "Enable SpatialIndex AreaStore backend" TRUE)
221241
set(USE_SPATIAL FALSE)
222242

@@ -597,6 +617,9 @@ if(BUILD_CLIENT)
597617
if (USE_REDIS)
598618
target_link_libraries(${PROJECT_NAME} ${REDIS_LIBRARY})
599619
endif()
620+
if (USE_PROMETHEUS)
621+
target_link_libraries(${PROJECT_NAME} ${PROMETHEUS_LIBRARIES})
622+
endif()
600623
if (USE_SPATIAL)
601624
target_link_libraries(${PROJECT_NAME} ${SPATIAL_LIBRARY})
602625
endif()
@@ -632,6 +655,9 @@ if(BUILD_SERVER)
632655
if (USE_REDIS)
633656
target_link_libraries(${PROJECT_NAME}server ${REDIS_LIBRARY})
634657
endif()
658+
if (USE_PROMETHEUS)
659+
target_link_libraries(${PROJECT_NAME}server ${PROMETHEUS_LIBRARIES})
660+
endif()
635661
if (USE_SPATIAL)
636662
target_link_libraries(${PROJECT_NAME}server ${SPATIAL_LIBRARY})
637663
endif()

Diff for: ‎src/cmake_config.h.in

+1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#cmakedefine01 USE_LEVELDB
2424
#cmakedefine01 USE_LUAJIT
2525
#cmakedefine01 USE_POSTGRESQL
26+
#cmakedefine01 USE_PROMETHEUS
2627
#cmakedefine01 USE_SPATIAL
2728
#cmakedefine01 USE_SYSTEM_GMP
2829
#cmakedefine01 USE_REDIS

Diff for: ‎src/defaultsettings.cpp

+3
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,9 @@ void set_default_settings(Settings *settings)
334334
// Server
335335
settings->setDefault("disable_escape_sequences", "false");
336336
settings->setDefault("strip_color_codes", "false");
337+
#if USE_PROMETHEUS
338+
settings->setDefault("prometheus_listener_address", "127.0.0.1:30000");
339+
#endif
337340

338341
// Network
339342
settings->setDefault("enable_ipv6", "true");

Diff for: ‎src/map.cpp

+9-2
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ bool Map::isNodeUnderground(v3s16 p)
144144
{
145145
v3s16 blockpos = getNodeBlockPos(p);
146146
MapBlock *block = getBlockNoCreateNoEx(blockpos);
147-
return block && block->getIsUnderground();
147+
return block && block->getIsUnderground();
148148
}
149149

150150
bool Map::isValidPosition(v3s16 p)
@@ -1187,7 +1187,7 @@ bool Map::isBlockOccluded(MapBlock *block, v3s16 cam_pos_nodes)
11871187
ServerMap
11881188
*/
11891189
ServerMap::ServerMap(const std::string &savedir, IGameDef *gamedef,
1190-
EmergeManager *emerge):
1190+
EmergeManager *emerge, MetricsBackend *mb):
11911191
Map(dout_server, gamedef),
11921192
settings_mgr(g_settings, savedir + DIR_DELIM + "map_meta.txt"),
11931193
m_emerge(emerge)
@@ -1221,6 +1221,8 @@ ServerMap::ServerMap(const std::string &savedir, IGameDef *gamedef,
12211221
m_savedir = savedir;
12221222
m_map_saving_enabled = false;
12231223

1224+
m_save_time_counter = mb->addCounter("minetest_core_map_save_time", "Map save time (in nanoseconds)");
1225+
12241226
try {
12251227
// If directory exists, check contents and load if possible
12261228
if (fs::PathExists(m_savedir)) {
@@ -1777,6 +1779,8 @@ void ServerMap::save(ModifiedState save_level)
17771779
return;
17781780
}
17791781

1782+
u64 start_time = porting::getTimeNs();
1783+
17801784
if(save_level == MOD_STATE_CLEAN)
17811785
infostream<<"ServerMap: Saving whole map, this can take time."
17821786
<<std::endl;
@@ -1835,6 +1839,9 @@ void ServerMap::save(ModifiedState save_level)
18351839
infostream<<"Blocks modified by: "<<std::endl;
18361840
modprofiler.print(infostream);
18371841
}
1842+
1843+
auto end_time = porting::getTimeNs();
1844+
m_save_time_counter->increment(end_time - start_time);
18381845
}
18391846

18401847
void ServerMap::listAllLoadableBlocks(std::vector<v3s16> &dst)

Diff for: ‎src/map.h

+5-1
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
3131
#include "voxel.h"
3232
#include "modifiedstate.h"
3333
#include "util/container.h"
34+
#include "util/metricsbackend.h"
3435
#include "nodetimer.h"
3536
#include "map_settings_manager.h"
3637
#include "debug.h"
@@ -45,6 +46,7 @@ class NodeMetadata;
4546
class IGameDef;
4647
class IRollbackManager;
4748
class EmergeManager;
49+
class MetricsBackend;
4850
class ServerEnvironment;
4951
struct BlockMakeData;
5052

@@ -324,7 +326,7 @@ class ServerMap : public Map
324326
/*
325327
savedir: directory to which map data should be saved
326328
*/
327-
ServerMap(const std::string &savedir, IGameDef *gamedef, EmergeManager *emerge);
329+
ServerMap(const std::string &savedir, IGameDef *gamedef, EmergeManager *emerge, MetricsBackend *mb);
328330
~ServerMap();
329331

330332
s32 mapType() const
@@ -449,6 +451,8 @@ class ServerMap : public Map
449451
bool m_map_metadata_changed = true;
450452
MapDatabase *dbase = nullptr;
451453
MapDatabase *dbase_ro = nullptr;
454+
455+
MetricCounterPtr m_save_time_counter;
452456
};
453457

454458

Diff for: ‎src/server.cpp

+45-12
Original file line numberDiff line numberDiff line change
@@ -229,18 +229,46 @@ Server::Server(
229229
m_nodedef(createNodeDefManager()),
230230
m_craftdef(createCraftDefManager()),
231231
m_thread(new ServerThread(this)),
232-
m_uptime(0),
233232
m_clients(m_con),
234233
m_admin_chat(iface),
235234
m_modchannel_mgr(new ModChannelMgr())
236235
{
237-
m_lag = g_settings->getFloat("dedicated_server_step");
238-
239236
if (m_path_world.empty())
240237
throw ServerError("Supplied empty world path");
241238

242239
if (!gamespec.isValid())
243240
throw ServerError("Supplied invalid gamespec");
241+
242+
#if USE_PROMETHEUS
243+
m_metrics_backend = std::unique_ptr<MetricsBackend>(createPrometheusMetricsBackend());
244+
#else
245+
m_metrics_backend = std::unique_ptr<MetricsBackend>(new MetricsBackend());
246+
#endif
247+
248+
m_uptime_counter = m_metrics_backend->addCounter("minetest_core_server_uptime", "Server uptime (in seconds)");
249+
m_player_gauge = m_metrics_backend->addGauge("minetest_core_player_number", "Number of connected players");
250+
251+
m_timeofday_gauge = m_metrics_backend->addGauge(
252+
"minetest_core_timeofday",
253+
"Time of day value");
254+
255+
m_lag_gauge = m_metrics_backend->addGauge(
256+
"minetest_core_latency",
257+
"Latency value (in seconds)");
258+
259+
m_aom_buffer_counter = m_metrics_backend->addCounter(
260+
"minetest_core_aom_generated_count",
261+
"Number of active object messages generated");
262+
263+
m_packet_recv_counter = m_metrics_backend->addCounter(
264+
"minetest_core_server_packet_recv",
265+
"Processable packets received");
266+
267+
m_packet_recv_processed_counter = m_metrics_backend->addCounter(
268+
"minetest_core_server_packet_recv_processed",
269+
"Valid received packets processed");
270+
271+
m_lag_gauge->set(g_settings->getFloat("dedicated_server_step"));
244272
}
245273

246274
Server::~Server()
@@ -353,7 +381,7 @@ void Server::init()
353381
MutexAutoLock envlock(m_env_mutex);
354382

355383
// Create the Map (loads map_meta.txt, overriding configured mapgen params)
356-
ServerMap *servermap = new ServerMap(m_path_world, this, m_emerge);
384+
ServerMap *servermap = new ServerMap(m_path_world, this, m_emerge, m_metrics_backend.get());
357385

358386
// Initialize scripting
359387
infostream << "Server: Initializing Lua" << std::endl;
@@ -511,9 +539,7 @@ void Server::AsyncRunStep(bool initial_step)
511539
/*
512540
Update uptime
513541
*/
514-
{
515-
m_uptime.set(m_uptime.get() + dtime);
516-
}
542+
m_uptime_counter->increment(dtime);
517543

518544
handlePeerChanges();
519545

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

529555
m_time_of_day_send_timer -= dtime;
530-
if(m_time_of_day_send_timer < 0.0) {
556+
if (m_time_of_day_send_timer < 0.0) {
531557
m_time_of_day_send_timer = g_settings->getFloat("time_send_interval");
532558
u16 time = m_env->getTimeOfDay();
533559
float time_speed = g_settings->getFloat("time_speed");
534560
SendTimeOfDay(PEER_ID_INEXISTENT, time, time_speed);
561+
562+
m_timeofday_gauge->set(time);
535563
}
536564

537565
{
@@ -603,7 +631,7 @@ void Server::AsyncRunStep(bool initial_step)
603631
}
604632
m_clients.step(dtime);
605633

606-
m_lag += (m_lag > dtime ? -1 : 1) * dtime/100;
634+
m_lag_gauge->increment((m_lag_gauge->get() > dtime ? -1 : 1) * dtime/100);
607635
#if USE_CURL
608636
// send masterserver announce
609637
{
@@ -614,9 +642,9 @@ void Server::AsyncRunStep(bool initial_step)
614642
ServerList::AA_START,
615643
m_bind_addr.getPort(),
616644
m_clients.getPlayerNames(),
617-
m_uptime.get(),
645+
m_uptime_counter->get(),
618646
m_env->getGameTime(),
619-
m_lag,
647+
m_lag_gauge->get(),
620648
m_gamespec.id,
621649
Mapgen::getMapgenName(m_emerge->mgparams->mgtype),
622650
m_modmgr->getMods(),
@@ -638,6 +666,7 @@ void Server::AsyncRunStep(bool initial_step)
638666
const RemoteClientMap &clients = m_clients.getClientList();
639667
ScopeProfiler sp(g_profiler, "Server: update objects within range");
640668

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

@@ -703,6 +732,8 @@ void Server::AsyncRunStep(bool initial_step)
703732
message_list->push_back(aom);
704733
}
705734

735+
m_aom_buffer_counter->increment(buffered_messages.size());
736+
706737
m_clients.lock();
707738
const RemoteClientMap &clients = m_clients.getClientList();
708739
// Route data to every client
@@ -943,7 +974,9 @@ void Server::Receive()
943974
}
944975

945976
peer_id = pkt.getPeerId();
977+
m_packet_recv_counter->increment();
946978
ProcessData(&pkt);
979+
m_packet_recv_processed_counter->increment();
947980
} catch (const con::InvalidIncomingDataException &e) {
948981
infostream << "Server::Receive(): InvalidIncomingDataException: what()="
949982
<< e.what() << std::endl;
@@ -3127,7 +3160,7 @@ std::wstring Server::getStatusString()
31273160
// Version
31283161
os << L"version=" << narrow_to_wide(g_version_string);
31293162
// Uptime
3130-
os << L", uptime=" << m_uptime.get();
3163+
os << L", uptime=" << m_uptime_counter->get();
31313164
// Max lag estimate
31323165
os << L", max_lag=" << (m_env ? m_env->getMaxLagEstimate() : 0);
31333166

Diff for: ‎src/server.h

+15-6
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
3333
#include "util/numeric.h"
3434
#include "util/thread.h"
3535
#include "util/basic_macros.h"
36+
#include "util/metricsbackend.h"
3637
#include "serverenvironment.h"
3738
#include "clientiface.h"
3839
#include "chatmessage.h"
@@ -203,7 +204,7 @@ class Server : public con::PeerHandler, public MapEventReceiver,
203204

204205
// Connection must be locked when called
205206
std::wstring getStatusString();
206-
inline double getUptime() const { return m_uptime.m_value; }
207+
inline double getUptime() const { return m_uptime_counter->get(); }
207208

208209
// read shutdown state
209210
inline bool isShutdownRequested() const { return m_shutdown_state.is_requested; }
@@ -591,9 +592,6 @@ class Server : public con::PeerHandler, public MapEventReceiver,
591592
float m_step_dtime = 0.0f;
592593
std::mutex m_step_dtime_mutex;
593594

594-
// current server step lag counter
595-
float m_lag;
596-
597595
// The server mainly operates in this thread
598596
ServerThread *m_thread = nullptr;
599597

@@ -602,8 +600,6 @@ class Server : public con::PeerHandler, public MapEventReceiver,
602600
*/
603601
// Timer for sending time of day over network
604602
float m_time_of_day_send_timer = 0.0f;
605-
// Uptime of server in seconds
606-
MutexedVariable<double> m_uptime;
607603

608604
/*
609605
Client interface
@@ -677,6 +673,19 @@ class Server : public con::PeerHandler, public MapEventReceiver,
677673

678674
// ModChannel manager
679675
std::unique_ptr<ModChannelMgr> m_modchannel_mgr;
676+
677+
// Global server metrics backend
678+
std::unique_ptr<MetricsBackend> m_metrics_backend;
679+
680+
// Server metrics
681+
MetricCounterPtr m_uptime_counter;
682+
MetricGaugePtr m_player_gauge;
683+
MetricGaugePtr m_timeofday_gauge;
684+
// current server step lag
685+
MetricGaugePtr m_lag_gauge;
686+
MetricCounterPtr m_aom_buffer_counter;
687+
MetricCounterPtr m_packet_recv_counter;
688+
MetricCounterPtr m_packet_recv_processed_counter;
680689
};
681690

682691
/*

Diff for: ‎src/server/mods.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
2323
#include "scripting_server.h"
2424
#include "content/subgames.h"
2525
#include "porting.h"
26+
#include "util/metricsbackend.h"
2627

2728
/**
2829
* Manage server mods

Diff for: ‎src/server/mods.h

+3
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,10 @@ with this program; if not, write to the Free Software Foundation, Inc.,
2020
#pragma once
2121

2222
#include "content/mods.h"
23+
#include <memory>
2324

25+
class MetricsBackend;
26+
class MetricCounter;
2427
class ServerScripting;
2528

2629
/**

Diff for: ‎src/util/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ set(UTIL_SRCS
55
${CMAKE_CURRENT_SOURCE_DIR}/directiontables.cpp
66
${CMAKE_CURRENT_SOURCE_DIR}/enriched_string.cpp
77
${CMAKE_CURRENT_SOURCE_DIR}/ieee_float.cpp
8+
${CMAKE_CURRENT_SOURCE_DIR}/metricsbackend.cpp
89
${CMAKE_CURRENT_SOURCE_DIR}/numeric.cpp
910
${CMAKE_CURRENT_SOURCE_DIR}/pointedthing.cpp
1011
${CMAKE_CURRENT_SOURCE_DIR}/quicktune.cpp

Diff for: ‎src/util/metricsbackend.cpp

+140
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
/*
2+
Minetest
3+
Copyright (C) 2013-2020 Minetest core developers team
4+
5+
This program is free software; you can redistribute it and/or modify
6+
it under the terms of the GNU Lesser General Public License as published by
7+
the Free Software Foundation; either version 2.1 of the License, or
8+
(at your option) any later version.
9+
10+
This program is distributed in the hope that it will be useful,
11+
but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
GNU Lesser General Public License for more details.
14+
15+
You should have received a copy of the GNU Lesser General Public License along
16+
with this program; if not, write to the Free Software Foundation, Inc.,
17+
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18+
*/
19+
20+
#include "metricsbackend.h"
21+
#if USE_PROMETHEUS
22+
#include <prometheus/exposer.h>
23+
#include <prometheus/registry.h>
24+
#include <prometheus/counter.h>
25+
#include <prometheus/gauge.h>
26+
#include "log.h"
27+
#include "settings.h"
28+
#endif
29+
30+
MetricCounterPtr MetricsBackend::addCounter(
31+
const std::string &name, const std::string &help_str)
32+
{
33+
return std::make_shared<SimpleMetricCounter>(name, help_str);
34+
}
35+
36+
MetricGaugePtr MetricsBackend::addGauge(
37+
const std::string &name, const std::string &help_str)
38+
{
39+
return std::make_shared<SimpleMetricGauge>(name, help_str);
40+
}
41+
42+
#if USE_PROMETHEUS
43+
44+
class PrometheusMetricCounter : public MetricCounter
45+
{
46+
public:
47+
PrometheusMetricCounter() = delete;
48+
49+
PrometheusMetricCounter(const std::string &name, const std::string &help_str,
50+
std::shared_ptr<prometheus::Registry> registry) :
51+
MetricCounter(),
52+
m_family(prometheus::BuildCounter()
53+
.Name(name)
54+
.Help(help_str)
55+
.Register(*registry)),
56+
m_counter(m_family.Add({}))
57+
{
58+
}
59+
60+
virtual ~PrometheusMetricCounter() {}
61+
62+
virtual void increment(double number) { m_counter.Increment(number); }
63+
virtual double get() const { return m_counter.Value(); }
64+
65+
private:
66+
prometheus::Family<prometheus::Counter> &m_family;
67+
prometheus::Counter &m_counter;
68+
};
69+
70+
class PrometheusMetricGauge : public MetricGauge
71+
{
72+
public:
73+
PrometheusMetricGauge() = delete;
74+
75+
PrometheusMetricGauge(const std::string &name, const std::string &help_str,
76+
std::shared_ptr<prometheus::Registry> registry) :
77+
MetricGauge(),
78+
m_family(prometheus::BuildGauge()
79+
.Name(name)
80+
.Help(help_str)
81+
.Register(*registry)),
82+
m_gauge(m_family.Add({}))
83+
{
84+
}
85+
86+
virtual ~PrometheusMetricGauge() {}
87+
88+
virtual void increment(double number) { m_gauge.Increment(number); }
89+
virtual void decrement(double number) { m_gauge.Decrement(number); }
90+
virtual void set(double number) { m_gauge.Set(number); }
91+
virtual double get() const { return m_gauge.Value(); }
92+
93+
private:
94+
prometheus::Family<prometheus::Gauge> &m_family;
95+
prometheus::Gauge &m_gauge;
96+
};
97+
98+
class PrometheusMetricsBackend : public MetricsBackend
99+
{
100+
public:
101+
PrometheusMetricsBackend(const std::string &addr) :
102+
MetricsBackend(), m_exposer(std::unique_ptr<prometheus::Exposer>(
103+
new prometheus::Exposer(addr))),
104+
m_registry(std::make_shared<prometheus::Registry>())
105+
{
106+
m_exposer->RegisterCollectable(m_registry);
107+
}
108+
109+
virtual ~PrometheusMetricsBackend() {}
110+
111+
virtual MetricCounterPtr addCounter(
112+
const std::string &name, const std::string &help_str);
113+
virtual MetricGaugePtr addGauge(
114+
const std::string &name, const std::string &help_str);
115+
116+
private:
117+
std::unique_ptr<prometheus::Exposer> m_exposer;
118+
std::shared_ptr<prometheus::Registry> m_registry;
119+
};
120+
121+
MetricCounterPtr PrometheusMetricsBackend::addCounter(
122+
const std::string &name, const std::string &help_str)
123+
{
124+
return std::make_shared<PrometheusMetricCounter>(name, help_str, m_registry);
125+
}
126+
127+
MetricGaugePtr PrometheusMetricsBackend::addGauge(
128+
const std::string &name, const std::string &help_str)
129+
{
130+
return std::make_shared<PrometheusMetricGauge>(name, help_str, m_registry);
131+
}
132+
133+
MetricsBackend *createPrometheusMetricsBackend()
134+
{
135+
std::string addr;
136+
g_settings->getNoEx("prometheus_listener_address", addr);
137+
return new PrometheusMetricsBackend(addr);
138+
}
139+
140+
#endif

Diff for: ‎src/util/metricsbackend.h

+140
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
/*
2+
Minetest
3+
Copyright (C) 2013-2020 Minetest core developers team
4+
5+
This program is free software; you can redistribute it and/or modify
6+
it under the terms of the GNU Lesser General Public License as published by
7+
the Free Software Foundation; either version 2.1 of the License, or
8+
(at your option) any later version.
9+
10+
This program is distributed in the hope that it will be useful,
11+
but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
GNU Lesser General Public License for more details.
14+
15+
You should have received a copy of the GNU Lesser General Public License along
16+
with this program; if not, write to the Free Software Foundation, Inc.,
17+
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18+
*/
19+
20+
#pragma once
21+
#include <memory>
22+
#include "config.h"
23+
#include "util/thread.h"
24+
25+
class MetricCounter
26+
{
27+
public:
28+
MetricCounter() = default;
29+
30+
virtual ~MetricCounter() {}
31+
32+
virtual void increment(double number = 1.0) = 0;
33+
virtual double get() const = 0;
34+
};
35+
36+
typedef std::shared_ptr<MetricCounter> MetricCounterPtr;
37+
38+
class SimpleMetricCounter : public MetricCounter
39+
{
40+
public:
41+
SimpleMetricCounter() = delete;
42+
43+
virtual ~SimpleMetricCounter() {}
44+
45+
SimpleMetricCounter(const std::string &name, const std::string &help_str) :
46+
MetricCounter(), m_name(name), m_help_str(help_str),
47+
m_counter(0.0)
48+
{
49+
}
50+
51+
virtual void increment(double number)
52+
{
53+
MutexAutoLock lock(m_mutex);
54+
m_counter += number;
55+
}
56+
virtual double get() const
57+
{
58+
MutexAutoLock lock(m_mutex);
59+
return m_counter;
60+
}
61+
62+
private:
63+
std::string m_name;
64+
std::string m_help_str;
65+
66+
mutable std::mutex m_mutex;
67+
double m_counter;
68+
};
69+
70+
class MetricGauge
71+
{
72+
public:
73+
MetricGauge() = default;
74+
virtual ~MetricGauge() {}
75+
76+
virtual void increment(double number = 1.0) = 0;
77+
virtual void decrement(double number = 1.0) = 0;
78+
virtual void set(double number) = 0;
79+
virtual double get() const = 0;
80+
};
81+
82+
typedef std::shared_ptr<MetricGauge> MetricGaugePtr;
83+
84+
class SimpleMetricGauge : public MetricGauge
85+
{
86+
public:
87+
SimpleMetricGauge() = delete;
88+
89+
SimpleMetricGauge(const std::string &name, const std::string &help_str) :
90+
MetricGauge(), m_name(name), m_help_str(help_str), m_gauge(0.0)
91+
{
92+
}
93+
94+
virtual ~SimpleMetricGauge() {}
95+
96+
virtual void increment(double number)
97+
{
98+
MutexAutoLock lock(m_mutex);
99+
m_gauge += number;
100+
}
101+
virtual void decrement(double number)
102+
{
103+
MutexAutoLock lock(m_mutex);
104+
m_gauge -= number;
105+
}
106+
virtual void set(double number)
107+
{
108+
MutexAutoLock lock(m_mutex);
109+
m_gauge = number;
110+
}
111+
virtual double get() const
112+
{
113+
MutexAutoLock lock(m_mutex);
114+
return m_gauge;
115+
}
116+
117+
private:
118+
std::string m_name;
119+
std::string m_help_str;
120+
121+
mutable std::mutex m_mutex;
122+
double m_gauge;
123+
};
124+
125+
class MetricsBackend
126+
{
127+
public:
128+
MetricsBackend() = default;
129+
130+
virtual ~MetricsBackend() {}
131+
132+
virtual MetricCounterPtr addCounter(
133+
const std::string &name, const std::string &help_str);
134+
virtual MetricGaugePtr addGauge(
135+
const std::string &name, const std::string &help_str);
136+
};
137+
138+
#if USE_PROMETHEUS
139+
MetricsBackend *createPrometheusMetricsBackend();
140+
#endif

Diff for: ‎util/ci/build_prometheus_cpp.sh

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#! /bin/bash -eu
2+
3+
cd /tmp
4+
git clone --recursive https://github.com/jupp0r/prometheus-cpp
5+
mkdir prometheus-cpp/build
6+
cd prometheus-cpp/build
7+
cmake .. \
8+
-DCMAKE_INSTALL_PREFIX=/usr/local \
9+
-DCMAKE_BUILD_TYPE=Release \
10+
-DENABLE_TESTING=0
11+
make -j2
12+
sudo make install
13+

0 commit comments

Comments
 (0)
Please sign in to comment.