К содержанию

Наблюдаемость

Дашборд, /top, Prometheus, профиль тика и доступ к метрикам.

Открыть на GitHubОбновлено 2026-11-11

Сервер снимает нагрузку раз в секунду и отдаёт её без внешних агентов. Один и тот же снимок доступен из игры, из терминала, в браузере и в Prometheus.

СпособКогда нужен
/top в игрепосмотреть нагрузку из чата, не переключаясь в терминал
chunkwake topразовый снимок или --watch в соседнем окне
GET / в браузереживой дашборд: графики за 15 минут, ядра, мир, сеть
GET /metricsPrometheus и Grafana
GET /snapshotchunkwake top и лаборатория, JSON
GET /api/eventsпоток SSE, которым живёт дашборд
GET /api/profileпрофиль тика по подсистемам, JSON

Дашборд в браузере

http://127.0.0.1:25585/ — та же нагрузка, что в chunkwake top, но с графиками. Страница вшита в бинарник, внешних библиотек и CDN нет, интернет не нужен.

На странице:

  • KPI — TPS за 1/5/15 минут, MSPT (last, p95, p99 и бюджет), загрузка машины и процесса, RSS, игроки, чанки в симуляции.
  • Графики за 15 минут — TPS с линией цели, MSPT с p95 и бюджетом, CPU машины и сервера, RSS, сеть в обе стороны, игроки онлайн.
  • Ядра — полоска на каждое ядро: зелёная до 70 %, жёлтая до 90 %, красная выше.
  • Тик, мир, сеть — те же строки, что в ANSI-таблице chunkwake top.

Данные идут потоком GET /api/events (Server-Sent Events): сервер присылает кадр после каждой публикации снимка, страница ничего не опрашивает. Если поток оборвался, браузер переподключается, а страница подстраховывается /api/snapshot. История — 900 точек по секунде, доступна как GET /api/history, поэтому графики не теряются при перезагрузке.

Дашборд слушает тот же адрес, что и метрики (metrics-bind). По умолчанию это loopback: наружу страница и цифры не уходят.

Доступ и токен

На loopback настройка не нужна: chunkwake top и браузер на этой же машине работают без пароля. Если metrics-bind смотрит в сеть, сервер не запустит эндпоинт без токена и напишет в лог:

ERROR metrics disabled: metrics-bind=0.0.0.0 is reachable from the network,
but metrics-token is empty; set one with `chunkwake config set metrics-token
<long random string>` or bind to 127.0.0.1

Задайте токен длиной не меньше 16 символов, без пробелов:

metrics-bind=0.0.0.0
metrics-token=длинная-случайная-строка

Вход:

  • браузер — откройте http://адрес:25585/?token=... один раз: сервер поставит куку cw_metrics (HttpOnly, SameSite=Strict) и перекинет на / без токена в адресе. Без куки и токена страница покажет форму входа.
  • chunkwake top — читает токен из server.properties и отправляет заголовком Authorization: Bearer.
  • Prometheus — тот же заголовок в scrape_configs.

DNS rebinding закрыт: если браузер прислал Origin, он должен указывать на тот же хост, иначе ответ 403. Токен сравнивается побайтово без раннего выхода, чтобы его нельзя было подобрать по задержке.

Что меряется

Тик. Кольцевой буфер на 18 000 тиков (15 минут): TPS по окнам 1/5/15 минут, средний MSPT за минуту, p50/p95/p99, худший тик и число опоздавших тиков.

Процесс и машина. Загрузка по каждому ядру, средняя по машине, доля процесса в процентах одного ядра, RSS и виртуальная память, память системы.

Мир. Игроки, мобы, предметы, стрелы, сферы опыта, чанки в симуляции и известные миру, очереди редстоуна/жидкостей/воронок, печи, костры, задачи генерации.

Сеть. Байты и пакеты в обе стороны, средний и худший пинг по RTT keep_alive.

Память по частям. CHUNKWAKE_MEMSTATS=1 раз в 10 секунд пишет в лог столбцы в памяти, кэш кадров, мобов и предметов, прото-чанки генератора, кэши высот и раскладок структур. CHUNKWAKE_MEMSTATS_MI=1 добавляет статистику mimalloc после mi_collect.

/top

