mirror of
https://gitlab.com/crafty-controller/crafty-4.git
synced 2024-08-30 18:23:09 +00:00
Implementations of Prometheus Client
This commit is contained in:
parent
57dc58099b
commit
eb6d9560f8
@ -3,11 +3,14 @@ import logging
|
|||||||
import datetime
|
import datetime
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
|
|
||||||
|
from prometheus_client import Gauge
|
||||||
|
|
||||||
from app.classes.models.servers import Servers, HelperServers
|
from app.classes.models.servers import Servers, HelperServers
|
||||||
from app.classes.shared.helpers import Helpers
|
from app.classes.shared.helpers import Helpers
|
||||||
from app.classes.shared.main_models import DatabaseShortcuts
|
from app.classes.shared.main_models import DatabaseShortcuts
|
||||||
from app.classes.shared.migration import MigrationManager
|
from app.classes.shared.migration import MigrationManager
|
||||||
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from peewee import (
|
from peewee import (
|
||||||
SqliteDatabase,
|
SqliteDatabase,
|
||||||
@ -29,6 +32,13 @@ logger = logging.getLogger(__name__)
|
|||||||
peewee_logger = logging.getLogger("peewee")
|
peewee_logger = logging.getLogger("peewee")
|
||||||
peewee_logger.setLevel(logging.INFO)
|
peewee_logger.setLevel(logging.INFO)
|
||||||
|
|
||||||
|
# REGISTRY Entries for Server Stats functions
|
||||||
|
ONLINE_PLAYERS = Gauge(
|
||||||
|
name="online_players",
|
||||||
|
documentation="The number of players online for a server",
|
||||||
|
labelnames=["server_id"],
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
# **********************************************************************************
|
# **********************************************************************************
|
||||||
# Servers Stats Class
|
# Servers Stats Class
|
||||||
@ -157,6 +167,8 @@ class HelperServerStats:
|
|||||||
self.database.connect(reuse_if_open=True)
|
self.database.connect(reuse_if_open=True)
|
||||||
server_id = server_stats.get("id", 0)
|
server_id = server_stats.get("id", 0)
|
||||||
|
|
||||||
|
ONLINE_PLAYERS.labels(f"{self.server_id}").set(server_stats.get("online"))
|
||||||
|
|
||||||
if server_id == 0:
|
if server_id == 0:
|
||||||
logger.warning("Stats saving failed with error: Server unknown (id = 0)")
|
logger.warning("Stats saving failed with error: Server unknown (id = 0)")
|
||||||
return
|
return
|
||||||
|
50
app/classes/web/metrics_handler.py
Normal file
50
app/classes/web/metrics_handler.py
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
import logging
|
||||||
|
import typing as t
|
||||||
|
|
||||||
|
from prometheus_client import REGISTRY, CollectorRegistry
|
||||||
|
from prometheus_client.exposition import _bake_output
|
||||||
|
from prometheus_client.exposition import parse_qs, urlparse
|
||||||
|
|
||||||
|
from app.classes.web.base_api_handler import BaseApiHandler
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class BaseMetricsHandler(BaseApiHandler):
|
||||||
|
"""HTTP handler that gives metrics from ``REGISTRY``."""
|
||||||
|
|
||||||
|
registry: CollectorRegistry = REGISTRY
|
||||||
|
|
||||||
|
def get_registry(self) -> None:
|
||||||
|
# Prepare parameters
|
||||||
|
registry = self.registry
|
||||||
|
accept_header = self.request.headers.get("Accept")
|
||||||
|
accept_encoding_header = self.request.headers.get("Accept-Encoding")
|
||||||
|
params = parse_qs(urlparse(self.request.path).query)
|
||||||
|
# Bake output
|
||||||
|
status, headers, output = _bake_output(
|
||||||
|
registry, accept_header, accept_encoding_header, params, False
|
||||||
|
)
|
||||||
|
# Return output
|
||||||
|
self.finish_metrics(int(status.split(" ", maxsplit=1)[0]), headers, output)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def factory(cls, registry: CollectorRegistry) -> type:
|
||||||
|
"""Returns a dynamic MetricsHandler class tied
|
||||||
|
to the passed registry.
|
||||||
|
"""
|
||||||
|
# This implementation relies on MetricsHandler.registry
|
||||||
|
# (defined above and defaulted to REGISTRY).
|
||||||
|
|
||||||
|
# As we have unicode_literals, we need to create a str()
|
||||||
|
# object for type().
|
||||||
|
cls_name = str(cls.__name__)
|
||||||
|
MyMetricsHandler = type(cls_name, (cls, object), {"registry": registry})
|
||||||
|
return MyMetricsHandler
|
||||||
|
|
||||||
|
def finish_metrics(self, status: int, headers, data: t.Dict[str, t.Any]):
|
||||||
|
self.set_status(status)
|
||||||
|
self.set_header("Content-Type", "text/plain")
|
||||||
|
for header in headers:
|
||||||
|
self.set_header(*header)
|
||||||
|
self.finish(data)
|
19
app/classes/web/routes/metrics/index.py
Normal file
19
app/classes/web/routes/metrics/index.py
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
from prometheus_client import Info
|
||||||
|
from app.classes.web.metrics_handler import BaseMetricsHandler
|
||||||
|
|
||||||
|
CRAFTY_INFO = Info("Crafty_Controller", "Infos of this Crafty Instance")
|
||||||
|
|
||||||
|
|
||||||
|
# Decorate function with metric.
|
||||||
|
class ApiOpenMetricsIndexHandler(BaseMetricsHandler):
|
||||||
|
def get(self):
|
||||||
|
auth_data = self.authenticate_user()
|
||||||
|
if not auth_data:
|
||||||
|
return
|
||||||
|
|
||||||
|
version = f"{self.helper.get_version().get('major')}.{self.helper.get_version().get('minor')}.{self.helper.get_version().get('sub')}"
|
||||||
|
CRAFTY_INFO.info(
|
||||||
|
{"version": version, "docker": f"{self.helper.is_env_docker()}"}
|
||||||
|
)
|
||||||
|
|
||||||
|
self.get_registry()
|
18
app/classes/web/routes/metrics/metrics_handlers.py
Normal file
18
app/classes/web/routes/metrics/metrics_handlers.py
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
from app.classes.web.routes.metrics.index import ApiOpenMetricsIndexHandler
|
||||||
|
from app.classes.web.routes.metrics.servers import ApiOpenMetricsServersHandler
|
||||||
|
|
||||||
|
|
||||||
|
def metrics_handlers(handler_args):
|
||||||
|
return [
|
||||||
|
# OpenMetrics routes
|
||||||
|
(
|
||||||
|
r"/metrics?",
|
||||||
|
ApiOpenMetricsIndexHandler,
|
||||||
|
handler_args,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
r"/metrics/servers/(0-9)+?",
|
||||||
|
ApiOpenMetricsServersHandler,
|
||||||
|
handler_args,
|
||||||
|
),
|
||||||
|
]
|
12
app/classes/web/routes/metrics/servers.py
Normal file
12
app/classes/web/routes/metrics/servers.py
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
from prometheus_client import Histogram
|
||||||
|
from app.classes.web.metrics_handler import BaseMetricsHandler
|
||||||
|
|
||||||
|
|
||||||
|
# Decorate function with metric.
|
||||||
|
class ApiOpenMetricsServersHandler(BaseMetricsHandler):
|
||||||
|
def get(self):
|
||||||
|
auth_data = self.authenticate_user()
|
||||||
|
if not auth_data:
|
||||||
|
return
|
||||||
|
|
||||||
|
self.get_registry()
|
@ -20,6 +20,7 @@ from app.classes.web.public_handler import PublicHandler
|
|||||||
from app.classes.web.panel_handler import PanelHandler
|
from app.classes.web.panel_handler import PanelHandler
|
||||||
from app.classes.web.default_handler import DefaultHandler
|
from app.classes.web.default_handler import DefaultHandler
|
||||||
from app.classes.web.routes.api.api_handlers import api_handlers
|
from app.classes.web.routes.api.api_handlers import api_handlers
|
||||||
|
from app.classes.web.routes.metrics.metrics_handlers import metrics_handlers
|
||||||
from app.classes.web.server_handler import ServerHandler
|
from app.classes.web.server_handler import ServerHandler
|
||||||
from app.classes.web.ajax_handler import AjaxHandler
|
from app.classes.web.ajax_handler import AjaxHandler
|
||||||
from app.classes.web.api_handler import (
|
from app.classes.web.api_handler import (
|
||||||
@ -169,6 +170,8 @@ class Webserver:
|
|||||||
(r"/api/v1/users/delete_user", DeleteUser, handler_args),
|
(r"/api/v1/users/delete_user", DeleteUser, handler_args),
|
||||||
# API Routes V2
|
# API Routes V2
|
||||||
*api_handlers(handler_args),
|
*api_handlers(handler_args),
|
||||||
|
# API Routes OpenMetrics
|
||||||
|
*metrics_handlers(handler_args),
|
||||||
# Using this one at the end
|
# Using this one at the end
|
||||||
# to catch all the other requests to Public Handler
|
# to catch all the other requests to Public Handler
|
||||||
(r"/(.*)", PublicHandler, handler_args),
|
(r"/(.*)", PublicHandler, handler_args),
|
||||||
|
@ -9,7 +9,7 @@ cryptography==41.0.1
|
|||||||
libgravatar==1.0.0
|
libgravatar==1.0.0
|
||||||
peewee==3.13
|
peewee==3.13
|
||||||
pexpect==4.8
|
pexpect==4.8
|
||||||
psutil==5.9
|
psutil==5.9.5
|
||||||
pyOpenSSL==23.2.0
|
pyOpenSSL==23.2.0
|
||||||
pyjwt==2.4.0
|
pyjwt==2.4.0
|
||||||
PyYAML==6.0.1
|
PyYAML==6.0.1
|
||||||
@ -19,3 +19,4 @@ tornado==6.3.2
|
|||||||
tzlocal==4.0
|
tzlocal==4.0
|
||||||
jsonschema==4.5.1
|
jsonschema==4.5.1
|
||||||
orjson==3.8.12
|
orjson==3.8.12
|
||||||
|
prometheus-client==0.17.1
|
||||||
|
Loading…
Reference in New Issue
Block a user