feat(settings): блок «Статус стека» — на чём всё крутится
На странице Настроек появился блок с состоянием стека системы: версии компонентов, состояние сервисов и нагрузка. Рендерится из нового блока stack в ответе GET /api/system-info, в том же стиле, что и соседний блок системной информации (sys-card / sys-item / sys-bar, точки worker-dot, полосы загрузки и памяти с порогами 70 % и 90 %). Карточки: Приложение (версия и коммит, Node.js, PID и RSS, аптайм, куча, сворачиваемый список библиотек), Сервер (ОС, ядро, архитектура и число ядер, модель CPU, loadavg, память, аптайм, контейнер), База данных (PostgreSQL и версия, хост, состояние пула), Кэш (драйвер, версия Redis, ключи, память, попадания и промахи, операций в памяти) и Хранилище (драйвер, endpoint, бакет или каталог). - server.js: getStackInfo() — версии из package.json, node_modules и public/version.json, ОС из /etc/os-release, определение Docker, SHOW server_version, счётчики пула pg, состояние Redis. Считается вне cacheWrap, чтобы версии и нагрузка не отдавались из 30-секундного кэша; хосты только через URL.hostname, без учётных данных URL - settings.html: карточка sec-stack и пункт «Стек» в навигации - settings.js: renderStackInfo(), форматирование аптаймов с русскими склонениями, degrade-состояние «нет связи — в памяти»; кнопка обновления перезагружает оба блока одним запросом - admin.css: .sys-inline для точки статуса рядом с текстом - api.smoketest.js: контракт блока stack и проверка, что в ответе нет учётных данных из DATABASE_URL/REDIS_URL
This commit is contained in:
@@ -91,6 +91,10 @@ async function main() {
|
||||
ok('system-info', info.status === 200, info.status);
|
||||
ok('system-info reports redis driver', info.data && info.data.cache && info.data.cache.driver === 'redis', info.data && info.data.cache);
|
||||
ok('system-info reports cache hits', info.data && info.data.cache && info.data.cache.hits > 0, info.data && info.data.cache && info.data.cache.hits);
|
||||
const stack = info.data && info.data.stack;
|
||||
ok('system-info reports stack', Boolean(stack && stack.app && stack.runtime && stack.database && stack.cache && stack.storage), stack);
|
||||
ok('stack reports node and postgres version', Boolean(stack && stack.app.node && stack.database.version), stack && { node: stack.app.node, pg: stack.database.version });
|
||||
ok('stack never leaks credentials', !/:\/\/[^"@/]*@/.test(JSON.stringify(stack)), stack && stack.database.host, stack && stack.cache.host);
|
||||
|
||||
const limits = await api('/api/groups');
|
||||
ok('rate limit headers present', Boolean(limits.headers.get('ratelimit-limit')), {
|
||||
|
||||
Reference in New Issue
Block a user