docs(wiki): document collector and grafana hardening
This commit is contained in:
@@ -0,0 +1,48 @@
|
|||||||
|
# Getting Started and Prerequisites
|
||||||
|
|
||||||
|
## 1.2 Обязательные переменные и preflight
|
||||||
|
|
||||||
|
После `cc9e4a0` контур Grafana/Influx считается частью базового production path. Перед запуском `ansible/deploy_aw_server.yml` должны быть доступны не только WinRM/SSH секреты, но и write-token'ы InfluxDB для bucket `aw_metrics`.
|
||||||
|
|
||||||
|
Минимальный локальный secrets-файл:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
set -a
|
||||||
|
source secrets/deploy.secrets.env
|
||||||
|
set +a
|
||||||
|
```
|
||||||
|
|
||||||
|
Обязательные переменные для Influx exporters:
|
||||||
|
|
||||||
|
| Переменная | Назначение |
|
||||||
|
| --- | --- |
|
||||||
|
| `AW_WORKTIME_INFLUX_TOKEN` | Write-token для `aw-worktime-influx-exporter.service`; пишет `aw_rdp_worktime_*` ряды в `aw_metrics`. |
|
||||||
|
| `AW_DLP_INFLUX_TOKEN` | Write-token для `aw-dlp-influx-exporter.service`; пишет DLP health/signals/cases/reviews/rules в `aw_metrics`. |
|
||||||
|
|
||||||
|
Токены должны иметь право записи в bucket `aw_metrics` в org `proxmox`. Read-only token из Grafana datasource не подходит: exporter получит `HTTP 403 Forbidden`.
|
||||||
|
|
||||||
|
## Проверки перед deploy
|
||||||
|
|
||||||
|
Быстрый preflight:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
test -n "$AW_WORKTIME_INFLUX_TOKEN"
|
||||||
|
test -n "$AW_DLP_INFLUX_TOKEN"
|
||||||
|
ansible-playbook --syntax-check ansible/deploy_aw_server.yml -i ansible/inventory.ini
|
||||||
|
ansible-playbook --syntax-check ansible/deploy_aw_windows.yml -i ansible/inventory.ini
|
||||||
|
```
|
||||||
|
|
||||||
|
`deploy_aw_server.yml` теперь сам валидирует token'ы: если `aw_worktime_influx_enabled=true` или `aw_dlp_influx_enabled=true`, но соответствующий token пустой, playbook останавливается до записи `/etc/activitywatch/aw-server.env`.
|
||||||
|
|
||||||
|
## Runtime smoke-check
|
||||||
|
|
||||||
|
После deploy проверьте:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
systemctl is-active aw-worktime-influx-exporter.timer
|
||||||
|
systemctl is-active aw-dlp-influx-exporter.timer
|
||||||
|
journalctl -u aw-worktime-influx-exporter.service -n 20 --no-pager
|
||||||
|
journalctl -u aw-dlp-influx-exporter.service -n 20 --no-pager
|
||||||
|
```
|
||||||
|
|
||||||
|
Ожидаемый результат: oneshot services завершаются `status=0/SUCCESS`, в журнале есть строки вида `wrote ... points to aw_metrics`.
|
||||||
@@ -0,0 +1,88 @@
|
|||||||
|
# Grafana and Prometheus Monitoring Stack
|
||||||
|
|
||||||
|
## 7. Grafana / Influx exporters
|
||||||
|
|
||||||
|
После `cc9e4a0` Influx exporters для Grafana включены как production default:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
aw_worktime_influx_enabled: true
|
||||||
|
aw_dlp_influx_enabled: true
|
||||||
|
```
|
||||||
|
|
||||||
|
Оба exporter'а пишут в InfluxDB bucket:
|
||||||
|
|
||||||
|
```text
|
||||||
|
org: proxmox
|
||||||
|
bucket: aw_metrics
|
||||||
|
url: http://10.10.10.10:8086
|
||||||
|
```
|
||||||
|
|
||||||
|
Grafana datasource `InfluxDB-AW` читает тот же bucket.
|
||||||
|
|
||||||
|
## Token parameters
|
||||||
|
|
||||||
|
Новые обязательные параметры:
|
||||||
|
|
||||||
|
| Ansible var | Env source | Назначение |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| `aw_worktime_influx_token` | `AW_WORKTIME_INFLUX_TOKEN` | Write-token для `aw-worktime-influx-exporter.service`. |
|
||||||
|
| `aw_dlp_influx_token` | `AW_DLP_INFLUX_TOKEN` | Write-token для `aw-dlp-influx-exporter.service`. |
|
||||||
|
|
||||||
|
Эти token'ы должны иметь `write-bucket` permission на `aw_metrics`. Grafana read-token не подходит для exporters.
|
||||||
|
|
||||||
|
## Deploy validation
|
||||||
|
|
||||||
|
`deploy_aw_server.yml` теперь содержит preflight assert'ы:
|
||||||
|
|
||||||
|
- если `aw_worktime_influx_enabled=true`, `aw_worktime_influx_token` обязан быть непустым;
|
||||||
|
- если `aw_dlp_influx_enabled=true`, `aw_dlp_influx_token` обязан быть непустым.
|
||||||
|
|
||||||
|
Кроме того, разовый запуск exporters больше не маскируется `failed_when: false`. Если запись в Influx сломана, playbook должен явно упасть, а не оставлять Grafana со старыми рядами.
|
||||||
|
|
||||||
|
## Expected measurements
|
||||||
|
|
||||||
|
После успешного запуска в `aw_metrics` должны быть свежие ряды:
|
||||||
|
|
||||||
|
- `aw_window_event`
|
||||||
|
- `aw_afk_event`
|
||||||
|
- `aw_rdp_worktime_daily`
|
||||||
|
- `aw_rdp_worktime_hourly`
|
||||||
|
- `aw_rdp_worktime_summary_daily`
|
||||||
|
- `aw_dlp_endpoint_self_test`
|
||||||
|
- `aw_dlp_fileops_health`
|
||||||
|
- `aw_dlp_signal`
|
||||||
|
- DLP case/review/rule/incident measurements, если в источниках есть соответствующие события.
|
||||||
|
|
||||||
|
Быстрая диагностика:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
systemctl start aw-worktime-influx-exporter.service
|
||||||
|
systemctl start aw-dlp-influx-exporter.service
|
||||||
|
journalctl -u aw-worktime-influx-exporter.service -n 30 --no-pager
|
||||||
|
journalctl -u aw-dlp-influx-exporter.service -n 30 --no-pager
|
||||||
|
```
|
||||||
|
|
||||||
|
Успешный результат: `wrote ... points to aw_metrics`.
|
||||||
|
|
||||||
|
## Grafana checks
|
||||||
|
|
||||||
|
Через API:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -u "$GRAFANA_USER:$GRAFANA_PASSWORD" \
|
||||||
|
http://10.10.10.11:3000/api/datasources/uid/influxdb_aw/health
|
||||||
|
```
|
||||||
|
|
||||||
|
Ожидается:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{"message":"datasource is working. 1 buckets found","status":"OK"}
|
||||||
|
```
|
||||||
|
|
||||||
|
Dashboard UID, которые должны открываться:
|
||||||
|
|
||||||
|
- `detmir-aw-main`
|
||||||
|
- `detmir-rdp-user-activity`
|
||||||
|
- `detmir-dlp-security`
|
||||||
|
- `detmir-dlp-management`
|
||||||
|
- `awatch-dlp-overview`
|
||||||
@@ -4,6 +4,15 @@
|
|||||||
|
|
||||||
## 📚 Содержание
|
## 📚 Содержание
|
||||||
|
|
||||||
|
### Production guide
|
||||||
|
- [1.2 Getting Started and Prerequisites](Getting-Started-and-Prerequisites) - обязательные env-переменные, Influx token'ы и preflight validation
|
||||||
|
- [2.2 Server Infrastructure](Server-Infrastructure) - retention, journald limits и `aw-prune-local-state`
|
||||||
|
- [2.3 Russian WebUI Patch and Localization](Russian-WebUI-Patch-and-Localization) - runtime RU patch, DLP links и navigation fixes
|
||||||
|
- [2.4 Worktime API and UI Bridge](Worktime-API-and-UI-Bridge) - cache, build locks, trend optimization и foreground context
|
||||||
|
- [3 Windows Collector Suite](Windows-Collector-Suite) - RDP/session/process collectors, recovery и локализованный Administrator
|
||||||
|
- [7 Grafana and Prometheus Monitoring Stack](Grafana-and-Prometheus-Monitoring-Stack) - Influx exporters, token validation и Grafana checks
|
||||||
|
- [8 Operations, CI/CD, and Quality Assurance](Operations-CI-CD-and-Quality-Assurance) - тесты, autoheal и rollout checks
|
||||||
|
|
||||||
### Архитектура
|
### Архитектура
|
||||||
- [Обзор архитектуры](Architecture) - высокоуровневая архитектура системы
|
- [Обзор архитектуры](Architecture) - высокоуровневая архитектура системы
|
||||||
- [Компоненты системы](Components) - описание всех компонентов
|
- [Компоненты системы](Components) - описание всех компонентов
|
||||||
|
|||||||
@@ -0,0 +1,72 @@
|
|||||||
|
# Operations, CI/CD, and Quality Assurance
|
||||||
|
|
||||||
|
## 8. Quality gates after `cc9e4a0`
|
||||||
|
|
||||||
|
Коммит усилил тестовое покрытие worktime path и сделал часть operational failures явными.
|
||||||
|
|
||||||
|
## Worktime tests
|
||||||
|
|
||||||
|
Новые/расширенные тесты:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python3 -m pytest aw-server/test_aw_worktime_api.py aw-server/test_aw_worktime_ui_bridge.py
|
||||||
|
```
|
||||||
|
|
||||||
|
Покрываются:
|
||||||
|
|
||||||
|
- in-process events cache;
|
||||||
|
- management report build locks;
|
||||||
|
- trend building с `precomputed_payloads`;
|
||||||
|
- foreground context fallback в UI bridge;
|
||||||
|
- active session id detection;
|
||||||
|
- нормализация watcher/window events.
|
||||||
|
|
||||||
|
Ожидаемый результат для текущего набора: `28 passed`.
|
||||||
|
|
||||||
|
## Autoheal changes
|
||||||
|
|
||||||
|
`aw-server/aw-worktime-autoheal.sh` изменен так, чтобы management warm-up не был обязательным probe для общей доступности worktime API.
|
||||||
|
|
||||||
|
Текущая логика:
|
||||||
|
|
||||||
|
- обязательные probes проверяют health/report path;
|
||||||
|
- если worktime API недоступен, autoheal перезапускает `aw-worktime-api.service`;
|
||||||
|
- management warm выполняется отдельно;
|
||||||
|
- failure management warm логируется, но не переводит весь health path в hard failure.
|
||||||
|
|
||||||
|
Timeout management warm увеличен:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
WORKTIME_MANAGEMENT_WARM_TIMEOUT_SECONDS=60
|
||||||
|
```
|
||||||
|
|
||||||
|
Это снижает ложные перезапуски при тяжелой сборке management report.
|
||||||
|
|
||||||
|
## UI bridge service hardening
|
||||||
|
|
||||||
|
`aw-server/aw-worktime-ui-bridge.service` теперь использует:
|
||||||
|
|
||||||
|
```ini
|
||||||
|
StartLimitBurst=20
|
||||||
|
StartLimitIntervalSec=120
|
||||||
|
```
|
||||||
|
|
||||||
|
Большее значение `StartLimitBurst` нужно для recovery-сценариев после перезапуска AW server или временной недоступности buckets: bridge может несколько раз стартовать, пока API прогревается, не попадая сразу в systemd start-limit.
|
||||||
|
|
||||||
|
## Ansible validation
|
||||||
|
|
||||||
|
Перед rollout:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ansible-playbook --syntax-check ansible/deploy_aw_server.yml -i ansible/inventory.ini
|
||||||
|
ansible-playbook --syntax-check ansible/deploy_aw_windows.yml -i ansible/inventory.ini
|
||||||
|
```
|
||||||
|
|
||||||
|
Для Grafana exporters обязательно дополнительно проверить наличие:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
AW_WORKTIME_INFLUX_TOKEN
|
||||||
|
AW_DLP_INFLUX_TOKEN
|
||||||
|
```
|
||||||
|
|
||||||
|
Playbook теперь не должен скрывать ошибку записи в Influx: если exporter не может писать в `aw_metrics`, deploy считается неуспешным.
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
# Russian WebUI Patch and Localization
|
||||||
|
|
||||||
|
## 2.3 Russian WebUI patch
|
||||||
|
|
||||||
|
`aw-server/aw-ru-patch.js` продолжает быть runtime patch'ем поверх ActivityWatch WebUI, но после `cc9e4a0` логика стала более явной: текстовые переводы и навигационные исправления сведены в отдельную функцию `applyTextAndNavigationPatches(root)`.
|
||||||
|
|
||||||
|
## `applyTextAndNavigationPatches`
|
||||||
|
|
||||||
|
Функция выполняет общий набор patch'ей для переданного DOM root:
|
||||||
|
|
||||||
|
- обход текстовых узлов через `walk(root)`;
|
||||||
|
- перевод атрибутов через `translateAttributes(root)`;
|
||||||
|
- исправление DLP navigation links;
|
||||||
|
- повторное применение при route change в SPA.
|
||||||
|
|
||||||
|
Это снижает риск, что часть UI останется на английском после client-side перехода без полной перезагрузки страницы.
|
||||||
|
|
||||||
|
## Исправление DLP links
|
||||||
|
|
||||||
|
DLP navigation получила защиту от битых ссылок:
|
||||||
|
|
||||||
|
- исправляются ссылки вида `/activity/dlp` и другие broken DLP activity refs;
|
||||||
|
- DLP item помечается `data-aw-ru-dlp-item="1"`, чтобы patch не дублировал элемент;
|
||||||
|
- patch различает label `DLP` внутри activity tabs и реальные broken links.
|
||||||
|
|
||||||
|
## Улучшения локализации
|
||||||
|
|
||||||
|
Патч теперь повторно применяет текстовые и навигационные изменения:
|
||||||
|
|
||||||
|
- на первичной загрузке `document.body`;
|
||||||
|
- после смены route key;
|
||||||
|
- после восстановления settings host/host groups state.
|
||||||
|
|
||||||
|
Это особенно важно для WebUI страниц, где ActivityWatch перерисовывает DOM без reload: activity views, category builder, settings и DLP navigation.
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
# Server Infrastructure
|
||||||
|
|
||||||
|
## 2.2 Local state retention
|
||||||
|
|
||||||
|
Коммит `cc9e4a0` добавил отдельный server-side maintenance path для контроля роста локального state на AW server.
|
||||||
|
|
||||||
|
## `aw-prune-local-state.sh`
|
||||||
|
|
||||||
|
Скрипт `aw-server/aw-prune-local-state.sh` устанавливается в:
|
||||||
|
|
||||||
|
```text
|
||||||
|
/usr/local/bin/aw-prune-local-state.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
Назначение:
|
||||||
|
|
||||||
|
- чистит старые backup-файлы в `{{ aw_server_data_dir }}/backups`;
|
||||||
|
- отдельно удерживает последние DB backups и JSON backups;
|
||||||
|
- удаляет временные архивы из `/tmp`: `activitywatch-*.zip`, `hayabusa-*.zip`, `aw-hayabusa-profiles.txt`;
|
||||||
|
- удаляет временные WebUI/worktime artifacts старше одного дня: `aw-worktime-ui-bridge.py`, `views-default.json`, `apply_webui_ru_patch.out`.
|
||||||
|
|
||||||
|
## systemd unit и timer
|
||||||
|
|
||||||
|
Ansible создает:
|
||||||
|
|
||||||
|
```text
|
||||||
|
/etc/systemd/system/aw-prune-local-state.service
|
||||||
|
/etc/systemd/system/aw-prune-local-state.timer
|
||||||
|
```
|
||||||
|
|
||||||
|
Timer:
|
||||||
|
|
||||||
|
```ini
|
||||||
|
[Timer]
|
||||||
|
OnCalendar=*-*-* 04:40:00
|
||||||
|
Persistent=true
|
||||||
|
```
|
||||||
|
|
||||||
|
То есть очистка запускается ежедневно в `04:40`; если хост был выключен, `Persistent=true` догонит пропущенный запуск.
|
||||||
|
|
||||||
|
## Retention-параметры
|
||||||
|
|
||||||
|
Параметры задаются в `ansible/group_vars/aw_server.yml`:
|
||||||
|
|
||||||
|
| Переменная | Значение по умолчанию | Назначение |
|
||||||
|
| --- | ---: | --- |
|
||||||
|
| `aw_server_backup_retention_days` | `7` | Возраст backup-файлов, после которого они могут быть удалены. |
|
||||||
|
| `aw_server_backup_keep_last_db` | `2` | Минимум последних DB backup'ов, которые всегда сохраняются. |
|
||||||
|
| `aw_server_backup_keep_last_json` | `2` | Минимум последних JSON backup'ов, которые всегда сохраняются. |
|
||||||
|
| `aw_server_journal_system_max_use` | `100M` | Лимит persistent journald storage. |
|
||||||
|
| `aw_server_journal_runtime_max_use` | `50M` | Лимит runtime journald storage. |
|
||||||
|
| `aw_server_journal_system_keep_free` | `500M` | Минимально свободное место, которое journald должен оставить на FS. |
|
||||||
|
|
||||||
|
## journald retention
|
||||||
|
|
||||||
|
`deploy_aw_server.yml` устанавливает drop-in:
|
||||||
|
|
||||||
|
```text
|
||||||
|
/etc/systemd/journald.conf.d/aw-rus-retention.conf
|
||||||
|
```
|
||||||
|
|
||||||
|
Содержимое управляется Ansible:
|
||||||
|
|
||||||
|
```ini
|
||||||
|
[Journal]
|
||||||
|
SystemMaxUse={{ aw_server_journal_system_max_use }}
|
||||||
|
RuntimeMaxUse={{ aw_server_journal_runtime_max_use }}
|
||||||
|
SystemKeepFree={{ aw_server_journal_system_keep_free }}
|
||||||
|
```
|
||||||
|
|
||||||
|
После изменения drop-in playbook перезапускает `systemd-journald` и выполняет `journalctl --vacuum-size={{ aw_server_journal_system_max_use }}`. Это ограничивает рост логов без ручной очистки и снижает риск заполнения rootfs на AW server.
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
# Windows Collector Suite
|
||||||
|
|
||||||
|
## 3. Windows collectors
|
||||||
|
|
||||||
|
Коммит `cc9e4a0` существенно усилил Windows/RDP контур, особенно `windows/worktime-session-collector.ps1` и общую recovery библиотеку `windows/ActivityWatch.Windows.Common.psm1`.
|
||||||
|
|
||||||
|
## Worktime Session Collector
|
||||||
|
|
||||||
|
`worktime-session-collector.ps1` получил крупное расширение: новые helper-функции для session/process state, отдельную публикацию session events и более строгую нормализацию buckets.
|
||||||
|
|
||||||
|
Ключевые изменения:
|
||||||
|
|
||||||
|
- `Ensure-Bucket` теперь принимает `ClientName` и `BucketType`, а не жестко прошитые значения;
|
||||||
|
- добавлена поддержка bucket `aw-session-events_<host>`;
|
||||||
|
- collector публикует logon/session state и process transitions, если это включено конфигурацией;
|
||||||
|
- session records лучше отделяют active/disconnected/unknown состояния;
|
||||||
|
- downstream server-side bridge получает более качественные `sessionId`, `username`, `sessionName` и activity markers.
|
||||||
|
|
||||||
|
## Process events
|
||||||
|
|
||||||
|
Новый флаг:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
aw_windows_process_events_enabled: true
|
||||||
|
```
|
||||||
|
|
||||||
|
Он попадает в deployment config как:
|
||||||
|
|
||||||
|
```json
|
||||||
|
sessionEvents.processEventsEnabled
|
||||||
|
```
|
||||||
|
|
||||||
|
Когда флаг включен, Windows collector публикует process-level изменения в session events bucket. Это дает server-side слою больше контекста для active session detection и forensic review.
|
||||||
|
|
||||||
|
## Localized Administrator
|
||||||
|
|
||||||
|
Новый параметр:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
aw_windows_builtin_administrator_name: "Администратор"
|
||||||
|
```
|
||||||
|
|
||||||
|
Назначение: явно фиксировать локализованное имя встроенной учетной записи Administrator с SID `*-500`.
|
||||||
|
|
||||||
|
Для текущего Windows host `SHARKON2025` task name должен строиться как:
|
||||||
|
|
||||||
|
```text
|
||||||
|
ActivityWatch Launch [SHARKON2025_Администратор]
|
||||||
|
```
|
||||||
|
|
||||||
|
Если task по `SHARKON2025_Administrator` не найден, recovery/deploy path обязан пробовать кириллическое имя `Администратор`. Это зафиксировано через:
|
||||||
|
|
||||||
|
- default vars в `ansible/deploy_aw_windows.yml`;
|
||||||
|
- `ansible/group_vars/aw_windows.yml`;
|
||||||
|
- example vars в `ansible/group_vars/windows.example.yml`;
|
||||||
|
- env override `AWATCH_RUS_BUILTIN_ADMINISTRATOR_NAME`;
|
||||||
|
- fallback в `Get-ActivityWatchBuiltInAdministratorName`.
|
||||||
|
|
||||||
|
## Recovery hardening
|
||||||
|
|
||||||
|
`ActivityWatch.Windows.Common.psm1` усилил recovery path:
|
||||||
|
|
||||||
|
- `Get-ActivityWatchBuiltInAdministratorName` сначала смотрит env override, затем SID-500 lookup, затем host-specific fallback `SHARKON2025 -> Администратор`;
|
||||||
|
- `Normalize-ActivityWatchUsers` стабилизирован для pipeline/list cases;
|
||||||
|
- удаление scheduled tasks стало устойчивее к частично удаленным task definitions;
|
||||||
|
- recovery task может ориентироваться на live interactive session и запускаться в interactive logon context, когда это безопаснее для watcher'ов.
|
||||||
|
|
||||||
|
Операционный вывод: для RDP/console telemetry нельзя полагаться на task name с английским `Administrator` на русифицированной Windows. Локализованное имя должно быть частью deploy vars.
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
# Worktime API and UI Bridge
|
||||||
|
|
||||||
|
## 2.4 Worktime API
|
||||||
|
|
||||||
|
`aw-server/aw-worktime-api.py` теперь рассчитан на повторные management-запросы без лишнего чтения одних и тех же bucket events.
|
||||||
|
|
||||||
|
## In-process events cache
|
||||||
|
|
||||||
|
Добавлен in-process cache событий:
|
||||||
|
|
||||||
|
```text
|
||||||
|
AW_WORKTIME_EVENTS_CACHE_TTL_SECONDS=30
|
||||||
|
```
|
||||||
|
|
||||||
|
Ключ cache - bucket id. Значение хранит `stored_at` и список events. Cache защищен `threading.Lock`, поэтому параллельные HTTP-запросы не ломают состояние процесса. Основной эффект: management report и trend building меньше давят на `/api/0/buckets/.../events`.
|
||||||
|
|
||||||
|
## Build locks для management report
|
||||||
|
|
||||||
|
Функция `get_management_build_lock(host, report_date)` выдает lock на пару `host + date`. Это предотвращает параллельную сборку одного и того же management report при одновременных запросах UI, warm-up и health probes.
|
||||||
|
|
||||||
|
Поведение:
|
||||||
|
|
||||||
|
- первый запрос собирает payload;
|
||||||
|
- конкурирующие запросы ждут тот же lock;
|
||||||
|
- после сборки результат кладется в cache/файловый слой как раньше.
|
||||||
|
|
||||||
|
## Оптимизация trend building
|
||||||
|
|
||||||
|
`build_management_trend(...)` принимает `precomputed_payloads`. Текущий report payload переиспользуется как готовый день тренда, а не пересчитывается повторно.
|
||||||
|
|
||||||
|
Практический эффект: endpoint management report меньше тратит CPU на день, который уже был рассчитан текущим запросом.
|
||||||
|
|
||||||
|
## UI Bridge foreground context cache
|
||||||
|
|
||||||
|
`aw-server/aw-worktime-ui-bridge.py` сохраняет `last_foreground_context` в state. Если свежий collector health event временно недоступен, bridge может использовать последний валидный foreground context вместо деградации в generic `RDP`.
|
||||||
|
|
||||||
|
Нормализация foreground context:
|
||||||
|
|
||||||
|
- `foregroundProcess` становится `app`;
|
||||||
|
- если процесс без `.exe`, suffix добавляется автоматически;
|
||||||
|
- `foregroundTitle` становится `title`;
|
||||||
|
- context учитывается только для активных session ids, если они известны.
|
||||||
|
|
||||||
|
## Active session detection
|
||||||
|
|
||||||
|
Функция `get_latest_active_session_ids(events)` группирует session events по timestamp, берет самый свежий срез и возвращает только активные `sessionId`.
|
||||||
|
|
||||||
|
Это убирает смешивание старых disconnected-сессий с текущим состоянием и стабилизирует связку:
|
||||||
|
|
||||||
|
```text
|
||||||
|
aw-worktime-sessions_* -> aw-rdp-window_* -> aw-watcher-window_*
|
||||||
|
```
|
||||||
|
|
||||||
|
## Нормализация window events
|
||||||
|
|
||||||
|
Bridge теперь формирует window events из session state и foreground context:
|
||||||
|
|
||||||
|
- активное окно получает app/title из foreground context;
|
||||||
|
- title дополняется агрегированным RDP summary через `build_window_title(...)`;
|
||||||
|
- `normalize_watcher_window_events(...)` подготавливает совместимый поток для `aw-watcher-window_<host>`;
|
||||||
|
- sync в watcher bucket выполняется только если `watcher_window_needs_bridge_sync(...)` считает его нужным.
|
||||||
|
|
||||||
|
Это сохраняет совместимость с ActivityWatch WebUI и Grafana, где часть запросов ожидает canonical watcher bucket.
|
||||||
Reference in New Issue
Block a user