System Info і діагностика¶
Сторінка Інформація (бокова панель → Інформація, route /system) — це адмін-діагностична поверхня BamDude — version metadata, DB row counts, storage breakdown, log viewer, debug-logging toggle, support bundle generator і кнопки maintenance (optimize DB, rebuild search index, check for updates).
Що це¶
Read-only дашборд, що тягне з GET /api/v1/system/info (більшість сторінки), GET /api/v1/system/storage-usage (storage breakdown) і GET /api/v1/support/logs (log viewer). Maintenance-actions — POST endpoint-и за відповідними permission-ами. Усе живе в running BamDude-процесі — зовнішня metrics-БД не потрібна (для цього див. Prometheus).
Version info¶
| Поле | Source |
|---|---|
version |
APP_VERSION з backend/app/core/config.py, ставиться при build-time через node scripts/set_version.js. |
python_version |
Версія Python interpreter running-процесу. |
| Database engine + version | SHOW server_version на PostgreSQL, SELECT sqlite_version() на SQLite. |
platform / architecture / hostname |
З Python-модуля platform. |
boot_time / uptime |
System boot time з psutil, форматоване в Nd Nh Nm. |
Build date і git SHA через цей endpoint не експонуються — release-білди печуть version string при set_version.js time, це канонічний ідентифікатор. Node version теж не репортиться; React-bundle шипиться pre-built під static/.
Database stats¶
GET /api/v1/system/info агрегує row counts і кілька sum-ів:
| Stat | Що рахує |
|---|---|
archives |
Загальна кількість рядків print_archives. |
archives_completed / archives_failed / archives_printing |
Те саме, partition за status. |
printers |
Усі зареєстровані принтери. |
spools |
Усі spool-records (live inventory rows). |
projects |
Усі projects. |
smart_plugs |
Усі зареєстровані smart-plug-и. |
total_print_time_seconds / _formatted |
Сума print_time_seconds крізь усі архіви. |
total_filament_grams / _kg |
Сума filament_used_grams. |
database.size (під storage) |
Розмір файлу bambuddy.db або PostgreSQL DB size, якщо PG. |
Storage usage breakdown¶
GET /api/v1/system/storage-usage ходить по data-директоріях і класифікує кожен файл в один з buckets, повертаючи size + percentage of total:
| Bucket | Roots |
|---|---|
database |
bambuddy.db (і legacy bambutrack.db, якщо є). |
library_thumbnails / library_files / library_other |
<data_dir>/library/.... |
archive_files / archive_thumbnails / archive_timelapses |
Сама archive-директорія. |
virtual_printer_uploads / virtual_printer_upload_cache / virtual_printer_certs / virtual_printer_other |
<base_dir>/virtual_printer/.... |
downloads |
<base_dir>/firmware/. |
attachments |
<data_dir>/projects/ і <data_dir>/products/ — вкладення замовлень і виробів. |
plate_calibration |
Директорія plate-detection reference image. |
logs |
Сконфігурована log-директорія. |
other_data |
Все під data-теками, що не зматчилось правилом, з per-bucket sub-breakdown, що відрізняє system (deletable=false) від data (deletable=true). |
Scan кешується на 5 хвилин (STORAGE_USAGE_CACHE_SECONDS = 300). Передай ?refresh=true, щоб форсити re-scan; передай max_age_seconds=N (clamped 0–3600), щоб override-нути cache TTL.
Дивись перед backup-ом
Окидаючи поглядом breakdown перед backup, бачиш — чи archive-тека є домінантною часткою (зазвичай так), і чи є headroom тримати timelapse-и, чи прунити їх спочатку.
Resource usage¶
| Stat | Source |
|---|---|
| CPU count + percent | psutil.cpu_count() / psutil.cpu_percent(interval=0.1). |
| Memory total / available / used / percent | psutil.virtual_memory(). |
| Disk total / used / free / percent | psutil.disk_usage(base_dir). |
connected_printers |
Live MQTT-connected принтери з printer_manager. |
Значення — point-in-time — refresh сторінки re-семплить їх. Historical rollup тут немає. Для time-series скрейпай Prometheus.
Log viewer¶
GET /api/v1/support/logs тейлить <log_dir>/bamdude.log, парсить кожен рядок у структурований entry, і повертає найсвіжіші entry-ї першими.
| Param | Замітки |
|---|---|
limit |
1–1000, default 200. |
level |
DEBUG, INFO, WARNING або ERROR. Case-insensitive. |
search |
Substring-match по message body і logger name. Case-insensitive. |
Multi-line entry-ї (особливо stack traces) пересобираються — continuation-рядок прикріплюється до next-parsed entry над ним.
| Дія | Endpoint | Permission |
|---|---|---|
| List recent logs | GET /api/v1/support/logs |
settings:read |
| Truncate log-файл | DELETE /api/v1/support/logs |
settings:update |
| Toggle DEBUG-level logging | POST /api/v1/support/debug-logging |
settings:update |
DEBUG-level logging gated
Helper _apply_log_level пінить httpcore і httpx на WARNING навіть у DEBUG mode — full request URL logging would leak bearer-токени в Discord / generic-webhook URL-ах. paho.mqtt перемикається на DEBUG, коли toggle on — там і живе більшість корисного printer-protocol detail.
Ротація + retention логів¶
Активний файл bamdude.log ротується під час першого запису після опівночі за локальним часом сервера. Архіви — звичайні текстові файли bamdude-YYYY-MM-DD.log. Перезапуск посеред дня не запускає ротацію примусово.
У Системній інформації → Файли логів першим показано bamdude.log із позначкою Поточний, розміром, часом зміни й кнопкою Завантажити. Він доступний, навіть якщо добових архівів ще немає. Завантажується повний файл станом на початок копіювання; запис логів триває. Перезапуск і ввімкнення DEBUG не потрібні, обмеження на хвіст логу з support bundle тут немає. Розмір у списку оновлюється кнопкою Оновити й може відрізнятися від пізнішого завантаження через нові записи.
Далі йдуть добові архіви, від найновішого, з кнопками Завантажити та Видалити з підтвердженням другим кліком. У поточного рядка кнопки видалення немає; наявна дія Обрізати у переглядачі логу залишається окремо.
Завантаження поточного логу використовує GET /api/v1/support/logs/download і потребує settings:read. Віддається необроблений текст, як і для архівів. Бекенд копіює знімок обмеженого розміру в робочому потоці, закриває активний файл до передачі мережею та видаляє тимчасову копію після передачі або обриву з'єднання. Якщо лог очистили під час копіювання, повторіть завантаження.
log_retention_days за замовчуванням — 7 (діапазон 1–365). Оператори з settings:update можуть змінити його в налаштуваннях. Новий ліміт одразу застосовується до хендлера, а зайві архіви видаляються під час наступної успішної ротації; саме збереження налаштування їх не видаляє.
Support bundle¶
GET /api/v1/support/bundle створює ZIP-файл з:
| Файл | Вміст |
|---|---|
support-info.json |
Version, OS info, DB row counts, sanitised printer/integration info, anonymized settings, dependency versions, log-file size, network interfaces з masked subnets, WebSocket connection count, Docker memory limit (якщо containerised) — і сам процес BamDude, див. нижче. |
bamdude.log |
Tail bamdude.log, sanitised. |
Bundle вимагає, щоб debug logging був наразі ввімкнений — endpoint відмовляється генерувати інакше (400 Debug logging must be enabled before generating a support bundle). Workflow:
- Settings → System → перемкни DEBUG logging on.
- Відтвори issue.
- Згенеруй bundle.
- Перемкни DEBUG logging back off (інакше залишається on — стан персистить у
Settings-таблиці і re-apply при рестарті).
Сам процес BamDude¶
Раніше бандл описував машину, базу, принтери й налаштування — усе, крім процесу, який власне працює. Тож звіт «пам'ять росте днями, поки його не вб'ють» приходив без нічого, з чим можна працювати: числа, які вказують на причину, існують лише поки це відбувається, а на момент запитання контейнер уже перезапущено.
Тепер бандли несуть:
| Поле | Чому важливо |
|---|---|
| Пам'ять у користуванні проти зарезервованої | Різниця між цими двома й відрізняє справжній витік від нешкідливого адресного простору |
| Кількість потоків і дочірніх процесів | Зростання кількості потоків — це інший баг, ніж зростання купи |
| Відкриті файли й сокети | Витік дескрипторів ззовні виглядає як витік пам'яті |
| Uptime | Дає масштаб усім іншим числам |
| Розбивка того, чим заповнена пам'ять | Вказує, яке саме виділення росте |
На вже дуже великому процесі розбивка пропускається — і про це сказано
Генерація бандла для діагностики некерованого росту пам'яті не має стати тим, що добиває машину.
Дочірні процеси записуються лише за іменем, ніколи за командним рядком —
у командному рядку ffmpeg лежить пароль камери.
Це потрапляє і в бандл, який ти завантажуєш, і в пакет, доданий до звіту про баг.
Sanitisation¶
_sanitize_log_content і _collect_support_info працюють разом, щоб тримати secret-и зовні:
- Printer names →
[PRINTER], serial numbers →[SERIAL], IP addresses →[IP], access codes →[ACCESS_CODE], usernames →[USER], email-и →[EMAIL]. - URL credentials (
http://user:pass@host,rtsps://bblp:code@host) →[CREDENTIALS]@. - LDAP Distinguished Name-и →
[DN]. ПровіднийCN=у DN — це справжнє ім'я користувача, тож поводимось із ним як з email. На відміну від решти списку, DN не візьмеш із БД — він per-user і приходить із твого каталогу — тому ловиться за формою: два або більшеattr=value-компонентів через кому. ТобтоCN=Joe Schmoe,OU=Staff,DC=example,DC=comприбирається всюди, де трапиться, включно з текстом помилки від бібліотеки каталогу. Одинокийkey=valueу сторонньому рядку не чіпається. - Path-компоненти типу
/home/<user>/,/Users/<user>/,/opt/<user>/колапсуються в/home/[user]/тощо. - MQTT relay broker → masked: bare IP стає
[IP], hostname стає*.tld. - Subnets в network info → перші два октети стають
x.x(тож192.168.1.0/24→x.x.1.0/24). - Settings values — ключі, що містять будь-яке з
access_code,password,token,secret,api_key,cloud_token,mqtt_password,email,username,vapid,private_key,public_key,webhook,url,path,config,_ip,host,credentialредактяться у[REDACTED](або""якщо порожнє). Будь-які інші settings passthrough as-is, тож feature flags і themes видно в bundle.
Bundle — правильна штука, щоб приклеїти до GitHub-issue при репорті бага.
Maintenance actions¶
| Дія | Endpoint | Permission |
|---|---|---|
Optimize / vacuum SQLite — виконує ANALYZE, PRAGMA wal_checkpoint(TRUNCATE), потім VACUUM |
POST /api/v1/settings/optimize-db |
settings:backup |
| Rebuild archive search index — див. Search | POST /api/v1/archives/search/rebuild-index |
archives:update_all |
| Check for updates — див. Updates нижче | GET /api/v1/updates/check |
system:read |
Окремої "Clear Cache" кнопки на BamDude System-сторінці немає — page-level кеші (storage breakdown, system info) автоекспайряться самі; єдиний manual flush — ?refresh=true query-param на /system/storage-usage.
"Restart application" кнопки теж немає — upstream Bambuddy-концепт in-app restart має сенс тільки для bare-metal/systemd-інсталів, а target-deployment BamDude — Docker. Рестартуй контейнер через docker compose restart bamdude (або що там в твоєму orchestrator-і).
Update checker¶
GET /api/v1/updates/check poll-ить GitHub Releases і порівнює latest-tag до APP_VERSION. Два setting keys кермують поведінкою:
| Setting key | Ефект |
|---|---|
check_updates (default true) |
Коли false, endpoint повертає {update_available: false, message: "Update checks are disabled"} без походу на GitHub. |
include_beta_updates (default false) |
Коли true, prerelease-и (X.Y.ZbN) — eligible matches. Коли false, тільки stable-релізи. Detection — dual-signal: реліз вважається prerelease якщо тег матчить bN/betaN/alphaN/rcN АБО якщо marked-prerelease у GitHub UI. |
Check-response несе is_prerelease, is_docker, latest_version — UI рендерить правильні install-команди per-channel + per-install-shape.
In-app apply (native-інстали)¶
POST /api/v1/updates/apply робить фактичний git checkout + dependency install. Поведінка з 0.4.4:
- Приймає опційний
tag_namebody field — frontend передає те, що тільки що отримав з/check, щоб apply ударив exact-реліз який юзер бачив. - Резолвить у
vX.Y.Z[bN]git-ref через_resolve_git_ref()(працює і зv-prefixed і з bare формами). - Виконує
git fetch origin --tags --prune --forceпотімgit reset --hard refs/tags/<ref>. Працює для будь-якого tag незалежно від гілки — pre-fix хардкодивgit reset --hard origin/main, що тихо no-op'ило бета-інстали (бо бета-теги наdev, неmain). - Встановлює Python-deps (
pip install -r requirements.txt) і ребілдить frontend-бандл (npm install && npm run build) коли npm доступний.
Endpoint потребує settings:update. Запуск з Settings → System → Install Update коли update показано як available.
Docker-інстали¶
Docker-інсталам /apply відмовляє з is_docker: True — запуск git fetch / pip install / npm build всередині запущеного контейнера зіпсує image. Замість того UI surface-ить дві бокові секції з конкретними командами що використовують resolved latest_version + is_prerelease:
Image-based (типове) — більшість операторів запускає image: kainpl/bamdude:<tag> у compose-файлі:
# docker-compose.yml
image: kainpl/bamdude:0.4.5b1 # для бет — явний пін обов'язковий
# АБО
image: kainpl/bamdude:latest # для stable (latest трекає тільки main)
Hint-текст у UI явно пояснює чому :latest не підтягне бету — :latest Docker tag трекає main, бети тегаються на dev і шипляться як :X.Y.ZbN без :latest-промоушна.
Source-build — для операторів які склонували репо і використовують build: у compose:
git fetch origin --tags --prune --force
git checkout v0.4.5b1
docker compose build --pull
docker compose up -d
Це BamDude self-update path. Для printer firmware оновлень див. Firmware Updates — повністю окремий flow.
Permission-и¶
| Дія | Permission |
|---|---|
| Дивитись system info, storage usage, update check | system:read |
| Дивитись logs, отримати debug-logging state, генерувати support bundle | settings:read |
| Toggle debug logging, clear logs | settings:update |
| Optimize/vacuum DB, restore backup | settings:backup |
| Rebuild archive search index | archives:update_all |
system:maintenance чи support_bundle:create permission-у немає — support bundle і log endpoint-и сидять під namespace settings.
API reference¶
GET /api/v1/system/info # full system snapshot
GET /api/v1/system/storage-usage # bucketed storage breakdown
GET /health # unauthenticated liveness probe ({"status":"healthy"})
GET /api/v1/support/logs # tail bamdude.log
DELETE /api/v1/support/logs # truncate log-файл
GET /api/v1/support/debug-logging # поточний debug-logging state
POST /api/v1/support/debug-logging # toggle debug logging
GET /api/v1/support/bundle # download support ZIP
POST /api/v1/settings/optimize-db # ANALYZE + WAL checkpoint + VACUUM
POST /api/v1/archives/search/rebuild-index # rebuild FTS index
GET /api/v1/updates/version # current version (unauthenticated)
GET /api/v1/updates/check # check GitHub for newer release
Unauthenticated /health whitelist-нутий setup-gate middleware-ом, тож скрейпай його ще до того, як initial setup completes.