Graylog собирает логи со всех серверов, контейнеров и сетевых устройств в одно хранилище, индексирует их и отдаёт результаты поиска за секунды. Стек состоит из трёх частей: сервер Graylog (приём, обработка, API и веб-интерфейс), MongoDB (конфигурация, пользователи, streams) и OpenSearch (хранение и полнотекстовый поиск).
Первый рабочий контур поднимается за 30-60 минут: docker compose с тремя сервисами, один input, один stream, один alert. Дальше маршрут сообщения целиком: от источника до дашборда.
В статье: установка Graylog 6.x в Docker и из пакетов на Ubuntu, подключение Linux через rsyslog, Windows через Winlogbeat и NXLog, контейнеров через GELF-драйвер, сетевых устройств Cisco, MikroTik и pfSense по Syslog. Затем streams и pipelines для маршрутизации, поиск, дашборды, event definitions с уведомлениями, управление индексами и чек-лист диагностики, когда логи не приходят.
Что такое Graylog и зачем он нужен в вашей инфраструктуре
Graylog работает с логами как с базой данных: поиск по полям, агрегации, фильтры по времени, retention по расписанию. MongoDB хранит описания inputs, streams, dashboards и права. OpenSearch хранит сами сообщения и отвечает за поиск. Сервер принимает Syslog, GELF, Beats, Raw/Plaintext и HTTP, прогоняет сообщения через extractors и pipelines, раскладывает по streams и записывает в index sets.
Возможности, которые нужны в повседневной эксплуатации:
- inputs: приём данных по Syslog, GELF, Beats, HTTP, Raw/Plaintext;
- streams: маршрутизация по полям, отдельные index sets и права доступа для команд;
- pipelines: парсинг Grok, обогащение через lookup tables, удаление шума;
- search и dashboards: сохранённые запросы, виджеты, агрегации;
- alerts: event definitions и уведомления в email, Slack, webhook;
- RBAC: роли, доступ к конкретным streams, API-токены;
- journal: дисковый буфер, который держит сообщения, пока OpenSearch недоступен.
Graylog закрывает задачи от аудита действий до разбора инцидентов, он оправдан при 5-500 источниках. Для одного-двух хостов хватит journald и локальной ротации: центральный сервер добавит только хлопоты с диском и бэкапами.
Если проектируете систему целиком, начните с обзора архитектуры централизованного сбора логов: конвейер, агенты, хранилище и точки отказа.
Graylog vs ELK: что выбрать под вашу задачу
Сравнение по четырём осям, которые решают выбор на практике.
| Критерий | Graylog | ELK (Elasticsearch, Logstash, Kibana) / OpenSearch Stack |
|---|---|---|
| Время до первого результата | 30-60 минут: docker compose, панель управления из коробки | Часы или дни: версии, pipelines Logstash, шаблоны индексов, Kibana |
| Ресурсы | 4 vCPU и 8 ГБ RAM для старта, heap OpenSearch 2 ГБ | Сопоставимо на старте, заметно выше на больших объёмах и сложном парсинге |
| Парсинг | Pipelines и extractors в веб-интерфейсе, lookup tables | Logstash и ingest pipelines в конфигах, гибче для нестандартных схем |
| Эксплуатация | Один интерфейс для inputs, streams, алертов и прав | Нужна экспертиза по каждому компоненту, зато богаче экосистема |
Graylog берите, когда нужен быстрый результат и встроенные streams с pipelines. ELK выбирают при готовой экспертизе в Elasticsearch, требовании к глубокой кастомизации ingest-конвейеров или жёстких ILM-политик. Пошаговый запуск альтернативы разобран в руководстве ELK стек 2026: готовое решение для сбора и анализа логов.
Требования к серверу и подготовка окружения
Для продакшена малого масштаба хватит 4 vCPU и 8 ГБ RAM на SSD. При десятках тысяч сообщений в минуту берите 8 vCPU и 16-32 ГБ RAM. Java heap OpenSearch начинается с 2 ГБ и растёт до половины памяти сервера, потолок 31 ГБ: выше отключаются сжатые указатели и память расходуется зря.
Настройки ядра обязательны, иначе OpenSearch не стартует:
sudo sysctl -w vm.max_map_count=262144 echo "vm.max_map_count=262144" | sudo tee /etc/sysctl.d/99-graylog.conf sudo swapoff -a
Для systemd-юнита OpenSearch поднимите лимиты: nofile 65536 и memlock unlimited. Свап держите выключенным, память фиксируется в heap.
Версии компонентов: Graylog 6.x, OpenSearch 2.x, MongoDB 6.x. MongoDB 6.x требует поддержки AVX процессором, проверьте на старом железе: grep -o avx /proc/cpuinfo. Порты: 9000 (web и API), 12201 (GELF UDP/TCP), 514 и 1514 (Syslog), 5044 (Beats), 9200 (OpenSearch, слушать только на localhost).
Если своего железа нет, для старта подойдёт облачный сервер с 4 vCPU и 8 ГБ RAM, например Timeweb Cloud: конфигурацию можно менять по мере роста потока логов.
Установка Graylog: Docker Compose как самый быстрый путь
Сгенерируйте два секрета: пароль пользователя admin и случайный password_secret.
echo -n "MyStrongPassword" | sha256sum openssl rand -hex 32
Первая команда выводит SHA2-хеш пароля (64 hex-символа), вторая даёт секрет на 64 символа. Оба значения подставьте в compose.
services:
mongodb:
image: mongo:6.0
restart: unless-stopped
volumes:
- mongo_data:/data/db
networks:
- graylog
opensearch:
image: opensearchproject/opensearch:2.19.0
restart: unless-stopped
environment:
- discovery.type=single-node
- bootstrap.memory_lock=true
- OPENSEARCH_JAVA_OPTS=-Xms2g -Xmx2g
- DISABLE_INSTALL_DEMO_CONFIG=true
- DISABLE_SECURITY_PLUGIN=true
ulimits:
memlock: -1
nofile: 65536
volumes:
- os_data:/usr/share/opensearch/data
networks:
- graylog
graylog:
image: graylog/graylog:6.2
restart: unless-stopped
depends_on:
- mongodb
- opensearch
environment:
- GRAYLOG_PASSWORD_SECRET=вставьте_значение_из_openssl
- GRAYLOG_ROOT_PASSWORD_SHA2=вставьте_хеш_из_sha256sum
- GRAYLOG_HTTP_EXTERNAL_URI=http://10.0.0.10:9000/
- GRAYLOG_ELASTICSEARCH_HOSTS=http://opensearch:9200
- GRAYLOG_MONGODB_URI=mongodb://mongodb:27017/graylog
ports:
- "9000:9000"
- "1514:1514"
- "12201:12201/udp"
- "12201:12201/tcp"
- "5044:5044"
volumes:
- graylog_data:/usr/share/graylog/data
networks:
- graylog
volumes:
mongo_data:
os_data:
graylog_data:
networks:
graylog:
driver: bridge
Запуск и проверка:
docker compose up -d docker compose logs -f graylog
Когда в логе появится строка о старте сервера, откройте http://10.0.0.10:9000 и войдите как admin с паролем, чей хеш вы сгенерировали. Настройку vm.max_map_count примените и на хосте с Docker: OpenSearch использует ядро хоста, и без 262144 контейнер уйдёт в рестарт.
DISABLE_SECURITY_PLUGIN=true подходит для изолированного контура: внутри него трафик между контейнерами не шифруется. Для сегмента с публичным доступом включите плагин безопасности и TLS.
Развертывание на Ubuntu/Debian без Docker (пакеты)
Если контейнеры запрещены политикой, ставьте компоненты пакетами. Подключите официальные репозитории MongoDB, OpenSearch и Graylog, затем:
sudo apt update sudo apt install opensearch mongodb-org graylog-server
В /etc/opensearch/opensearch.yml для одиночного узла:
network.host: 127.0.0.1 discovery.type: single-node plugins.security.disabled: true
В /etc/opensearch/jvm.options задайте -Xms2g и -Xmx2g. Файл /etc/graylog/server/server.conf:
password_secret = 64_случайных_символа root_password_sha2 = hex_хеш_пароля_admin elasticsearch_hosts = http://127.0.0.1:9200 mongodb_uri = mongodb://localhost:27017/graylog http_bind_address = 0.0.0.0:9000 http_external_uri = http://10.0.0.10:9000/
Службы включаются одной командой:
sudo systemctl enable --now opensearch mongod graylog-server sudo systemctl status graylog-server
Порт 514 привилегированный, а graylog-server работает под непривилегированным пользователем graylog. Syslog input слушайте на 1514, а трафик с 514 перенаправляйте правилом NAT:
sudo iptables -t nat -A PREROUTING -p udp --dport 514 -j REDIRECT --to-port 1514 sudo iptables -t nat -A PREROUTING -p tcp --dport 514 -j REDIRECT --to-port 1514
Типовые ошибки при первом запуске и как их исправить
- OpenSearch падает с "max virtual memory areas vm.max_map_count [65530] is too low": примените sysctl vm.max_map_count=262144.
- MongoDB завершается с кодом 132 или Illegal instruction: у процессора нет AVX, MongoDB 6.x на таком железе не запустится. Возьмите хост с AVX.
- Graylog не видит OpenSearch: проверьте elasticsearch_hosts. В Docker это http://opensearch:9200, из пакетов http://127.0.0.1:9200, контейнеры должны быть в одной сети.
- Веб-интерфейс недоступен: http_bind_address = 0.0.0.0:9000, порт 9000 проброшен, security group облака не блокирует трафик.
- Контейнер graylog перезапускается по кругу: пустой password_secret или обрезанный root_password_sha2. Хеш занимает ровно 64 символа.
- Кракозябры в логах: источник пишет в Windows-1251 или KOI8-R, а Graylog хранит UTF-8. Кодировку правьте на агенте.
- Время событий сдвинуто на часы: устройство отправляет локальное время без указания зоны. Настройте NTP и UTC на источниках.
Настройка inputs: подключаем Linux, Windows, Docker и сетевые устройства
Все источники заводятся по одной схеме: System → Inputs → Select input → Launch new input. Выбираете тип, узел, порт и опции парсинга. После старта откройте Show received messages: там видно, доходят ли пакеты и как они разбираются. Дальше конкретные конфиги для четырёх классов источников.
Syslog с Linux-серверов через rsyslog
Создайте input Syslog UDP на порту 1514. На клиенте добавьте файл /etc/rsyslog.d/90-graylog.conf:
# отправка всего потока в Graylog по UDP *.* @10.0.0.10:1514;RSYSLOG_SyslogProtocol23Format
Для TCP используйте два символа @: @@10.0.0.10:1514. TCP предпочтительнее: пакеты не теряются при перегрузке сети.
Чтобы не гнать на сервер отладочный шум, ограничьте поток уровнем info и обязательными facility:
*.info;mail.none;cron.none @10.0.0.10:1514;RSYSLOG_SyslogProtocol23Format authpriv.* @10.0.0.10:1514;RSYSLOG_SyslogProtocol23Format
Перезапуск и тест:
sudo systemctl restart rsyslog logger -p user.err "graylog test 123"
Запрос source:имя-хоста AND message:"graylog test" вернёт тестовую строку. Откройте порт на клиенте и сервере: ufw allow 1514/udp.
Windows: Winlogbeat и NXLog
Для журналов Windows Event Log используйте Winlogbeat и input Beats на порту 5044. Фрагмент winlogbeat.yml:
winlogbeat.event_logs:
- name: Application
ignore_older: 72h
- name: System
- name: Security
processors:
- drop_event.when.not.equals.event_id: 4624
output.logstash:
hosts: ["10.0.0.10:5044"]
Фильтр в примере оставляет из Security только события входа (4624), остальное отбрасывается на клиенте и экономит трафик.
Для текстовых логов приложений и legacy-систем удобнее NXLog с модулем xm_gelf и отправкой в GELF TCP на 12201:
<Extension gelf>
Module xm_gelf
</Extension>
<Input in_file>
Module im_file
File "C:\\Logs\\app\\*.log"
</Input>
<Output out_graylog>
Module om_tcp
Host 10.0.0.10
Port 12201
OutputType GELF_TCP
</Output>
<Route 1>
Path in_file => out_graylog
</Route>
Что выбрать: Beats input для журналов Windows, там готовые поля event_id, channel, provider; NXLog или Vector для файлов приложений и многострочных форматов. Оба варианта включаются одновременно, порты не конфликтуют.
Docker: GELF-драйвер и сбор логов контейнеров
Самый чистый способ: input GELF на 12201 и драйвер логирования gelf. Агент внутри контейнера не нужен.
docker run --log-driver=gelf --log-opt gelf-address=udp://10.0.0.10:12201 --log-opt tag=nginx --log-opt gelf-compression-type=gzip nginx:latest
В Compose то же самое описывается секцией logging:
services:
app:
image: nginx:latest
logging:
driver: gelf
options:
gelf-address: "udp://10.0.0.10:12201"
tag: "nginx-{{.Name}}"
gelf-compression-type: "gzip"
GELF UDP экономит ресурсы, но теряет пакеты при перегрузке; для критичных сервисов создайте второй input GELF TCP и укажите tcp-адрес. Многострочные события драйвер не склеивает: каждая строка уходит отдельным сообщением. Стектрейсы собирайте агентом внутри контейнера (Filebeat, Vector, Fluent Bit) или логируйте в JSON одной строкой.
Сетевые устройства: Cisco, MikroTik, pfSense
Создайте input Syslog UDP на 1514 и настройте устройства. Cisco IOS:
logging host 10.0.0.10 transport udp port 1514 logging trap informational logging source-interface Loopback0
MikroTik:
/system logging action add name=graylog target=remote remote=10.0.0.10 remote-port=1514 /system logging add topics=info action=graylog add topics=error action=graylog add topics=firewall action=graylog
pfSense: Status → System Logs → Settings → Remote Logging. Включите отправку, укажите адрес 10.0.0.10, порт 1514, формат RFC 5424. На всех устройствах выставьте NTP и зону UTC: если устройство не указывает зону, метка времени в Graylog разойдётся с реальной, и события уедут в прошлое или будущее.
Streams и pipelines: маршрутизация и обогащение сообщений
Порядок обработки сообщения: extractors на input → pipeline processors → правила streams → запись в index set. Streams отвечают за маршрутизацию и права, pipelines за парсинг и обогащение. Настройка только одной части быстро превращает поиск в свалку.
Как встроить Graylog в общий конвейер с метриками, разобрано в статье про маршрутизацию логов и метрик в DevOps.
Создание stream и правила маршрутизации
Streams → Create stream. Пример: поток Linux auth с правилами:
- Field source must match regular expression .*
- Field facility must equal auth или authpriv
Практичные потоки: Linux auth, Docker errors, Firewall denies, Kubernetes. Сообщение может попасть сразу в несколько streams, и это удвоит объём индексов. Для узких потоков включайте опцию Remove matches from Default Stream.
Порядок streams влияет на порядок выполнения привязанных pipelines, поэтому критичные потоки держите выше шумных. Права на stream выдаются ролям, об этом в разделе про доступ.
Pipeline rules: парсинг, обогащение, drop
Набор правил создаётся в Pipelines → Add new pipeline, затем привязывается к streams. Правила раскладываются по этапам (stages 0-9): этапы выполняются последовательно, порядок правил внутри этапа не гарантирован.
Удаление шума healthcheck:
rule "Drop healthchecks"
when
has_field("message") && contains(to_string($message.message), "/healthz")
then
drop_message();
end
Разбор логов приложения через Grok:
rule "Parse app log"
when
has_field("message")
then
let parsed = grok(
pattern: "%{TIMESTAMP_ISO8601:event_time} %{LOGLEVEL:app_level} %{WORD:service} %{GREEDYDATA:details}",
value: to_string($message.message),
only_named_captures: true
);
set_fields(fields: parsed);
end
Для access-логов nginx шаблон расширяется полями IPORHOST, HTTPDATE, WORD и NUMBER, а квадратные скобки и кавычки внутри шаблона экранируются.
Обогащение через lookup table: загрузите CSV вида ip,hostname,environment в System → Lookup Tables, затем добавьте правило:
rule "Enrich with environment"
when
has_field("client_ip")
then
let env = lookup("ip_to_env", to_string($message.client_ip));
set_field("environment", env);
end
Перед включением проверьте правило в симуляторе обработки на реальном образце сообщения. Сохранённый pipeline применится к новым сообщениям, переиндексация старых не запустится автоматически.
Extractors vs Pipelines: что и когда использовать
| Критерий | Extractors | Pipelines |
|---|---|---|
| Где настраиваются | На конкретном input | Глобально, с привязкой к streams |
| Условия | Нет, срабатывают всегда | Блок when с любыми проверками полей |
| Функции | Regex, Grok, копирование, подстрока | Grok, lookup, set_field, drop_message, parse_date и десятки других |
| Когда использовать | Простые legacy-сценарии, привязка к транспорту | Вся новая логика: парсинг, обогащение, фильтрация |
Не дублируйте разбор одного поля двумя механизмами: pipeline перезапишет результат работы extractor, и отладка усложнится.
Поиск, дашборды и уведомления о событиях
Полезные поисковые запросы для дежурного
Синтаксис поиска: field:value, операторы AND, OR, NOT, диапазоны [0 TO 3], wildcard *. Примеры, которые закрывают типовые вопросы в инциденте:
- level:[0 TO 3] AND source:web-* : все ошибки и критические события на вебах, уровни GELF и Syslog идут от 0 до 7;
- message:*timeout* : таймауты в любом приложении;
- source:fw-* AND action:deny : блокировки на фаерволе;
- http_response_code:[500 TO 599] AND source:nginx-* : пятисотые ответы nginx;
- NOT source:healthcheck* : убрать шум балансировщика.
Удачные запросы сохраняйте кнопкой Save: Deploy errors, DB timeouts, Auth failures. Сохранённый поиск открывается в один клик и доступен команде.
Сборка дашборда: ошибки, топ источников, тренды
Dashboards → Create dashboard. Рабочий набор виджетов для дежурной смены:
- Count by source: агрегация count, группировка по полю source, лимит 10.
- Errors by level: тот же count с запросом level:[0 TO 3] и группировкой по level.
- Latest errors: Message Table с полями timestamp, source, level, message и обновлением раз в 30 секунд.
- 5xx dynamics: временной график count с запросом http_response_code:[500 TO 599].
Каждый виджет фильтруется по времени и streams. Дашборд экспортируется в JSON через Content Packs: храните его в git и переносите между стендами одной операцией импорта. Доступ выдавайте в режиме просмотра, чтобы виджеты не переписались случайными правками.
Event definitions и уведомления в Slack/Email
Alerts → Event Definitions → Create event definition, тип Filter & Aggregation. Условие собирается из поискового запроса и агрегации. Пример для вебов: запрос level:[0 TO 3] AND source:web-*, агрегация count() > 20 за 5 минут, группировка по source, grace period 10 минут.
Email требует настроек SMTP в server.conf: transport_email_enabled, transport_email_hostname, transport_email_port, transport_email_use_tls, учётные данные и transport_email_from_email. Slack и другие сервисы подключаются HTTP-уведомлением: POST на webhook с JSON-телом, куда поля события подставляются через плейсхолдеры.
Проверьте канал тестовым уведомлением сразу после настройки. Grace period и отключённые повторные уведомления защищают дежурного от лавины одинаковых алертов, а раздельные определения для предупреждений и критичных событий помогают расставить приоритеты.
Управление индексами и retention: как не утонуть в диске
Данные в OpenSearch лежат в индексах, которыми управляют index sets. Откройте System → Indices → Create index set: префикс, число shards, replicas, стратегия ротации и срок хранения.
- Shards: 1 shard на 30 ГБ данных. Для одиночного узла ставьте 1 shard и 0 реплик.
- Rotation: по времени (P1D) или по размеру (1 ГБ). Частая ротация ускоряет поиск и упрощает удаление старых индексов.
- Retention: Delete after N days. Стандарт для прода 30 дней, для аудита 365, для debug 7.
Расчёт диска: суточный объём × срок хранения × (1 + число реплик) + journal. Миллион сообщений после сжатия занимает примерно 0,7-1,5 ГБ, дальше считайте по своему потоку.
Смена retention не трогает существующие индексы: старые удаляйте вручную через System → Indices. Свободное место и заполнение journal видны в System → Overview, проверяйте их перед каждым релизом.
Выгрузка архивов в S3 доступна в коммерческих редакциях Graylog. В open source вариантов два: держать дешёвый диск под ротацию или экспортировать нужные выборки через API. Политики ILM в OpenSearch применяют, когда хранилище обслуживает отдельная команда; иначе rotation и retention внутри index set проще и предсказуемее. Практические конфигурации собраны в статье хранение и ротация логов в продакшене.
Создание отдельного index set для критичных логов
System → Indices → Create index set. Пример для аудита: title audit, prefix audit, shards 1, replicas 0, rotation P1D, retention 365 дней. Затем привяжите поток: Streams → нужный stream → Edit → Index Set → audit, и включите Remove matches from Default Stream.
Для шумных debug-логов заведите второй index set: rotation по размеру 1 ГБ, retention 7 дней. Разделение даёт две вещи: критичные события живут год, а отладочный поток не съедает диск.
Права доступа и типовые ошибки при подключении источников
Роли и права: минимально необходимый доступ
Встроенные роли Admin и Reader покрывают крайние случаи. Для команд создавайте роли с точными правами: глобальное право streams:read, доступ к конкретному stream через Share, отдельные права на dashboards и searches.
- Пользователь без прав на stream не увидит его сообщения ни в поиске, ни в дашбордах.
- API-токены создаются в профиле: Profile → API tokens → Create. Храните токены в секретах CI, не в коде.
- Встроенного admin используйте для первичной настройки, дальше заведите именные учётки в Users с нужными ролями.
- Проверяйте доступ глазами коллеги: зайдите под тестовым пользователем и убедитесь, что лишние streams скрыты.
Чек-лист: логи не приходят, что проверить
- Input в статусе Running и привязан к тому же узлу, куда идёт трафик.
- Порт слушается: ss -lunp | grep 1514 для UDP, ss -ltnp | grep 1514 для TCP.
- Firewall и security group открыты на обеих сторонах: ufw allow 1514/udp, правила nftables или iptables.
- Формат сообщения совпадает с типом input: GELF в Syslog input не распарсится.
- Часовой пояс источника: сдвиг времени прячет сообщения за пределами выбранного диапазона.
- Кодировка UTF-8: Windows-1251 даёт кракозябры, а иногда и потерю полей.
- Трафик доходит: tcpdump -i any -n udp port 1514 в течение 10 секунд.
- Сообщения видны в Input → Show received messages.
- Поиск без фильтров: расширьте диапазон до суток и очистите строку запроса.
- Серверные логи: /var/log/graylog-server/server.log и журнал в System → Overview.
- Потери UDP: переключите источник на TCP и проверьте повторно.
Порядок проверок экономит время: сначала выясните, доходит ли трафик до сервера, потом разбирайтесь с парсингом и полями.
Кракозябры, обрезанные сообщения и multiline
Кракозябры появляются, когда источник отправляет текст в Windows-1251 или KOI8-R. Graylog хранит UTF-8, поэтому кодировку исправляют на агенте: в NXLog задайте кодировку файла, в Vector и Fluent Bit есть подходящие опции, на Linux проверьте LANG и локаль приложения.
Обрезанные сообщения приходят из-за лимитов UDP и MTU. rsyslog по умолчанию ограничивает размер сообщения примерно 8 КБ, поднимите MaxMessageSize, а для длинных строк переходите на TCP. Драйвер gelf в Docker тоже режет слишком длинные записи, для них используйте GELF TCP или агент внутри контейнера.
Multiline GELF не поддерживает: стектрейс Java или Python приезжает десятком сообщений. Варианты решения: multiline на агенте (Filebeat, Vector, Fluent Bit), структурное логирование в JSON одной строкой либо Beats input для Windows Event Log, где склейка не требуется.
Итог: с чего начать и что делать дальше
Минимальный план на первые два часа:
- Поднимите сервер 4 vCPU / 8 ГБ RAM, примените vm.max_map_count и отключите swap.
- Запустите docker compose и войдите в веб-интерфейс.
- Создайте Syslog input на 1514 и подключите один Linux-сервер через rsyslog.
- Проверьте поиск, затем создайте stream для ошибок с правилом level:[0 TO 3] и отдельный index set с retention 30 дней.
- Настройте event definition и уведомление в Slack или email.
- Соберите дашборд из четырёх виджетов: источники, уровни, таблица ошибок, график 5xx.
Дальше расширяйте охват: pipelines для nginx и приложений, lookup-таблицы с окружениями, RBAC для команд, контроль диска и journal. Обновляйте Graylog и OpenSearch по плану: мажорные версии меняют формат конфигов.
Если выбираете платформу для следующего стенда, держите под рукой сравнение систем сбора и анализа логов в 2026: там docker-compose для быстрого старта и рекомендации под Kubernetes, аудит и SIEM. Для экспериментов с разбором инцидентов нейросетью подойдёт агрегатор API, например AiTunnel: доступ к GPT, Gemini и Claude по одному ключу без VPN.