Files
Ubuntu_docs/Logs/Vector_dev_install_telegram.md
2025-06-25 23:00:43 +05:00

13 KiB
Raw Blame History

Шаг 1: Создание Telegram-бота Зарегистрируйте бота через BotFather:

Откройте Telegram и найдите @BotFather. Отправьте команду /start. Отправьте /newbot, чтобы создать нового бота. Следуйте инструкциям: Укажите имя бота (например, MyLogBot). Укажите username бота, заканчивающийся на bot (например, @MyLogAllBot). После создания вы получите токен (например, 8007457609:AAGnrXOSaoxODMSh4yCzUEIp0uxfH3Hk8ws). Сохраните его, он понадобится для API.

Настройка Vector для отправки логов в Gotify

Эта инструкция описывает, как установить Vector, настроить его для чтения JSON-логов из файла /opt/org_ccalm_main/logs/ccalm.log, фильтрации строк с уровнем ERROR и отправки уведомлений в Gotify.


0. Подключаемся к инфраструктуре

  ssh ubuntu@almaty.ccalm.org -p 22

Предварительные требования

  • ОС: Ubuntu/Debian (для других ОС уточните, чтобы адаптировать команды).
  • Файл логов: /opt/org_ccalm_main/logs/ccalm.log с JSON-строками (поля level и message).
  • Gotify: Доступный сервер Gotify с URL и токеном (например, https://gotify.example.com/message?token=<your-token>).
  • Доступ к терминалу с правами sudo.

Шаг 1: Установка Vector

Пробуем скачать deb пакет с сайта

curl -L https://packages.timber.io/vector/0.46.X/vector_0.46.1-1_amd64.deb -o vector_0.46.1-1_amd64.deb &&
sudo dpkg -i vector_0.46.1-1_amd64.deb &&
sudo apt-get install -f &&
vector --version

That make deleting:

sudo apt remove --purge vector

Шаг 2: Создание конфигурации Vector

Vector использует YAML для конфигурации. Настроим чтение логов, фильтрацию ERROR и отправку в Gotify.

  1. Создайте файл конфигурации /etc/vector/vector.yaml:
cd /etc/vector &&
sudo tee vector.yaml > /dev/null <<'EOF'
data_dir: "/var/lib/vector"

sources:
  ccalm_logs:
    type: file
    include:
      - /opt/org_ccalm_main/logs/org-ccalm-main.log
    read_from: beginning

  ccalm_translation_logs:
    type: file
    include:
      - /opt/org_ccalm_translation/logs/org-ccalm-translation.log
    read_from: beginning

  ccalm_dbms_logs:
    type: file
    include:
      - /opt/org_ccalm_dbms/logs/org-ccalm-dbms.log
    read_from: beginning

  ccalm_jwt_logs:
    type: file
    include:
      - /opt/org_ccalm_jwt/logs/org-ccalm-jwt.log 
    read_from: beginning

transforms:
  parse_json_ccalm:
    type: remap
    inputs:
      - ccalm_logs
    source: |
      structured, err = parse_json(.message)
      if err != null {
        abort
      }
      merged, err = merge(., structured)
      if err != null {
        abort
      }
      . = merged

  parse_json_translation:
    type: remap
    inputs:
      - ccalm_translation_logs
    source: |
      structured, err = parse_json(.message)
      if err != null {
        abort
      }
      merged, err = merge(., structured)
      if err != null {
        abort
      }
      . = merged

  parse_json_dbms:
    type: remap
    inputs:
      - ccalm_dbms_logs
    source: |
      structured, err = parse_json(.message)
      if err != null {
        abort
      }
      merged, err = merge(., structured)
      if err != null {
        abort
      }
      . = merged

  parse_json_jwt:
    type: remap
    inputs:
      - ccalm_jwt_logs
    source: |
      structured, err = parse_json(.message)
      if err != null {
        abort
      }
      merged, err = merge(., structured)
      if err != null {
        abort
      }
      . = merged

  filter_errors_ccalm:
    type: filter
    inputs:
      - parse_json_ccalm
    condition: '.level == "ERROR" || .level == "WARN"'

  filter_errors_translation:
    type: filter
    inputs:
      - parse_json_translation
    condition: '.level == "ERROR" || .level == "WARN"'

  filter_errors_dbms:
    type: filter
    inputs:
      - parse_json_dbms
    condition: '.level == "ERROR" || .level == "WARN"'

  filter_errors_jwt:
    type: filter
    inputs:
      - parse_json_jwt
    condition: '.level == "ERROR" || .level == "WARN"'

  format_telegram_json_ccalm:
    type: remap
    inputs:
      - filter_errors_ccalm
    source: |
      msg, err = string(.message)
      if err != null {
        msg = "Unable to parse message"
      }
      marker_str = ""
      if exists(.marker) {
        m, err = string(.marker)
        if err == null && length(m) > 0 {
          marker_str = "Marker: ```text\n" + m + "```"
        }
      }
      level_str = ""
      icon_str = ""
      if exists(.level) {
        m, err = string(.level)
        if err == null {
          level_str = "level: ```text\n" + m + "```"
        }
        if m == "ERROR" {
          icon_str = "‼"
        }
        if m == "WARN" {
          icon_str = "⚠️"
        }
      }
      .message = "{\"chat_id\":\"-1002640082189\",\"message_thread_id\":2,\"text\":\"" + icon_str + " " + level_str + marker_str + "Message: ```text\n" + msg + "```\", \"parse_mode\":\"Markdown\"}"

  format_telegram_json_translation:
    type: remap
    inputs:
      - filter_errors_translation
    source: |
      msg, err = string(.message)
      if err != null {
        msg = "Unable to parse message"
      }
      marker_str = ""
      if exists(.marker) {
        m, err = string(.marker)
        if err == null && length(m) > 0 {
          marker_str = "Marker: ```text\n" + m + "```"
        }
      }
      level_str = ""
      icon_str = ""
      if exists(.level) {
        m, err = string(.level)
        if err == null {
          level_str = "level: ```text\n" + m + "```"
        }
        if m == "ERROR" {
          icon_str = "‼"
        }
        if m == "WARN" {
          icon_str = "⚠️"
        }
      }
      .message = "{\"chat_id\":\"-1002640082189\",\"message_thread_id\":24,\"text\":\"" + icon_str + " " + level_str + marker_str + "Message: ```text\n" + msg + "```\", \"parse_mode\":\"Markdown\"}"

  format_telegram_json_dbms:
    type: remap
    inputs:
      - filter_errors_dbms
    source: |
      msg, err = string(.message)
      if err != null {
        msg = "Unable to parse message"
      }
      marker_str = ""
      if exists(.marker) {
        m, err = string(.marker)
        if err == null && length(m) > 0 {
          marker_str = "Marker: ```text\n" + m + "```"
        }
      }
      level_str = ""
      icon_str = ""
      if exists(.level) {
        m, err = string(.level)
        if err == null {
          level_str = "level: ```text\n" + m + "```"
        }
        if m == "ERROR" {
          icon_str = "‼"
        }
        if m == "WARN" {
          icon_str = "⚠️"
        }
      }
      .message = "{\"chat_id\":\"-1002640082189\",\"message_thread_id\":9,\"text\":\"" + icon_str + " " + level_str + marker_str + "Message: ```text\n" + msg + "```\", \"parse_mode\":\"Markdown\"}"

  format_telegram_json_jwt:
    type: remap
    inputs:
      - filter_errors_jwt
    source: |
      msg, err = string(.message)
      if err != null {
        msg = "Unable to parse message"
      }
      marker_str = ""
      if exists(.marker) {
        m, err = string(.marker)
        if err == null && length(m) > 0 {
          marker_str = "Marker: ```text\n" + m + "```"
        }
      }
      level_str = ""
      icon_str = ""
      if exists(.level) {
        m, err = string(.level)
        if err == null {
          level_str = "level: ```text\n" + m + "```"
        }
        if m == "ERROR" {
          icon_str = "‼"
        }
        if m == "WARN" {
          icon_str = "⚠️"
        }
      }
      .message = "{\"chat_id\":\"-1002640082189\",\"message_thread_id\":4,\"text\":\"" + icon_str + " " + level_str + marker_str + "Message: ```text\n" + msg + "```\", \"parse_mode\":\"Markdown\"}"


sinks:
  telegram_ccalm:
    type: http
    inputs:
      - format_telegram_json_ccalm
    uri: "https://api.telegram.org/bot8007457609:AAGnrXOSaoxODMSh4yCzUEIp0uxfH3Hk8ws/sendMessage"
    method: post
    encoding:
      codec: text
    request:
      headers:
        Content-Type: "application/json"
    batch:
      max_events: 1

  telegram_translation:
    type: http
    inputs:
      - format_telegram_json_translation
    uri: "https://api.telegram.org/bot8007457609:AAGnrXOSaoxODMSh4yCzUEIp0uxfH3Hk8ws/sendMessage"
    method: post
    encoding:
      codec: text
    request:
      headers:
        Content-Type: "application/json"
    batch:
      max_events: 1

  telegram_dbms:
    type: http
    inputs:
      - format_telegram_json_dbms
    uri: "https://api.telegram.org/bot8007457609:AAGnrXOSaoxODMSh4yCzUEIp0uxfH3Hk8ws/sendMessage"
    method: post
    encoding:
      codec: text
    request:
      headers:
        Content-Type: "application/json"
    batch:
      max_events: 1

  telegram_jwt:
    type: http
    inputs:
      - format_telegram_json_jwt
    uri: "https://api.telegram.org/bot8007457609:AAGnrXOSaoxODMSh4yCzUEIp0uxfH3Hk8ws/sendMessage"
    method: post
    encoding:
      codec: text
    request:
      headers:
        Content-Type: "application/json"
    batch:
      max_events: 1
EOF

curl https://api.telegram.org/bot8007457609:AAGnrXOSaoxODMSh4yCzUEIp0uxfH3Hk8ws/getUpdates

Пробую отправку через curl

curl -X POST -k "https://gotify.geovizor.top:8443/message?token=AYmcpr43YtPKDmZ" \
  -H "Content-Type: application/json" \
  -d '{"message": "Test message", "priority": 5}'

Проверяем что gotify работает:

curl -k -X POST -H "Content-Type: application/json" -H "Host: gotify.geovizor.top" -d '{"message":"Test message 00","priority":5}' --http1.1 https://gotify.geovizor.top:8443/message?token=AYmcpr43YtPKDmZ -v

Объяснение конфигурации

  • Source (ccalm_logs): Читает логи из файла, парсит JSON, поддерживает многострочные логи.
  • Transform (filter_errors): Фильтрует логи с level: "ERROR".
  • Sink (gotify): Отправляет отфильтрованные логи в Gotify через HTTP POST.

Шаг 3: Проверка конфигурации

Проверьте корректность YAML:

vector --config /etc/vector/vector.yaml validate

Ожидаемый вывод: Configuration is valid.

Шаг 4: Запуск Vector

Тестовый запуск (для отладки)

sudo vector --config /etc/vector/vector.yaml

Запуск как сервиса

  1. Включите и запустите сервис:
  sudo systemctl enable vector
  sudo systemctl start vector
  1. Проверьте статус:
   sudo systemctl status vector
   sudo systemctl stop vector

Шаг 5: Проверка отправки в Gotify

  1. Убедитесь, что Gotify доступен по указанному URL.
  2. Добавьте тестовую строку лога в /opt/org_ccalm_main/logs/ccalm.log:
echo '{"level": "ERROR", "marker":"12345", "message": "Database connection failed 0", "timestamp": "2025-05-18T12:28:00Z"}' | sudo tee -a /opt/org_ccalm_jwt/logs/org-ccalm-jwt.log
  1. Проверьте Gotify (веб-интерфейс или приложение) — должно прийти уведомление с заголовком "CCALM Log Error" и сообщением "Database connection failed".

Шаг 6: Отладка

  • Логи Vector: /var/log/vector/vector.log или stdout (в тестовом режиме).
  • Проверьте логи при проблемах:
  cat /var/log/vector/vector.log

Дополнительные настройки

  • Права доступа к файлу логов:
  sudo chown vector:vector /opt/org_ccalm_main/logs/ccalm.log
  sudo chmod 644 /opt/org_ccalm_main/logs/ccalm.log
  • Если JSON-формат отличается: Если поле level называется иначе (например, log_level), замените .level на .log_level в condition.
  • HTTP вместо HTTPS: Если Gotify использует HTTP, замените https:// на http:// в uri.

Примечания

  • Убедитесь, что Gotify настроен и токен действителен.
  • Если логи не отправляются, проверьте сетевую доступность Gotify и правильность URL/токена.
  • Для чтения только новых логов удалите read_from: beginning в конфигурации.