mirror of
https://github.com/Cockatrice/Cockatrice.git
synced 2026-09-23 18:06:26 -07:00
[Server] Instrument command processing, game starts, and event loops
Add a lock-free MetricsRegistry that accumulates per-command processing times in preallocated histogram slots (one per protobuf command type, bucketed at 1/5/10/25/50/100/250/500/1000/2500/5000 ms +Inf). The hot-path observeCommand() uses only relaxed atomic adds — no locks, no allocations, no cache-line ping-pong beyond the unavoidable counter updates. Wire the registry into AbstractServerSocketInterface::processCommandContainer() so every processed command is attributed with its container's wall-clock time. When a container exceeds metrics/slow_command_ms (default 500), a warning is logged including the connected username. Add an EventLoopWatchdog heartbeat that runs on every socket pool thread. If a heartbeat overshoots metrics/stall_warn_ms (default 2000 ms), the overshoot is recorded in atomic counters and a warning is logged. Both thresholds are configurable in servatrice.ini; setting stall_warn_ms to 0 disables the watchdogs entirely. Track game-start durations via a separate histogram in MetricsRegistry. Server_Game::startGameNow() measures the time from zone creation through player materialization and reports it via Server::observeGameStartDurationMs(). Add a live card-count gauge: Server_Game exposes getCardsInGame() and Servatrice::getCardsInGamesTotal() sums across all running games under the appropriate read locks. Include a standalone metrics_registry_test (Google Test) that validates empty registries, single/multi-sample histograms, kind encoding, overflow-slot collapse, negative-duration clamping, gauge rendering, and the game-start histogram separation. Took 10 minutes
This commit is contained in:
parent
ab243cc499
commit
b4b409a575
18 changed files with 749 additions and 1 deletions
50
servatrice/src/event_loop_watchdog.h
Normal file
50
servatrice/src/event_loop_watchdog.h
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
/**
|
||||
* @file event_loop_watchdog.h
|
||||
* @ingroup Servatrice
|
||||
*/
|
||||
|
||||
#ifndef EVENT_LOOP_WATCHDOG_H
|
||||
#define EVENT_LOOP_WATCHDOG_H
|
||||
|
||||
#include <QElapsedTimer>
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
|
||||
class Servatrice;
|
||||
class QTimer;
|
||||
|
||||
/**
|
||||
* @brief Detects blocked or overloaded worker event loops.
|
||||
*
|
||||
* One instance lives in each socket pool thread. A heartbeat timer tick that
|
||||
* arrives late means the loop spent that time elsewhere: busy work, a queued
|
||||
* slot, or a hard wedge. Overshoots past the configured threshold bump
|
||||
* lock-free counters on the metrics registry and log one warning per stall,
|
||||
* so a stuck pool thread becomes visible instead of silent lag.
|
||||
*/
|
||||
class EventLoopWatchdog : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
/// How often the heartbeat expects to fire. Small enough to catch short stalls.
|
||||
static constexpr int HeartbeatIntervalMs = 500;
|
||||
|
||||
EventLoopWatchdog(Servatrice *_servatrice, QString _threadName);
|
||||
|
||||
/**
|
||||
* Starts the heartbeat timer. Must be invoked queued after the instance
|
||||
* was moved to its target thread so the timer lives there too.
|
||||
*/
|
||||
void start();
|
||||
|
||||
private slots:
|
||||
void checkHeartbeat();
|
||||
|
||||
private:
|
||||
Servatrice *servatrice;
|
||||
QString threadName;
|
||||
QElapsedTimer sinceLastTick;
|
||||
QTimer *heartbeatTimer = nullptr;
|
||||
};
|
||||
|
||||
#endif
|
||||
Loading…
Add table
Add a link
Reference in a new issue