Заметки

Блог Никиты Самохвалова, обо всём и ни о чём.

Надёжное подключение приватных НПМ-пакетов

Как подключать публичные или приватные пакеты, опубликованные в npmjs.com — более-менее понятно. Но иногда нужно разместить репозиторий с библиотекой в своём хранилище (например, корпоративном «Гитлабе»), чтобы скрыть код от посторонних глаз (допустим, что-то узкоспециализированное под конкретный проект).

Менеджер пакетов НПМ может выкачивать зависимости как по ХТТП, так и по ССХ. У использования каждого протокола есть свои плюсы и минусы, но я предпочитаю работать по ССХ.

Предположим, что у нас есть свой «Гитлаб» по адресу gitlab.company.ru, а в нём репозиторий lazarus. Попробуем его подключить:

npm i git+ssh://git@gitlab.company.ru:lazarus.git

Но такое подключение рано или поздно приведёт к неприятным последствиям: мы не указали мажорную версию библиотеки. Исправим это:

npm i git+ssh://git@gitlab.company.ru:lazarus.git#semver:^v1

Теперь, если выйдет мажорный релиз (вер. 2), наше приложение по-прежнему будет работать с первой версией, даже если кто-то обновил все зависимости проекта.

Опытные разработчики пакетов применяют семантическое версионирование. В этом случае достаточно указать мажорную версию (цифру из первого разряда) и не бояться минорных обновлений и исправлений ошибок и дыр в безопасности (что весьма важно). Но в особо экстремальных случаях можно указывать версию вплоть до патча:

npm i git+ssh://git@gitlab.company.ru:lazarus.git#semver:^v1.3.3

«Девопсов» не существует

Девопс-инженеров не существует. Девопс-программистов тоже не существует. Девопс-профессий не бывает, так же как не бывает аджайл-менеджеров. Никому же в голову не придёт величать себя гибким руководителем проектов?

Есть профессии, а есть методологии и навыки. Приобретая навыки администрирования и создания инфраструктуры ИС, программист не становится «девопсером». И наоборот, научившись программировать, системный администратор не становится «девопсером». Оба расширяют свой кругозор и профессиональные навыки, что позволит однажды называть себя инженерами.

В некоторых компаниях в названия отделов добавляют приставку «девопс». Разумеется, ничего, кроме иллюзий и чувства обмана и недосказанности это не приносит. А в названиях вакансий приставка «девопс» используется или с целью пустить пыль в глаза, или по причине банальной неграмотности.

Такое изощрённое внедрение методологии может привести к её отторжению сотрудниками компании и разочарованию в глазах руководства.

Девопс — это философия и определённый набор практик, призванных ускорить поставку ПО и окончательно устранить пропасть в отношениях между людьми и отделами, работающими по гибкой (аджайл) методологии разработки ПО.

2017   девопс

Вебинар о «тонком» коде

Шаблоны проектирования, влияющие на архитектуру всего приложения — основополагающая вещь. Чаще всего ошибки совершаются именно при работе над архитектурой системы. А архитектурные ошибки, как известно, самые дорогие.

В эту среду на вебинаре о «тонком» коде я попытался рассмотреть азы проектирования архитектуры, при которой код не превращается в лапшу из сотен, а иногда и тысяч строк. Ничего нового, но старые добрые практики:

Дополнительные материалы:

  1. Мартин Фаулер о сервисном слое и CQRS.
  2. Серия обучающих статей о DDD и сервисном слое.
  3. «Куда поместить код: статический метод или сервис?»
  4. Командная шина в «Ларавеле».

Отношения в «Йии»

Разрабатывая в «Йии 2» интерфейсы управления данными, которые имеют различные связи и отношения, сразу же сталкиваешься с проблемой управления этими самыми связями и отношениями.

