Файлы и папки
Всё, что хранит Signal Lab, — обычный JSON (или текст) в одной папке, папке данных. Значений секретов в ней никогда нет.
Папка данных
| Где работает Signal Lab | Папка данных |
|---|---|
| Настольное приложение, Windows | Documents\SignalLab в вашей пользовательской папке: C:\Users\<you>\Documents\SignalLab |
| Настольное приложение, Linux | ~/Documents/SignalLab |
| Сервер | --data-dir или SIGNALLAB_DATA_DIR; если не задано ни то, ни другое, — Documents/SignalLab в домашней папке пользователя, от имени которого он работает |
| Сервер, образ Docker | /data, том (signallab-data в файле compose) |
signallab run | Временная папка, которая удаляется при выходе, если только --data-dir не называет другую |
Настольное приложение тоже берёт SIGNALLAB_DATA_DIR из своего окружения, если она задана. Папка создаётся, когда в неё что-то записывают впервые.
TIP
В Windows приложение использует папку Documents прямо в вашей пользовательской папке, даже если Windows хранит ваши документы в другом месте (OneDrive).
На сервере файлы записываются на машине сервера, а не на вашей. Значок Сервер в шапке сообщает, где именно, в своей подсказке; API отдаёт это как data_dir команды app_info, а /api/files скачивает то, что в ней лежит.
Команды signallab emulate, signallab send и signallab mcp читают библиотеки приложения из той же папки, что и настольное приложение.
Что в ней лежит
| Файл | Что это | Когда записывается |
|---|---|---|
experiment.json | Эксперимент, открытый в редакторе | Вскоре после каждого изменения |
signals.json | Библиотека сигналов (Сигналы) | Вскоре после каждого изменения |
emulators.json | Библиотека эмуляторов (Эмуляторы) | Вскоре после каждого изменения |
runs/run-<ms>-<job>.json | Один отчёт на каждый запуск, закончившийся сам | Когда запуск заканчивается |
exports/experiment-<ms>-<16 hex digits>.json | Снимок эксперимента | Экспорт текущей схемы |
capture-<ms>.jsonl, capture-<ms>.txt | Кадры Инспектора | Экспорт .jsonl, Экспорт .txt |
token | Токен доступа сервера, читаемый только его пользователем | --generate-token, при первом запуске |
.experiment-<hex>.tmp, .signals-<hex>.tmp, .emulators-<hex>.tmp | Сохранение в процессе | На мгновение, затем переименовывается |
<ms> — время в миллисекундах с 1970 года; <job> — номер задачи запуска. На сервере каждый браузер работает с одним и тем же experiment.json, теми же библиотеками и теми же отчётами.
Форматы
Все файлы — JSON в UTF-8, записанный с отступами, чтобы его удобно было читать и сравнивать. В каждом есть version; файл более старой версии читается и переносится на текущую при открытии и записывается обратно уже в текущей версии при следующем сохранении — после чего более старый Signal Lab открыть его не сможет.
experiment.json
Документ эксперимента, версия 9 — тот же JSON, который записывает Экспорт текущей схемы и читает Открыть JSON…:
{
"version": 9,
"name": "HTTP check",
"params": [],
"profiles": [],
"profile": null,
"seed": null,
"cookies": true,
"nodes": [ { "id": "start", "type": "start", "x": 40, "y": 80 }, … ],
"edges": [ { "from": "start", "to": "request", "port": "next" }, … ]
}- Не больше 4 МиБ и от 1 до 64 узлов (
doc.node_count). - Версии с 1 по 8 переносятся при открытии. Файл старше версии 8 открывается с выключенным
cookies, чтобы запускаться как раньше; остальные настройки, которые добавила каждая версия (параметры во 2-й, профили в 3-й, повторные попытки в 4-й, повторы и циклы в 5-й, эмуляторы в 6-й, помехи в 7-й, WebSocket и аутентификация HTTP в 8-й, нагрузка в 9-й), начинаются пустыми. - Версия новее той, которую знает этот Signal Lab, отклоняется (
doc.version_unsupported), а не открывается без того, что он не может прочитать. - Файл, который не разбирается, сопровождается сообщением с путём, строкой и столбцом и никогда не заменяется.
- Он записывается во временный файл и переименовывается, поэтому неудачная запись оставляет предыдущий.
Что такое узлы, параметры и профили: эксперименты, узлы, данные.
signals.json
Библиотека сигналов, версия 2:
{
"version": 2,
"signals": [
{
"id": "…",
"name": "Go cue",
"group": "Stage/Cues",
"note": "",
"body": { "transport": "osc", "target": "127.0.0.1:9000", "address": "/cue/go", "args": [ { "type": "int", "value": 1 } ] }
}
],
"folders": [ "Stage", "Stage/Cues" ]
}group— папка сигнала в виде пути через/; пусто означает верхний уровень.folders(добавлено в версии 2) перечисляет все папки, включая пустые, и пропускается, если папок нет. Файл версии 1 читается так же, без пустых папок.body— одно изosc,udp,httpилиmqtt; их поля описаны вsignals_save.- Если файла нет, записывается стартовый набор — все цели на
127.0.0.1— и переименовывается на язык интерфейса. - Файл, который не разбирается, сопровождается сообщением с путём, строкой и столбцом (
signals.json_invalid) и никогда не заменяется стартовым набором: исправьте или удалите его. Пока он не читается, библиотеку никто не записывает — сохранение отклоняется с той же ошибкой, а файл остаётся как есть, — пока Перечитать файл не прочитает его снова. Сохранение идёт через временный файл в той же папке, поэтому оборванная запись оставляет предыдущий файл.
emulators.json
Библиотека эмуляторов, версия 1:
{
"version": 1,
"emulators": [
{ "id": "demo-api", "note": "…", "emulator": { "name": "Demo API", "bind": "127.0.0.1:8080", "protocol": "http", "routes": [ … ] } }
]
}Каждая запись — документ эмулятора с id и note; сам документ описан в разделе эмуляторы. Как и у сигналов, отсутствующему файлу достаётся стартовый набор (все привязаны к 127.0.0.1), а испорченный файл сопровождается сообщением об ошибке (emulators.json_invalid) и никогда не заменяется. Он записывается через временный файл. signallab emulate читает и собственный файл, в котором один эмулятор, их список или библиотека, подобная этой.
Отчёты о запусках
runs/run-<started ms>-<job>.json, отчёт версии 5: один файл на каждый запуск, который прошёл или не прошёл; он никогда не перезаписывается (второй запуск с тем же именем получает -2, -3…). Остановленный запуск не сохраняет ничего.
| Поле | Что это |
|---|---|
version | 5 |
experiment | Имя эксперимента |
document_version | Версия документа, который выполнялся |
seed, profile | С чем он выполнялся |
overrides | Значения, заданные только для этого запуска |
params | Все значения параметров, которые он использовал |
started_ms, ended_ms | Миллисекунды с 1970 года |
outcome | passed или failed |
error | Его первый сбой или null |
steps | Все шаги, как у experiment://step |
emulators | Что принял и на что ответил каждый узел Эмулятор (с версии 3); пропускается, если таких нет |
impairments | Что сделало реле каждого узла Сетевые помехи по фазам (с версии 4); пропускается, если таких нет |
Измерения шага нагрузки лежат в его последнем шаге (с версии 5). История запусков на ленте запуска и кнопка Сравнить читают эти файлы; отчёт, который не удаётся прочитать, в список не попадает. См. запуски и отчёты.
Экспорт
exports/experiment-…json: документ эксперимента, как выше. Каждый экспорт — новый файл.capture-….jsonl: по одному кадру Инспектора на строку, с хранимыми им байтами вdata, в base64.capture-….txt: кадры для чтения, каждый с hex-дампом.
На сервере экспорт Инспектора скачивается на ваш компьютер по мере создания; экспорт эксперимента предлагает кнопку Скачать, а надпись Отчёт сохранён на ленте запуска — это ссылка, скачивающая отчёт.
Секретов в этих файлах нет
Эксперимент называет секрет — {{secret.API_TOKEN}} — и записывается только имя. Значение хранится так:
| Где работает Signal Lab | Где значения секретов |
|---|---|
| Настольное приложение, Windows | Диспетчер учётных данных Windows, под именем SignalLab (окно Секреты в редакторе) |
| Настольное приложение, Linux | Нигде: секреты хранить нельзя (secret.unsupported) |
| Сервер | Только чтение: переменная окружения SIGNALLAB_SECRET_<NAME> или файл <NAME> в --secrets-dir (по умолчанию /run/secrets/signallab) |
signallab | Те же файлы и переменные или хранилище системы с --secrets system |
WARNING
То, что вы вводите прямо в поле, хранится так, как набрано. Пароль в учётных данных сигнала HTTP, пароль эмулятора брокера MQTT, токен, вставленный в заголовок, — всё это обычный текст в signals.json, emulators.json или experiment.json и в их экспорте. Для всего, что вы не положили бы в общую папку, используйте в эксперименте {{secret.NAME}}.
Настройки интерфейса
То, что запоминает интерфейс, — его язык, значения, введённые последними на каждом экране, какая панель открыта и какого она размера, Хранить cookie, когда в последний раз искали обновления и случайный номер установки для обновлений, — хранит сам интерфейс, а не папка данных: в собственном хранилище приложения на настольном компьютере и в хранилище сайта браузера для страницы сервера (у каждого браузера своё). Учётные данные экрана HTTP там не хранятся.
Signal Lab не пишет файлов журнала; см. устранение неполадок.
Копирование, правка, перенос
- Копируйте всю папку целиком. Всё в ней — самодостаточный JSON; значений секретов в ней нет, поэтому на новой машине задайте их заново.
- Правьте
signals.json,emulators.jsonиexperiment.jsonвручную, пока Signal Lab закрыт (или, на сервере, пока не открыта ни одна страница): приложение записывает весь файл из того, что держит в памяти, поэтому изменение, сделанное во время работы, перезаписывается его следующим сохранением. Ошибка будет показана со строкой и столбцом при следующем чтении файла и никогда не будет молча заменена — дляsignals.jsonэто так и при сохранении самим приложением: сохранение отклоняется, и файл остаётся таким, каким вы его оставили. - Удаляйте файлы
runs/,exports/иcapture-*когда угодно. Удалениеsignals.jsonилиemulators.jsonвозвращает стартовый набор; удалениеexperiment.jsonвозвращает стартовый эксперимент. - Переносите папку, скопировав её и указав Signal Lab новое место:
--data-dirдля сервера,SIGNALLAB_DATA_DIRдля настольного приложения. - Делитесь экспериментом, экспортировав его или добавив его JSON в коммит рядом с проектом, который он проверяет;
signallab runзапустит его оттуда.