rails
May 27

Как пережить DEPRECATION WARNING без психологической травмы

Всем привет! Сегодня я расскажу о нескольких способах поиска deprecation warnings при обновлении версии rails на старом проекте.

Небольшая вводная

Всякий из нас хотя бы раз сталкивался с ситуацией, когда проект использует устаревшую версию Ruby on Rails. Например, у вас может быть установлен Rails 5, в то время как большинство уже перешло на Rails 6 или 7. И рано или поздно вам придется столкнуться с задачей обновления версии Rails, что неизбежно приведет к появлению предупреждений о устаревании функций (deprecation warnings).

В этой статье описаны три подхода к легкому (или почти легкому) поиску всех deprecation warnings:

  • Базовый
  • Расширенный
  • Мечтательный

Способ "Базовый"

Если на каком-то из стендов в конфигах (config/environments/production.rb) у вас установлено config.active_support.deprecation = :log, то вам подойдет этот способ.

Шаг 1: Скачать лог(и) по ssh

# Скачиваем лог с сервера по ssh
rsync -apr user@host:port:/rails-app/log/production.log ~/downloads

Шаг 2: Обработка лога и поиск предупреждений об устаревании

cd ~/downloads
# Ищем строки с предупреждениями о устаревании, очищаем их от лишнего текста,
# Сортируем и убираем дубликаты, записываем результат в файл
grep 'DEPRECATION WARNING' production.log | sed 's|.*WARNING||' | sort -u > file.txt

Шаг 3: Ручное исправление устаревших методов в проекте

Используем результаты из файла file.txt для поиска методов в проекте. Исправляем найденные методы, заменяя их на новые версии.

Если методы не найдены в проекте, но есть в логах, то, вероятно, они используются в гемах. В этом случае нужно проверить зависимости проекта и обновить гемы, которые используют устаревшие методы.

Шаг 4: Использование grep для поиска устаревших методов в гемах

# Ищем, например, метод alias_method_chain в директории с гемами
grep -r alias_method_chain ~/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.1/gems/

Grep будет выводить результаты поиска, включая имя файла и саму строку, содержащую метод. Это поможет вам определить, в каком геме и файле находится этот метод.

Стоит отметить, что если у вас централизованный сбор логов (Graylog/ELK), то первые 2 шага будут отличаться. Вместо этого можно использовать функцию поиска, предоставляемую интерфейсом Graylog/ELK.

Недостатки этого подхода

1. Ограниченная активность на стенде.

Возможно, не все функции используются на стенде, что может привести к тому, что не все устаревшие методы будут отражены в логах.

2. Недостаточная история логов.

Если логи были включены недавно, то они могут не содержать всей информации об устаревших методах, что может привести к пропуску некоторых проблем.

Способ "Расширенный"

Установить config.active_support.deprecation = :notify и с помощью ActiveSupport::Notifications можно создать кастомный отлов предупреждений об устранении метода и отправлять в систему отслеживания ошибок.

Ниже пример с отправкой в чат телеграмма.

ActiveSupport::Notifications.subscribe('deprecation.rails') do |_name, _start, _finish, _id, payload|
  message = "Предупреждение об устаревании: #{payload[:message]}"
  Faraday.post "https://api.telegram.org/bot#{TG_TOKEN}/sendMessage", { chat_id: CHAT_ID, text: message }
rescue StandardError => e
  Rails.logger.error "Проблема с отправкой предупреждения: #{e.message}"
end

Недостатки этого подхода

1. Ограниченная активность на стенде

В целом, точно такая же проблема, как и в прошлом варианте.

2. Кривой код может положить стенд

В случае ошибки (не пойманного исключения) стенд может быть полностью парализован. Следует принять меры для явного подавления ошибок.

3. Большая активность на стенде

При высокой активности на стенде и большом кол-ве устаревших методов можно заспамить себя уведомлениями 🙂 (Sentry устраняет эту проблему).

Способ "Мечтательный"

Этот способ позволяет эффективно бороться с предупреждениями об устаревании. Правда, необходимо иметь хорошее покрытие тестами, желательно 100%.

Если так и есть, то рад за вас, но не от всего сердца 🙂 Если меньше, то остается только мечтать.

В файле config/environments/test.rb добавить строку config.active_support.deprecation = :raise

После этого запустить тесты и исправить все упавшие.

Заключение

Кроме того, есть полезный инструмент https://github.com/shopify/deprecation_toolkit, который может помочь в борьбе с устаревшими методами. Однако, мой основной совет - регулярно обновляйте свои зависимости и не допускайте, чтобы ваш кодовая база стала неудобоваримой. Делайте обновление Rails регулярной задачей, и ваша жизнь станет намного проще.

Благодарности

Анатолию Сахацкому за помощь в сборе материалов для статьи