Brazil's biggest MU Online portal — since 2003
Tutorial Advanced Infra

How to build a real-time metrics dashboard for your MU Online server

Build a real-time metrics dashboard to monitor online players, uptime, CPU/RAM usage, slow queries, and your MU Online server's economy, using periodic collection, a time-series database, and a web panel for visualization.

BR Bruno · Updated on May 15, 2024 · ⏱ 17 min read
Quick answer

Running a MU Online server "in the dark" — with no visibility into how many players are online right now, whether the database is under stress, or whether the economy is inflating — is like flying without instruments. A real-time metrics dashboard turns operational decisions (when to scale hardware,

Running a MU Online server "in the dark" — with no visibility into how many players are online right now, whether the database is under stress, or whether the economy is inflating — is like flying without instruments. A real-time metrics dashboard turns operational decisions (when to scale hardware, when to review a drop rate, when to investigate lag) from guesswork into hard data. This tutorial walks through building a complete dashboard: from collecting system and game metrics, through time-series storage, to visualization in a web panel and automatic alerts.

What's worth measuring

Before picking a tool, define what the dashboard needs to answer. A solid set of metrics for a MU server covers three layers:

LayerMetricsSuggested frequency
InfrastructureCPU, RAM, disk, network, service uptime5-15 seconds
Game serverPlayers online, ConnectServer connections, average latency15-30 seconds
Economy/gameZen in circulation, Excellent items dropped/hour, resets/day5-15 minutes

Infrastructure and game server metrics need high frequency because they change fast; economy metrics are aggregated and change slowly, so collecting every minute is already more than enough.

Prerequisites

  • A MU server already running and configured.
  • Access to the emulator's database (MSSQL or MySQL, depending on the emulator).
  • A machine/VM (or the host itself) to run the monitoring stack.
  • Basic scripting knowledge (PowerShell, Python, or Node.js) for the collectors.

Step 1 — Choose the monitoring stack

Two common routes:

  • Ready-made stack (Prometheus + Grafana): Prometheus collects and stores time series; Grafana visualizes them. Steeper learning curve, but extremely extensible with native alerting.
  • Lightweight custom panel: a collector script periodically writes metrics to a SQL table, and a simple web page (PHP/Node) queries and displays them via charts (Chart.js). Faster to set up, less flexible long-term.

For small/medium servers, start with the custom panel; migrate to Prometheus/Grafana once metric volume justifies it.

Step 2 — Create the time-series table (custom route)

CREATE TABLE metrics_snapshot (
    id INT IDENTITY PRIMARY KEY,
    captured_at DATETIME NOT NULL DEFAULT GETDATE(),
    players_online INT NOT NULL,
    cpu_percent DECIMAL(5,2),
    ram_percent DECIMAL(5,2),
    zen_total BIGINT,
    excellent_drops_last_hour INT
);

This table grows fast if collected every few seconds — plan a cleanup routine (e.g., keep fine granularity for 7 days and aggregate into hourly averages afterward).

Step 3 — Write the infrastructure collector

A simple PowerShell (Windows) collector that writes CPU and RAM every 15 seconds:

while ($true) {
    $cpu = (Get-Counter '\Processor(_Total)\% Processor Time').CounterSamples.CookedValue
    $ram = (Get-CimInstance Win32_OperatingSystem)
    $ramPercent = 100 - ($ram.FreePhysicalMemory / $ram.TotalVisibleMemorySize * 100)

    Invoke-Sqlcmd -Query "INSERT INTO metrics_snapshot (cpu_percent, ram_percent) VALUES ($cpu, $ramPercent)"
    Start-Sleep -Seconds 15
}

Run it as a service/scheduled task to make sure collection survives reboots.

Step 4 — Write the game metrics collector

Query the emulator's own connected accounts/characters table (the table/column name varies by emulator — usually something like MEMB_STAT or a connection flag in Character):

SELECT COUNT(*) AS players_online FROM MEMB_STAT WHERE ConnectStat = 1;

Store this value together with the aggregated economy (sum of Zen, count of Excellent drops in the last hour via the item log, if your emulator logs that).

Step 5 — Build the visualization (web panel)

A simple page querying the metrics_snapshot table and rendering it with Chart.js:

fetch('/api/metrics?range=1h')
  .then(r => r.json())
  .then(data => {
    new Chart(document.getElementById('grafico-online'), {
      type: 'line',
      data: {
        labels: data.map(d => d.captured_at),
        datasets: [{ label: 'Players Online', data: data.map(d => d.players_online) }]
      }
    });
  });

Build separate panels for: online count over the day, CPU/RAM, and economy (Zen in circulation, Excellent drops).

Step 6 — Add healthcheck and alerts

Set up a script that tests the ConnectServer/GameServer port every minute and fires a webhook to Discord if the check fails 3 times in a row (avoiding false alerts from momentary network instability):

$falhas = 0
while ($true) {
    $ok = Test-NetConnection -ComputerName "127.0.0.1" -Port 44405 -InformationLevel Quiet
    if (-not $ok) {
        $falhas++
        if ($falhas -ge 3) {
            Invoke-RestMethod -Uri $webhookDiscord -Method Post -Body (@{content="⚠️ GameServer is down!"} | ConvertTo-Json) -ContentType 'application/json'
        }
    } else { $falhas = 0 }
    Start-Sleep -Seconds 60
}

Step 7 — Monitor slow database queries

Enable your DBMS's slow query log (slow query log in MySQL, Query Store in SQL Server) and add a panel to the dashboard showing the slowest queries in the last hour. This often reveals bottlenecks before they turn into lag players can feel, especially during peak hours.

Step 8 — Define data retention and aggregation

Without a retention policy, the metrics table grows indefinitely. A reasonable scheme: keep 15-second granularity for 48h, aggregate into 5-minute averages for 30 days, and aggregate into daily averages indefinitely for long-term historical analysis.

Step 9 — Restrict access to sensitive data

Split the dashboard into two layers: a public (or semi-public, on the site) one with aggregated metrics (total online, uptime, current season) for community transparency, and an authenticated administrative one with sensitive details (IPs, specific accounts, individual logs).

Common errors and fixes

SymptomLikely causeFix
Metrics table grows uncontrollablyNo retention/aggregation policyImplement periodic cleanup and aggregation
Dashboard freezes or gets slowHeavy queries directly on the raw tableUse aggregated views or short-term caching
False alerts about the server being downSingle check with no tolerance for network failuresRequire N consecutive failures before alerting
Collection impacts GameServer performanceOverly aggressive collection frequencyReduce frequency for heavy metrics (economy)
Sensitive data exposed publiclySingle panel with no access separationSeparate the public (aggregated) panel from the admin one

Deployment checklist

  • Infrastructure, game, and economy metrics defined and prioritized.
  • Time-series table/stack created with a retention plan.
  • System and game collectors running as a persistent service.
  • Visualization panel built with charts for the key metrics.
  • Healthcheck with webhook alerting configured and tested.
  • Slow query monitoring enabled on the database.
  • Separation between public (aggregated) and admin (detailed) panels.

With the dashboard live, you can make hardware scaling, economy tuning, and maintenance-window decisions based on real data instead of intuition — the next step is reviewing the server's base configuration described in the server creation tutorial in light of what the dashboard's numbers are revealing.

Frequently asked questions

Do I need Grafana, or can I build a simpler dashboard?

Grafana is the most robust free option, but for small servers, a custom web panel querying the database every few seconds (via AJAX/polling) already gets the job done. The choice depends on how much time you want to invest maintaining the tool.

Does collecting metrics every second overload the server?

Collecting every 1 second for heavy metrics (like counting online characters via a full query) can indeed generate unnecessary load. It's recommended to collect system metrics (CPU/RAM) every 5-15s and game metrics every 30-60s.

How do I monitor slow database queries?

Most DBMSs (MySQL/MSSQL) have a native slow query log (slow query log in MySQL, Query Store in SQL Server) that can be enabled and then consumed by your dashboard or by tools like Percona Toolkit.

Can I get automatic alerts when the server goes down?

Yes. Set up a healthcheck that periodically tests the GameServer/ConnectServer port and fires a webhook (Discord, Telegram) when the check fails N times in a row, avoiding false alerts from a single network hiccup.

Does the dashboard expose sensitive data if it's public?

It can, if you include individual player data (IP, email) without anonymization. Keep the public dashboard limited to aggregated metrics (total online, uptime, overall economy) and restrict detailed data to an authenticated admin panel.

BR
Events, maps & items editor

Bruno specializes in MU Online events, maps, bosses and item economy. He documents every detail based on real gameplay.

Keep reading

Related articles