Например
Представим, что есть три таблицы: новости, категории, и связи «многие ко многим» новостей с категориями. В РЕСТ-сервис прилетает запрос от клиента на создание новости. Среди прочего, в запросе переданы идентификаторы категорий, к которым относится новость. Так вот, «Йии», с его экшеном создания, не сможет сгенерировать запись для таблицы связей новостей с категориями. Он просто не умеет так, для этого нужно писать дополнительную логику обработки идентификаторов категорий в сервисном слое или модели. Или… Использовать расширение, которое само сделает всю грязную работу.

Мы в «Нотамедии» сделали и протестировали на десятке проектов расширение с незамысловатым названием yii2-relation, которое содержит поведение, управляющее записями в связанных моделях. Просто подключите и укажите, какими отношениями нужно управлять. И не нужно дописывать модель. И не нужно изменять экшен.


composer require notamedia/yii2-relation

Репозиторий

Логирование из «Йии» в «Сентри»

Недавно исполнился год одному маленькому, но полезному расширению с «Сентри-логером» для фреймворка «Йии-2». Бета-версию я опубликовал 29 декабря 2015 года. В то время поиск существующих решений не принёс больших успехов: имеющиеся в открытом доступе логеры либо плохо сопровождались, либо имели недостаточную нам функциональность.

Наш логер позволяет прикладывать к сообщениям теги и контекстную информацию, умеет модифицировать экстра-поля через колбек-функцию в конфигурации компонента, покрыт юнит-тестами и совместим со всеми актуальными версиями ПХП. Ничего особенного, просто аккуратное и гибкое расширение для интеграции «Йии» с «Сентри».


composer require notamedia/yii2-sentry

Репозиторий


Полезные советы

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

return [
    'components' => [
        'log' => [
            'traceLevel' => YII_DEBUG ? 3 : 0,
            'targets' => [
                [
                    'class' => 'notamedia\sentry\SentryTarget',
                    'dsn' => 'http://sentry/13',
                    'levels' => ['error', 'warning'],
                ],
                [
                    'class' => 'yii\log\FileTarget',
                    'levels' => ['error', 'warning'],
                ],
            ],
        ],
    ],
];

Из-за отложенного экспорта в логерах «Йии», сообщения от долгоиграющих консольных процессов (крон-задачи и воркеры) могут крайне долго не записываться в логи. Поэтому, для консольных приложений устанавливайте свойства exportInterval и flushInterval в значение 1:

return [
    'components' => [
        'log' => [
            'flushInterval' => 1,
            'targets' => [
                [
                    'class' => 'yii\log\FileTarget',
                    'exportInterval' => 1
                ],
            ],
        ],
    ],
];

В противном случае, в логах не появятся сообщения до тех пор, пока логер «Йии» не наберёт достаточное количество, что бы записать их все махом.

Читайте так же: «Протоколирование в программировании».

УИК-2016

6 декабря я выступал на УИКе в Ижевске с докладом «DevOps от А до Я». Это было обзорное выступление: что из себя представляет данная методология, из каких составляющих формируется девопс как таковой, что и как автоматизировать инженерам, зачем и кому вообще нужен девопс.

Большое спасибо организаторам УИКа за приглашение и гостеприимство!

Термин «девопс» зачастую употребляют неверно, называя им должность сотрудника (любимый ход кадровиков), высококвалифицированного инженера или даже воркфлоу в системе контроля версий (да-да, и такое объяснение я слышал), со всеми вытекающими: подразумевая каждый что-то своё, люди общаются на разных языках, что в итоге может привести к полному непониманию этой методологии и её отторжению.

Мне нравится философия девопса. Натерпевшись бюрократии в эксплуатации веб-проектов, насмотревшись на проблемы их непрерывной разработки, я выступаю с докладами о девопсе и охотно делюсь своим опытом. Вы можете скачать мою презентацию с митапа на УИКе или пригласить меня к себе в гости поговорить об этой методологии :-)

Доклад про методологию DevOps

В четверг я выступал с докладом «DevOps: дирижируем оркестром» на десятой встрече «Симфониакс». Встреча проходила на мансарде «Рамблера».

