[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"docs-infra\u002Fdeploy\u002Flogs":3,"docs-tabs-infra\u002Fdeploy\u002Flogs":6},{"content":4,"lastmod":5},"\n## Логи сервиса\n\n`GET \u002Fv1\u002Finfra\u002Fservers\u002F:id\u002Flogs`\n\nВозвращает логи BLACKHOLE-сервера через системную утилиту `journalctl`. Без параметра `service` читается весь системный журнал (все сервисы и общесистемные сообщения). Для логов конкретного systemd-юнита — передайте `service` (по умолчанию при деплое создаётся `app.service`, если не указали другое имя). Поддерживает фильтрацию по количеству строк, временному окну и подстроке.\n\n## Параметры\n\n| Параметр | В | Тип | Обяз. | По умолч. | Описание |\n|----------|---|-----|:-----:|-----------|----------|\n| `id` | path | string (UUID) | да | — | ID BLACKHOLE-сервера |\n| `service` | query | string | нет | — | Имя systemd-юнита: `app`, `crm-dashboard`, и т. п. Не указывайте расширение `.service`. По умолчанию читается весь системный журнал |\n| `lines` | query | number | нет | 50 | Количество строк, 1–500 |\n| `since` | query | string | нет | — | Временная метка в формате утилиты `journalctl`: `\"1 hour ago\"`, `\"2026-04-22 10:00:00\"`, `\"10 minutes ago\"` |\n| `grep` | query | string | нет | — | Подстрока для фильтра, до 200 символов |\n\n## Примеры\n\n### curl — личный ключ\n\n```bash\n# Логи приложения за последний час с фильтром по \"error\"\ncurl -H \"X-Api-Key: YOUR_API_KEY\" \\\n  \"https:\u002F\u002Fvibecode.bitrix24.tech\u002Fv1\u002Finfra\u002Fservers\u002FSERVER_ID\u002Flogs?service=app&lines=100&since=1%20hour%20ago&grep=error\"\n\n# Весь системный журнал, последние 10 строк (для отладки cloud-init)\ncurl -H \"X-Api-Key: YOUR_API_KEY\" \\\n  \"https:\u002F\u002Fvibecode.bitrix24.tech\u002Fv1\u002Finfra\u002Fservers\u002FSERVER_ID\u002Flogs?lines=10\"\n```\n\n### curl — OAuth-приложение\n\n```bash\ncurl -H \"X-Api-Key: YOUR_APP_KEY\" \\\n  -H \"Authorization: Bearer USER_SESSION_TOKEN\" \\\n  \"https:\u002F\u002Fvibecode.bitrix24.tech\u002Fv1\u002Finfra\u002Fservers\u002FSERVER_ID\u002Flogs?service=app&lines=50\"\n```\n\n### JavaScript — личный ключ\n\n```javascript\nconst params = new URLSearchParams({\n  service: 'app',\n  lines: '100',\n  since: '30 minutes ago',\n})\n\nconst res = await fetch(\n  `https:\u002F\u002Fvibecode.bitrix24.tech\u002Fv1\u002Finfra\u002Fservers\u002F${serverId}\u002Flogs?${params}`,\n  { headers: { 'X-Api-Key': 'YOUR_API_KEY' } }\n)\nconst { data } = await res.json()\ndata.logs.forEach(line => console.log(line))\n```\n\n### JavaScript — OAuth-приложение\n\n```javascript\nconst res = await fetch(\n  `https:\u002F\u002Fvibecode.bitrix24.tech\u002Fv1\u002Finfra\u002Fservers\u002F${serverId}\u002Flogs?service=app&lines=50`,\n  {\n    headers: {\n      'X-Api-Key': 'YOUR_APP_KEY',\n      'Authorization': 'Bearer USER_SESSION_TOKEN',\n    },\n  }\n)\n```\n\n## Поля ответа\n\n| Поле | Тип | Описание |\n|------|-----|----------|\n| `success` | boolean | Всегда `true` при успехе |\n| `data.service` | string \\| null | Эхо параметра `?service=`, или `null` если не передавался |\n| `data.logs` | array\\\u003Cstring\\> | **Основное поле.** Строки логов в порядке поступления (новые — в конце массива) |\n| `data.lines` | array\\\u003Cstring\\> | Алиас `data.logs` (тот же массив). Сохранён для обратной совместимости — в новом коде используйте `data.logs` |\n| `data.requestedLines` | number | Эхо `?lines=` параметра (валидировано 1–500, default 50) |\n| `data.returnedLines` | number | Длина `data.logs` |\n| `data.since` | string \\| null | Эхо `?since=`, или `null` |\n| `data.grep` | string \\| null | Эхо `?grep=`, или `null` |\n| `data.hint` | string | Опционально. Диагностика когда `data.logs.length === 0` |\n\n## Пример ответа\n\n```json\n{\n  \"success\": true,\n  \"data\": {\n    \"service\": null,\n    \"logs\": [\n      \"Apr 22 11:17:02 epd65hdv07p8g89c0c06 CRON[1406]: pam_unix(cron:session): session closed for user root\",\n      \"Apr 22 11:17:27 epd65hdv07p8g89c0c06 vibe-agent[1098]: 2026\u002F04\u002F22 11:17:27 [exec] id= timeout=10s workdir=\\\"\\\" command=\\\"uname -a\\\"\",\n      \"Apr 22 11:17:28 epd65hdv07p8g89c0c06 cloud-init[975]: Reading package lists...\"\n    ],\n    \"lines\": [\n      \"Apr 22 11:17:02 epd65hdv07p8g89c0c06 CRON[1406]: pam_unix(cron:session): session closed for user root\",\n      \"Apr 22 11:17:27 epd65hdv07p8g89c0c06 vibe-agent[1098]: 2026\u002F04\u002F22 11:17:27 [exec] id= timeout=10s workdir=\\\"\\\" command=\\\"uname -a\\\"\",\n      \"Apr 22 11:17:28 epd65hdv07p8g89c0c06 cloud-init[975]: Reading package lists...\"\n    ],\n    \"requestedLines\": 50,\n    \"returnedLines\": 3,\n    \"since\": null,\n    \"grep\": null\n  }\n}\n```\n\n## Пример ответа при ошибке\n\n400 — сервер в OPEN-режиме:\n\n```json\n{\n  \"success\": false,\n  \"error\": {\n    \"code\": \"NOT_BLACKHOLE\",\n    \"message\": \"Deployment API only available for BLACKHOLE servers\"\n  }\n}\n```\n\n## Ошибки\n\n| HTTP | Код | Описание |\n|------|-----|----------|\n| 400 | `VALIDATION_ERROR` | Нарушена схема: `lines` вне 1–500, `grep` длиннее 200 символов |\n| 400 | `NOT_BLACKHOLE` | Сервер в режиме OPEN — Deploy API недоступен |\n| 401 | `MISSING_API_KEY` | Не передан заголовок `X-Api-Key` |\n| 401 | `INVALID_API_KEY` | Неверный или просроченный API-ключ |\n| 404 | `NOT_FOUND` | Сервер не существует, удалён или принадлежит другому API-ключу |\n| 409 | `SERVER_NOT_READY` | Сервер не готов к операции: не запущен или туннель не подключён. В ответе — поле `hint` с причиной и следующим шагом. Разбудите сервер или вызовите [`\u002Frepair`](\u002Fdocs\u002Finfra\u002Flifecycle\u002Frepair) и повторите запрос. Случай «числится подключённым, но у Gateway нет живого туннеля» на этом маршруте приходит как `502 TUNNEL_NOT_FOUND` (см. ниже) |\n| 429 | `RATE_LIMITED` | Превышен лимит 10 операций в минуту на сервер |\n| 502 | `TUNNEL_NOT_FOUND` \u002F `GATEWAY_UNREACHABLE: …` | Нет живого туннеля до сервера либо Gateway недоступен — вызовите [`\u002Frepair`](\u002Fdocs\u002Finfra\u002Flifecycle\u002Frepair) и повторите. `GATEWAY_UNREACHABLE` несёт детали после двоеточия, поэтому сопоставляйте `error.code` по префиксу, а не по точному совпадению |\n| 503 | `GATEWAY_TIMEOUT: …` | Gateway не ответил вовремя. Код тоже несёт детали после двоеточия — сравнивайте по префиксу |\n| 502 | `LOGS_UNAVAILABLE` | Агент не смог прочитать системный журнал: нет такого юнита, неверный фильтр, отказано в доступе или `journalctl` вернул ошибку |\n\nПолный список общих ошибок API — [Ошибки](\u002Fdocs\u002Ferrors).\n\n## Известные особенности\n\n- **Формат строк — как выдаёт `journalctl`.** Каждая строка уже содержит время, имя хоста, имя процесса и его PID — дополнительная обработка на клиенте не нужна, выводите как есть.\n- **Фильтр `grep` — простая подстрока, не регулярное выражение.** Для сложных паттернов выгружайте больше строк и фильтруйте на клиенте.\n- **Логи агента туннеля видны без `service`** — под именем `vibe-agent`. Полезно для диагностики, когда приложение не отвечает через Deploy API. Просто не передавайте параметр `service` — увидите весь системный журнал, включая `vibe-agent`, cloud-init и другие общесистемные сообщения.\n- **Лимит 500 строк помножен на ограничение 10 вызовов в минуту** — за минуту можно прочитать максимум 5000 строк. Для большего объёма логов — несколько вызовов с разными `since` и аккуратно к лимиту.\n\n## Galaxy-приложения\n\nЕсли сервер — galaxy-приложение (`kind=GALAXY_APP`), эндпоинт возвращает не системный журнал хоста, а stdout\u002Fstderr самого контейнера приложения (`docker logs`). Параметр `service` для galaxy-приложений не применяется.\n\n- **Чтение read-only.** Запрос логов не будит спящую галактику. Если хост-галактика спит или недоступен, ответ — пустой массив `data.logs` плюс диагностическое поле `data.hint`. Разбудите галактику (любым обращением к приложению) и повторите запрос.\n- **`since` — длительность или RFC3339, не относительная текстовая форма.** Для galaxy-приложений `since` принимает только длительность в секундах\u002Fминутах\u002Fчасах (`10m`, `2h`, `24h`) или метку времени RFC3339 (`2026-06-24T10:00:00Z`) — для интервала в сутки используйте `24h`. Относительные текстовые формы `journalctl` (`\"1 hour ago\"`, `\"10 minutes ago\"`) допустимы только для Black Hole-серверов — для galaxy-приложения такое значение вернёт `400 VALIDATION_ERROR`.\n- **`grep`** работает так же — простая подстрока, фильтрация на стороне платформы.\n\n## Смотрите также\n\n- [Полный деплой](.\u002Fdeploy.md) — посмотреть, какое имя сервиса создаётся.\n- [Выполнить команду](.\u002Fexec.md) — `journalctl -u app -f` для потокового чтения логов в реальном времени через `exec`.\n- [Метрики туннеля](.\u002Fmetrics.md) — активность агента и HTTP-соединения.\n","2026-06-29",{}]