/top            всё
/top tick       только тик
/top cpu        только процессор
/top mem        память
/top world      мир
/top net        сеть

Каждая строка — отдельный элемент с подсказкой при наведении. Полоска █░ показывает загрузку: зелёная до 70 %, жёлтая до 90 %, красная выше.

chunkwake top

$ chunkwake top --dir ./server
================= My Server · 26.3 · up 02:14:07 =================
── TICK
  rate      20/s  running   ticks 161234
  TPS   now  20.0  1m  19.9  5m  20.0  15m  20.0
  MSPT  last   0.31  1m avg   0.28  p50   0.21  p95   0.60  p99   1.10  max  12.40
  budget  50.0 ms  ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░  0%
...
ФлагПо умолчаниюЧто делает
--dir PATHтекущий каталоггде взять server.properties с metrics-*
--host HOSTmetrics-bindадрес эндпоинта
--port PORTmetrics-portпорт эндпоинта
--watch SEC—перерисовывать каждые SEC секунд
--json—печатать снимок как JSON
--no-color—без ANSI-цветов, для логов

Настройки

metrics-enabled=true
metrics-bind=127.0.0.1
metrics-port=25585
metrics-token=

По умолчанию эндпоинт слушает только loopback. metrics-token нужен только при внешнем metrics-bind.

Страница отдаётся сжатой (gzip), если браузер это умеет: 80 КБ превращаются в 24. Скрытая вкладка закрывает поток и не тянет кадры. Если metrics-port занят, сервер пробует 25586 и 25587 и пишет в лог, на каком порту слушает. chunkwake top перебирает те же три порта.

Prometheus

chunkwake_up
chunkwake_tps{window="1m"|"5m"|"15m"}
chunkwake_tick_rate
chunkwake_tick_frozen
chunkwake_mspt{quantile="0.5"|"0.95"|"0.99"|"max"}
chunkwake_mspt_last
chunkwake_ticks_total
chunkwake_late_ticks_total
chunkwake_process_cpu_percent
chunkwake_process_rss_bytes
chunkwake_process_threads
chunkwake_system_cpu_percent
chunkwake_system_memory_used_bytes
chunkwake_system_memory_total_bytes
chunkwake_cpu_core_percent{core="0"}
chunkwake_players
chunkwake_entities
chunkwake_dropped_items
chunkwake_chunks_simulated
chunkwake_chunks_loaded
chunkwake_chunkgen_pending
chunkwake_network_bytes_total{direction="in"|"out"}
chunkwake_network_packets_total{direction="in"|"out"}
chunkwake_ping_milliseconds
chunkwake_uptime_seconds

Пример prometheus.yml:

scrape_configs:
  - job_name: chunkwake
    static_configs:
      - targets: ["127.0.0.1:25585"]

Профиль тика

/debug start или /perf start пишет в debug/profile-<время>.txt строки тик<TAB>MSPT; /debug stop возвращает путь. Запись ограничена пятью минутами тиков.

Отдельно сервер всегда снимает разбивку тика по подсистемам — как spark, только без стеков:

ГдеЧто видно
GET / → «На что уходит тик»стековая диаграмма по секундам и список групп
chunkwake topсекция PROFILE: группы, ms/тик и доля
GET /api/profileJSON: 900 секунд по { at, ticks, total[18], max[18] }

По умолчанию показываются группы, а не внутренние фазы:

ГруппаЧто внутри
Мобы и животныеИИ, движение, спавн
Хопперы и механизмыпечи, костры, поршни, редстоун, жидкости, плиты
Предметы и снарядыдроп на земле, стрелы, опыт
Отправка игрокампакеты о блоках и позициях
Чанки в симуляциипересчёт чанков рядом с игроками
Плагиныкод плагинов в тике
Служебноечасы мира и прочая мелочь

Точные 18 фаз остаются под переключателем «Подробно» и в JSON. Время показывается в мс на тик, а не суммой за секунду. Замер — одно чтение Instant на фазу и два на тик сверху, поэтому профиль работает всегда, а не только под /debug start.

Чего здесь нет, в отличие от spark: стеков вызовов, конкретных блоков и чанков. Разбивка отвечает на вопрос «куда уходит время тика», а не «какой именно моб тормозит». Разбор внутри подсистемы — /debug start плюс профиль-файл.

Связанное

На этой странице