Доклад рассказывает об опыте «Нотамедии», в которой я работаю и помогаю внедрять данную методологию. Половина моего повествования уделена вопросам коммуникаций между людьми и командами, а так же процессами производства и эксплуатации продукта. Эта тема не менее важна, чем автоматизация и использование крутых инструментов, потому что половина успеха зависит именно от того, как построена работа и взаимодействие людей. Вопросы автоматизации тоже были затронуты, хоть и коротко (на выступление даётся всего 20 минут).

Видео всего митапа опубликовано на «Фейсбуке».

Консоль, «Битрикс» и непрерывная интеграция

И снова вести с полей открытого кода. В начале года я опубликовал «Консольный Джедай» для «1С-Битрикса». Он содержит широкий набор консольных команд, позволяет легко подружить сайт с системной непрерывной интеграции, а так же писать нормальные агенты для «Битрикса». «Джедай» построен на компоненте «Симфони-консоль»: аккуратный код, хорошая функциональность и широкий выбор сторонних консольных команд гарантирован.

Коротко о том, почему стоит начинать разработку проекта с установки «Джедая»:

  1. Управляйте настройками окружений, в котором может работать сайт.
  2. Оперируйте мощным, удобным АПИ для создания агентов.
  3. Используйте инструменты для подключения к системе непрерывной интеграции.
  4. Концентрируйтесь на логике приложения, а не index.php-портянках с нетривиальным подключением ядра.

На «Бэксе» есть вводная статья, а на «Ютубе» видео доклада с вебинара «Опенсорс-решений для „1С-Битрикса“ — 2016». Эти материалы и документация помогут лучше познакомиться с библиотекой.


«Джедай» уже используют в бою: агентство «Нотамедия», студии «Артикул-медиа», «Максимастер» и «Цитрус», порталы «Новый Калининград» и «Главная дверь».


composer require notamedia/console-jedi

Репозиторий

Интернационализация инфоблоков

Недавно я сделал модуль интернационализации инфоблоков «1С-Битрикса». В интерфейсе панели управления появляется кнопка создания элемента на другом языке. При этом, все записи одного элемента разных языковых версий будут иметь один и тот же публичный идентификатор, что позволит сделать на сайте переключалку между языковыми версиями материалов.

Для того, что бы инфоблок стал интернационализированным, его необходимо сконвертировать с помощью АПИ модуля:

<?php

use Bitrix\Main\Loader;
use Notamedia\i18n\Iblock\Converter\IblockManager;

// 1. Installation module notamedia.i18n

// 2. Convertion info block
if (Loader::includeModule('notamedia.i18n')) {
    $iblockId = 1; // ID of your info block

    $manager = new IblockManager($iblockId);
    $manager->convert('PUBLIC_ID', 'LANG', 'ru');
}

«Битрикс» я стараюсь не использовать, а его «инфоблоки» и подавно, но появилась задача довольно быстро и просто сделать интернационализацию инфоблока с небольшим объёмом данных. Поэтому, у модуля отсутствует интерфейс для конвертации инфоблоков, нет юнит-тестов. Возможно, кто-то будет использовать модуль для решения подобной задачи и даст ему второе дыхание.


composer require notamedia/bitrix-i18n

Репозиторий

Конвертацию инфоблоков рекомендую производить через миграции БД.

Протоколирование в программировании

Сайтам, так же как и самолётам, нужны «чёрные ящики», помогающие выяснять подробности изменений в системе или оперативно определять источники сбоев. Рано или поздно возникнет вопрос: «кто вносил изменения в эту запись?», «когда и кем был загружен файл?», «что делал этот посетитель?» Вопрос по-страшнее: «почему это не работает?» На эти, и многие другие вопросы, связанные с протоколированием, будет отвечать инженер, занимающийся поддержкой сайта. Поэтому, хороший программист на этапе разработки любезно и щедро внедряет логирование.

Работа воркеров, обработка запросов пользователей, нештатные ситуации в функционировании приложения — всё это должно логироваться. Цель логирования заключается не только в том, что бы зафиксировать факт какого-либо события, но и в том, что бы предоставить инженеру, занимающемуся поддержкой проекта, исчерпывающую информацию о произошедшем событии, которая позволит упростить и ускорить процесс отладки.

Правила хорошего лога

Приведу несколько правил логирования, сформировавшихся у меня за время работы над сайтами и различными веб-сервисами.

1. Помощь

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

2. Контекст

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

3. Категоризация

Логи нужно «раскидывать» по категориям, что бы было удобнее их анализировать.

4. Мониторинг

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

5. Резервирование

Если вы пишите логи в БД проекта (очень плохой вариант) или во внешние системы (например, «Сентри»), добавляйте в приложение резервный логер, параллельно пишущий в файл на сервере.

Рассмотрим несколько наглядных примеров.

Плохо

Хорошо

Не удалось получить данные RSS.

Level: error.

Не удалось прочитать данные из RSS.

Level: error.

Category: news_import.

Source: http://site.ru/rss.

HTTP status of source: 503.

Trace: <…>.

Ошибка отправки данных.

Level: ошибка.

Не удалось экспортировать статистику в ЦРМ.

Level: error.

Category: statistics_import.

Server: http://site-crm.ru/api/statistic.

Request: <…>.

HTTP status: 500.

Response: <…>.

Trace: <…>.

Произошла критическая ошибка.

Level: emergency.

Ошибка создания новости в БД.

Level: emergency.

Category: news.

Query: <…>.

Trace: <…>.

Ошибка в форме обратной связи.

Уровень: ошибка.

Невалидное сообщение из формы обратной связи.

Level: info.

Category: feedback.

Query: <…>.

User IP: <…>.

User Agent: <…>.

Cookies: <…>.

Session: <…>.

Browser: <…>.

Trace: <…>.

Агрегация

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

Выкатили релиз на тестовую площадку — что-то пошло не так.

Например, выкатив очередной релиз на тестовую площадку, сравните объём записей до и после. Если он непредвиденно резко изменился — что-то пошло не так. И конечно же, настройте рассылку оповещений, что бы в случае ошибок вы моментально о них узнали.

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

Что бы не быть голословным, приведу в пример один из своих проектов. У нас была форма обратной связи, и в какой-то момент часть пользователей начали жаловаться на сообщения об ошибках: «сервис временно недоступен». Однако, в логах бекенда подобных ошибок ни разу не фиксировалось.

Форма была весьма важной частью сайта, критичный функционал, так сказать. Поэтому я логировал абсолютно все уровни ошибок, в т. ч. некорректно заполненные формы от пользователей. Проанализировав такие логи, я обнаружил интересную аномалию — иногда клиент присылал на бекенд сообщения, в которых отсутствовала часть обязательных полей. Без их заполнения клиент просто не мог отправить запрос серверу. Спамеры? Нет, текст сообщений был совершенно адекватен. Запросы присылались в обход «толстого клиента» сайта? Нет, другого приложения не было.

Изучив подробнее метаданные, выяснилось, что пользователи переходили на страницу с формой обратной связи по прямой, некорректной, гиперссылке. По удивительному стечению обстоятельств, на этот некорректный запрос «толстый клиент» отображал и отправлял только часть полей формы, и, конечно же, бекенд считал такой запрос невалидным.

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

Установите удобную систему агрегации логов и она ещё не раз вас выручит. «Кибана», «Сентри», «Грейлог» и другие — выбирайте на свой вкус и под свои задачи.


P. S. Логи — как автотесты — потратив пару лишних минут на разработку, экономишь часы на поддержку проекта. Утверждение «пару лишних минут» не взято с потолка: действительно, имея грамотно настроенные приложение и логер, протоколирование работы скрипта входит в привычку, а сам процесс сводится к простейшему вызову метода и передачи ему сообщения.

Ранее Ctrl + ↓