Русский
Русский
English
Статистика
Реклама

Трассировка

Разработка контроллера резервного питания. Трассировка

14.06.2021 12:13:27 | Автор: admin

В предыдущей статье http://personeltest.ru/aways/habr.com/ru/post/557242/ была описана схемотехника контроллера резервного питания. Такой контроллер может пригодится в разнообразных технических системах и устройствах. Поэтому конструктив платы был выбран максимально нейтральный с возможностью выноса элементов управления на отдельную панель.

Выбор конструкции платы и ее трассировка - это каскад компромиссов. Компромиссы возникают когда надо удовлетворить целый список желаний включающий, но не ограниченный пунктами:

  • электромагнитная совместимость удовлетворяющая стандартам

  • высокая теплоотдача и большая рассеиваемая мощность без радиаторов и вентиляторов

  • низкая цена печатной платы

  • минимальные размеры

  • возможность изменять варианты сборки

  • обеспечение электробезопасности и электрической прочности

  • ремонтопригодность с минимальной оснасткой и оборудованием

  • пригодность для коррекций ошибок трассировки и схемотехники

  • технологичность сборки и невысокая цена сборки

  • максимальная тестируемость после сборки

  • удобство монтажа в целевой системе

Естественно что весь этот список невозможно не только максимально удовлетворить, но даже держать в памяти затруднительно.
Поэтому эмпирически выбираем два-три высших приоритета с которыми работаем в первую очередь.
Низкая серийность позволяет нам сдвинуть цену вниз по приоритетам. Боль прошлого опыта заставляет нас поднять ремонтопригодность и тюнингируемость на пару уровней выше чем это принято обычно.
В верхней строчке может оказаться электробезопасность и соответствие стандартам по ЭМС.
И не только потому что без этого регуляторы просто не позволят эксплуатировать плату. Плохая ЭМС может поднять результирующую цену платы многократно, поскольку приведет к длительному циклу отладки, к повышенному проценту ремонтов, удорожанию технической поддержки и многому другому. Соответственно вердикт - плата должна иметь не менее 4-х слоев.

В 4-х слоях удастся сделать максимально большие полигоны земли и питания, а также полигоны отвода тепла.
Толщину платы выбираем из соображений жесткости и из перечня доступных вариантов у производителя плат. Внутренние слои расположены ближе к внешним чтобы иметь лучшую емкостную связь с дорожками в верхних слоях и обеспечивать лучшую ЭМС, а также для лучшей передачи тепла от SMD компонентов в стороны от них.
Шесть слоев конечно было бы лучше, но нельзя забывать что цена еще не выкинута из списка приоритетов.

Вопрос выбора программных инструментов для трассировки решается в пользу Altium Designer. Как считают его разработчики он на сегодня наиболее массово применяемый инструмент в данной области.
Цена за standalone лицензию Altium до акций могла обойтись пределах 10 тыс. евро, еще 3 тыс. евро возможно придется отдать за опцию PDN Analyzer если потребуется точнее рассчитать потери и наводки в проводниках.
К счастью есть возможность поработать с триальной версией Altium и при должной сноровке выполнить трассировку необходимой нам платы в триальный период.

Результат работы показан ниже:

Вид трассировки с отображением всех 4-х слоев Вид трассировки с отображением всех 4-х слоев Вид сверху и вид снизуВид сверху и вид снизу

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

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

Расположение основных узлов на платеРасположение основных узлов на плате

Работа по правилам.
В Altium есть оригинальный механизм правил. Правила позволяют делать автоматическую проверку соответствия трассировки заданным технологическим нормам.

Для данной платы были созданы следующие основные правила:

Минимальные зазоры по умолчаниюМинимальные зазоры по умолчаниюМинимальная, предпочтительная и максимальная толщина проводниковМинимальная, предпочтительная и максимальная толщина проводниковМинимальные и максимальные размеры переходных отверстийМинимальные и максимальные размеры переходных отверстий

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

Слева диалог установки зазоров, справа диалог установки минимального пути для класса цепей 220VСлева диалог установки зазоров, справа диалог установки минимального пути для класса цепей 220V

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

Чтобы иметь возможность разным цепям назначать разные зазоры по отношению к другим цепям на схеме задаются классы цепей. Классы назначаются с помощью специальных визуальных элементов присоединяемых к цепям, как показано на рисунке. При щелчке на элементе открывается диалог, где можно написать имя класса цепи.
Затем в редакторе печатной платы в диалоге правил каждому классу обнаруженному на схеме можно записать свое правило со значением зазора. Естественно для классов можно задать и иные категории правил, например ширину проводников, типы переходных отверстий разрешенных для класса, способы подключения к полигонам, термо-барьеры и проч. Но для данной платы это не используется.
Обратной стороной правил является то что их может стать слишком много и тогда поддерживать правила при рефакторинге станет труднее чем делать ручные операции.

Площадки и их особенности

Как и при разработке программного обеспечения так и при разработке платы не имеет смысла сразу уделять много внимания форме площадок. Для этого есть рефакторинг и в Altium этот рефакторинг делать достаточно удобно.
Но несколько советов все же дам.

Площадки со скруглениямиПлощадки со скруглениями

Во первых, все площадки скругляю (или почти все, насколько видится целесообразным) .
Это заметно повышает плотность трассировки и заполняемость полигонами. Исключение составляют только первые пины многовыводных компонентов. Их делаю прямоугольными чтобы сразу визуально отличить и понять ориентацию компонента с какой бы стороны платы мы не смотрели (если это не SMD компонент)

Посадочное место силового транзистора. Красным обозначены открытые области маски для пасты. Посадочное место силового транзистора. Красным обозначены открытые области маски для пасты.

Следующим важным моментом является маска для нанесения пасты. Все области открытой маски для пасты на поверхности платы должны быть примерно одинаковыми. Так требуют технологи контрактных сборщиков чтобы лучше контролировать количество наносимой пасты.
Поэтому под большие площади занимаемые SDM транзисторами маска пасты делается не сплошной, а перфорированной. Если ее сделать сплошной, то переизбыток пасты вызовет миграцию корпуса силового транзистора при пайке с сторону со значительным смещением (доли миллиметра). Такой миграции хватит чтобы замкнуть затвор с истоком.
Если переходные отверстия находятся на площадке, то их диаметр не более 0.3 мм и над ними закрыта маска пасты. Паста никогда не ложится на переходные. С обратной стороны платы у таких переходных всегда открыта паяльная маска. Такие меры вполне эффективно препятствуют массивному перетеканию припоя на обратную сторону и образованию дефектов вспучивания паяльной маски на обратной стороне.

Площадки измерительных шунтов.
Оба показанных ниже варианта приемлемы. Но все же первый вариант выдаст менее точное измерение. И погрешность будет выше чем заявленная погрешность номинала самого шунта.

Шелкография

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

Какие рекомендации действительно важны

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

Неоднозначная рекомендация по применению термобарьеровНеоднозначная рекомендация по применению термобарьеровВажная рекомендация в отношении паяльной маски Важная рекомендация в отношении паяльной маски

Рекомендация по установке термо-барьеров. Она напрямую конфликтует с требованиями ЭМИ и теплопередачи, однако выполнение рекомендации обеспечивает исключительное удобство ремонта. Как правило если элемент не греется, не проводит большие токи, то ремонтировать его не приходится, если только не считать тюнинга.
Современные контрактные сборщики, по моему опыту, не отдают плат с дефектом надгробного камня, а исправляют его у себя, если он появляется. Они также и претензий не предъявляют в случае отсутствия термо-барьера.
Что же касается ремонта, то современные паяльники без труда справляются с отпайкой компонентов без термо-барьеров. Словом, рекомендация сомнительная.

Рекомендация для паяльной маски. Это очень важная рекомендация. Области открытой паяльной маски ни в коем случае не должны охватывать соседние площадки если они принадлежат разным цепям. Иначе практически гарантировано где-то возникнет замыкание между площадками и контрактный сборщик отдаст плату с дефектом потому что визуальный контроль его не обнаружит, так как замыкания могут быть под корпусами микросхем.

Проблемы земли
Вопрос о земле - важнейший в цифро-аналогово-силовых схемах. Малейшая неосмотрительность может привести к тяжелым финансовым последствиям либо, в лучшем случае, к значительной деградации качества работы схемы.
У Altium есть инструмент под названием PDN Analyzer для точного расчета потенциалов в проводниках с большими токами к которым относятся и полигоны земель. Однако в данном проекте этот анализатор не использовался. Все же это дорогое и трудоемкое удовольствие оправданное в более сложных проектах. Здесь подход был проще.
Были идентифицированы несколько основных доменов земли которые необходимо максимально разделить:
- цифровая земля микроконтроллера
- аналоговая земля микроконтроллера
- возвратная земля силовых ключей и DC/DC преобразователя
- чувствительная земля DC/DC преобразователя
- непосредственно заземление

Потом эти земли были обратно на схеме разделены специальными компонентами-перемычками представляющими собой просто короткие дорожки, как на рисунке ниже

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

Ниже показана результирующая топология каждой из земель.

На этом описание трассировки заканчивается. Насколько это возможно в формате короткой статьи я постарался отметить самые важные на мой взгляд моменты.

Следующим этапом будет программирование, наладка и тестирование платы. Но об этом позже.

Подробнее..

Удобное логирование на бэкенде. Доклад Яндекса

28.11.2020 12:19:52 | Автор: admin
Что-то всегда идет не по плану. Приходится отвечать на вопросы, Что сломалось?, Почему тормозит? и Почему мы не увидели этого раньше?. На примере простого приложения Даниил Галиев zefirior из Яндекс.Путешествий показал, как отвечать на эти вопросы и какие инструменты в этом помогут. Настроим логирование, прикрутим трассировку, разложим ошибки, и все это в удобном интерфейсе.

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



Что будем делать? Мы построим небольшое приложение, наш стартап. Потом внедрим в него базовое логирование, это маленькая часть доклада, то, что поставляет Python из коробки. И дальше самая большая часть мы разберем типичные проблемы, которые встречаются нам во время отладки, выкатки, и инструменты для их решения.

Небольшой дисклеймер: я буду говорить такие слова, как ручка и локаль. Поясню. Ручка возможно, яндексовый сленг, это обозначает ваши API, http или gRPC API или любые другие комбинации букв перед APU. Локаль это когда я разрабатываю на ноутбуке. Вроде бы я рассказал обо всех словах, которые я не контролирую.

Приложение Книжная лавка


Начнем. Наш стартап это Книжная лавка. Главной фичей этого приложения будет продажа книг, это все, что мы хотим сделать. Дальше немного начинки. Приложение будет написано на Flask. Все сниппеты кода, все инструменты общие и абстрагированы от Python, поэтому их можно будет интегрировать в большинство ваших приложений. Но в нашем докладе это будет Flask.

Действующие лица: я, разработчик, менеджеры и мой любимый коллега Эраст. Любые совпадения случайны.



Давайте немного про структуру. Это приложение с микросервисной архитектурой. Первый сервис Books, хранилище книг с метаданными о книгах. Он использует базу данных PostgreSQL. Второй микросервис микросервис доставки, хранит метаданные о заказах пользователей. Cabinet это бэкенд для кабинета. У нас нет фронтенда, в нашем докладе он не нужен. Cabinet агрегирует запросы, данные из сервиса книг и сервиса доставки.



По-быстрому покажу код ручек этих сервисов, API Books. Это ручка выгребает данные из базы, сериализует их, превращает в JSON и отдает.



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



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

Базовое логирование в приложении


Теперь давайте про базовое логирование, то, которое мы впилили. Начнем с терминологии.



Что нам дает Python? Четыре базовые, главные сущности:

Logger, входная точка логирования в вашем коде. Вы будете пользоваться каким-то Logger, писать logging.INFO, и все. Ваш код больше ничего не будет знать о том, куда сообщение улетело и что с ним дальше произошло. За это уже отвечает сущность Handler.

Handler обрабатывает ваше сообщение, решает, куда его отправить: в стандартный вывод, в файл или кому-нибудь на почту.

Filter одна из двух вспомогательных сущностей. Удаляет сообщения из лога. Другой стандартный вариант использования это наполнение данными. Например, в вашей записи нужно добавить атрибут. Для этого тоже может помочь Filter.

Formatter приводит ваше сообщение к нужному виду.



На этом с терминологией закончили, дальше к логированию прямо на Python, с базовыми классами, мы возвращаться не будем. Но вот пример конфигурации нашего приложения, которая раскатана на всех трех сервисах. Здесь два главных, важных для нас блока: formatters и handlers. Для formatters, есть пример, который вы можете увидеть здесь, шаблон того, как будет выводиться сообщение.

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

Проблема 1. Логи разбросаны


Переходим к проблемам. Для начала проблема первая: логи разбросаны.

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

Теперь вопрос. Прибегает к нам менеджер и спрашивает: Там сломалось, помоги! Вы бежите. У вас же все логируется, это великолепно. Вы заходите на первую машинку, смотрите там ничего нет по вашему запросу. Заходите на вторую машинку ничего. И так далее. Это плохо, это надо как-то решать.



Давайте формализуем результат, который мы хотим увидеть. Я хочу, чтобы логи были в одном месте. Это простое требование. Немного круче то, что я хочу поиск по логам. То есть да, оно лежит в одном месте и я умею грепать, но было бы прикольно, если бы были какие-нибудь tools, крутые фичи помимо простого грепа.

И я не хочу писать. Это Эраст любит писать код. Я не про это, я сразу сделал продукт. То есть хочется меньше дополнительного кода, обойтись одним-двумя файликами, строчками, и всё.



Решение, которое можно использовать, ElasticSearch. Давайте его попробуем поднять. Какие плюсы ElasticSearch нам даст? Это интерфейс с поиском логов. Сразу из коробки есть интерфейс, это вам не консолька, а единственное место хранения. То есть главное требование мы отработали. Нам не нужно будет ходить по серверам.

В нашем случае это будет довольно простая интеграция, и с недавним релизом у ElasticSearch выпустился новый агент, который отвечает за большинство интеграций. Они там сами впилили интеграции. Очень круто. Я составлял доклад чуть раньше и использовал filebeat, так же просто. Для логов все просто.

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



В первую очередь нам нужно будет развернуть агент, который будет отправлять наши логи в Elastic. Вы регистрируете аккаунт в Elastic и дальше добавляете в ваш docker-compose. Если у вас не docker-compose, можете поднимать ручками или в вашей системе. В нашем случае добавляется вот такой блок кода, интеграции в docker-compose. Всё, сервис настроен. И вы можете увидеть в блоке volumes файл конфигурации filebeat.yml.



Вот пример filebeat.yml. Здесь настроен автоматический поиск логов контейнеров docker, которые крутятся рядом. Кастомизован выбор этих логов. По условию можно задавать, вешать на ваши контейнеры лейблы, и в зависимости от этого ваши логи будут отправляться только у определенных контейнеров. С блоком processors:add_docker_metadata все просто. В логи добавляем немножечко больше информации о ваших логах в контексте docker. Необязательно, но прикольно.



Что мы получили? Это все, что мы написали, весь код, очень круто. При этом мы получили все логи в одном месте и есть интерфейс. Мы можем поискать наши логи, вот плашечка search. Они доставляются. И можно даже в прямом эфире включить так, чтобы стрим летел к нам в логи в интерфейс, и мы это видели.



Тут я бы и сам спросил: а чего, как грепать-то? Что из себя представляет поиск по логам, что там можно сделать?

Да, из коробки в таком подходе, когда у нас текстовые логи, есть небольшой затык: мы можем по тексту задать запрос, например message:users. Это выведет нам все логи, у которых есть подстрока users. Можно пользоваться звездочками, большинством других юниксовых wild cards. Но кажется, этого недостаточно, хочется сделать сложнее, чтобы можно было нагрепать в Nginx раньше, как мы это умеем.



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

Какие от этого есть плюсы? Это единый формат данных. Да, у объектов могут быть разные атрибуты, но любая внешняя система может прочитать именно JSON и получить какой-то объект.

Какая-никакая типизация. Это упрощает интеграцию с другими системами: не нужно писать десериализаторы. И как раз десериализаторы это другой пункт. Вам не нужно писать в приложении прозаичные тексты. Пример: User пришел с таким-то айдишником, с таким-то заказом. И это все нужно писать каждый раз.

Меня это напрягало. Я хочу написать: Прилетел запрос. Дальше: Такой-то, такой-то, такой-то, очень просто, очень по-айтишному.



Давайте дальше. Договоримся: логировать будем в формате JSON, это простой формат. Сразу ElasticSearch поддерживается, filebeat, которым мы сериализуем и попробуем впилить. Это не очень сложно. Для начала вы добавляете из библиотеки pythonjsonlogger в блок formatters JSONFormatter файлика settings, где у нас хранится конфигурация. У вас в системе это может быть другое место. И дальше в атрибуте format вы передаете, какие атрибуты вы хотите добавлять в ваш объект.

Блок ниже это блок конфигурации, который добавляется в filebeat.yml. Здесь из коробки есть интерфейс у filebeat для парсинга JSON-логов. Очень круто. Это все. Для этогов вам больше ничего писать не придется. И теперь ваши логи похожи на объекты.



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



Давайте подведем итог. Теперь наши логи имеют структуру. По ним несложно грепать и можно писать интеллектуальные запросы. ElasticSearch знает об этой структуре, так как он распарсил все эти атрибуты. А в kibana это интерфейс для ElasticSearch можно фильтровать такие логи с помощью специализированного языка запросов, который предоставляет Elastic Stack.

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

Проблема 2. Тормоза


Следующая проблема тормоза. В микросервисной архитектуре всегда и везде бывают тормоза.



Тут немного контекста, расскажу вам историю. Ко мне прибегает менеджер, главное действующее лицо нашего проекта, и говорит: Эй-эй, кабинет тормозит! Даня, спаси, помоги!

Мы пока ничего не знаем, лезем в Elastic в наши логи. Но давайте я расскажу, что, собственно, произошло.



Эраст добавил фичу. В книгах мы теперь отображаем не айдишник автора, а его имя прямо в интерфейсе. Очень круто. Сделал он это вот таким кодом. Небольшой кусок кода, ничего сложного. Что может пойти не так?

Вы наметанным взглядом можете сказать, что с SQLAlchemy так делать нельзя, с другой ORM тоже. Нужно сделать прекэш или что-нибудь еще, чтобы в цикле не ходить в базу с маленьким подзапросиком. Неприятная проблема. Кажется, что такую ошибку вообще нельзя допустить.

Давайте расскажу. У меня был опыт: мы работали с Django, и у нас в проекте был реализован кастомный прекэш. Много лет все шло хорошо. В какой-то момент мы с Эрастом решили: давай пойдем в ногу со временем, обновим Django. Естественно, Django ничего не знает о нашем кастомном прекэше, и интерфейс поменялся. Прикэш отвалился, молча. На тестировании это не отловили. Та же самая проблема, просто ее сложнее было отловить.

Проблема в чем? Как я помогу вам решить проблему?



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

Первое, что делаю, иду в ElasticSearch, у нас он уже есть, помогает, не нужно бегать по серверам. Я захожу в логи, ищу логи кабинета. Нахожу долгие запросы. Воспроизвожу на ноутбуке и вижу, что тормозит не кабинет. Тормозит Books.

Бегу в логи Books, нахожу проблемные запросы собственно, он у нас уже есть. Точно так же воспроизвожу Books на ноутбуке. Очень сложный код ничего не понимаю. Начинаю дебажить. Тайминги довольно сложно отлавливать. Почему? Внутри SQLAlchemy довольно сложно это определить. Пишу кастомные тайм-логгеры, локализую и исправляю проблему.



Мне было больно. Сложно, неприятно. Я плакал. Хочется, чтобы этот процесс поиска проблемы был быстрее и удобнее.

Формализуем наши проблемы. Сложно по логам искать, что тормозит, потому что наш лог это лог несвязанных событий. Приходится писать кастомные таймеры, которые показывают нам, сколько выполнялись блоки кода. Причем непонятно, как логировать тайминги внешних систем: например, ORM или библиотек requests. Надо наши таймеры внедрять внутрь либо каким-то Wrapper, но мы не узнаем, от чего оно тормозит внутри. Сложно.



Хорошее решение, которое я нашел, Jaeger. Это имплементация протокола opentracing, то есть давайте внедрим трассировку.

Что дает Jaeger? Это удобный интерфейс с поиском запросов. Вы можете отфильтровать долгие запросы или сделать это по тегам. Наглядное представление потока запросов, очень красивая картинка, чуть позже покажу.

Тайминги логируются из коробки. С ними ничего не надо делать. Если вам нужно про какой-то кастомный блок проверить, сколько он выполняется, вы можете его обернуть в таймеры, предоставляемые Jaeger. Очень удобно.



Посмотрим, как вообще можно было найти проблему в интерфейсе и там же ее локализовать. Мы заходим в интерфейс Jaeger. Вот так выглядят наши запросы. Мы можем поискать запросы именно кабинета или другого сервиса. Сразу фильтруем долгие запросы. Нас интересуют именно долгие, их по логам довольно сложно найти. Получаем их список.



Проваливаемся в этот запрос, и видим большую портянку SQL-подзапросов. Мы прямо наглядно видим, как они исполнялись по времени, какой блок кода за что отвечал. Очень круто. Причем в контексте нашей проблемы это не весь лог. Там есть еще большая портянка на два-три слайда вниз. Мы довольно быстро локализовали проблему в Jaeger. В чем после решения проблемы нам может помочь контекст, который предоставляет Jaeger?



Jaeger логирует, например, SQL-запросы: вы можете посмотреть, какие запросы повторяются. Очень быстро и круто.



Проблему мы решили и сразу видим в Jaeger, что все хорошо. Мы проверяем по тому же запросу, что у нас теперь нет подзапросов. Почему? Предположим, мы проверим тот же запрос, узнаем тайминг посмотрим в Elastic, сколько запрос выполнялся. Тогда мы увидим время. Но это не гарантирует, что подзапросов не было. А здесь мы это видим, круто.



Давайте внедрим Jaeger. Кода нужно не очень много. Вы добавляете зависимости для opentracing, для Flask. Теперь о том, какой код мы делаем.

Первый блок кода это настройка клиента Jaeger.

Затем мы настраиваем интеграцию с Flask, Django или с любым другим фреймворком, на который есть интеграция.

install_all_patches самая последняя строчка кода и самая интересная. Мы патчим большинство внешних интеграция, взаимодействуя с MySQL, Postgres, библиотекой requests. Мы все это патчим и именно поэтому в интерфейсе Jaeger сразу видим все запросы с SQL и то, в какой из сервисов ходил наш искомый сервис. Очень круто. И вам не пришлось много писать. Мы просто написали install_all_patches. Магия!

Что мы получили? Теперь не нужно собирать события по логам. Как я сказал, логи это разрозненные события. В Jaeger это одно большое событие, структуру которого вы видите. Jaeger позволяет отловить узкие места в приложении. Вы просто делаете поиск по долгим запросам, и можете проанализировать, что идет не так.

Проблема 3. Ошибки


Последняя проблема ошибки. Да, я лукавлю. Я не помогу вам избавиться от ошибок в приложении, но я расскажу, что с ними можно делать дальше.



Контекст. Вы можете сказать: Даня, мы логируем ошибки, у нас есть алерты на пятисотки, мы настроили. Чего ты хочешь? Логировали, логируем и будем логировать и отлаживать.

По логам вы не знаете важность ошибки. Что такое важность? Вот у вас есть одна крутая ошибка, и ошибка подключения к базе. База просто флапнула. Хочется сразу видеть, что эта ошибка не так важна, и если нет времени, не обращать на нее внимания, а фиксить более важную.

Частота появления ошибок это контекст, который может нам помочь в ее отладке. Как отслеживать появление ошибок? Преподолжим, у нас месяц назад была ошибка, и вот она снова появилась. Хочется сразу найти решение и поправить ее или сопоставить ее появление с одним из релизов.



Вот наглядный пример. Когда я впиливал интеграцию с Jaeger, то немного поменял свою API. У меня изменился формат ответа приложения. Я получил вот такую ошибку. Но в ней непонятно, почему у меня нет ключа, lots в объекте order, и нет ничего, что мне бы помогло. Мол, смотри ошибку здесь, воспроизведи и самостоятельно отлови.



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



Что мы получили на выходе? Вот такой дашборд с ошибками, которые можно сгруппировать по проектам и за которыми можно следить. Огромная портянка логов с ошибками группируется в одинаковые, похожие. По ним приводится статистика. И вы также можете работать с этими ошибками с помощью интерфейса.



Посмотрим на нашем примере. Проваливаемся в ошибку KeyError. Сразу видим контекст ошибки, что было в объекте order, чего там не было. Я сразу по ошибке вижу, что мне приложение Delivery отдало новую структуру данных. Кабинет просто к этому не готов.



Что дает sentry, помимо того, что я перечислил? Формализуем.

Это хранилище ошибок, в котором можно искать их. Для этого есть удобные инструменты. Есть группировка ошибок по проектам, по похожести. Sentry дает интеграции с разными трекерами. То есть вы можете следить за вашими ошибками, работать с ними. Вы можете просто добавлять задачу в ваш контекст, и все. Это помогает в разработке.

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



Давайте подведем итог. Мы с вами написали приложение, простое, но отвечающее потребностям. Оно помогает вам в разработке и поддержке, в его жизненном цикле. Что мы сделали? Мы собрали логи в одно хранилище. Это дало нам возможность не искать их по разным местам. Плюс у нас появился поиск по логам и сторонние фичи, наши tools.

Интегрировали трассировку. Теперь мы наглядно можем следить за потоком данных в нашем приложении.

И добавили удобный инструмент для работы с ошибками. Они в нашем приложении будут, как бы мы ни старались. Но мы будем фиксить их быстрее и качественнее.

Что еще можно добавить? Само приложение готово, оно есть по ссылке, вы можете посмотреть, как оно сделано. Там поднимаются все интеграции. Например, интеграции с Elastic или трассировки. Заходите, смотрите.

Еще одна крутая штука, которую я не успел осветить, requests_id. Почти ничем не отличается от trace_id, который используется в трассировках. Но за requests_id отвечаем мы, это самая главная его фича. Менеджер может прийти к нам сразу с requests_id, нам не потребуется его искать. Мы сразу начнем решать нашу проблему. Очень круто.

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

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

Как трассировка запросов сломала API

29.01.2021 14:10:10 | Автор: admin

TL;DR;

История провала со счастливым концом о том, как команда узнала о трассировке запросов, AOP, а потом сломала API.

Невинное начало

Каждый проект содержит логирование. Наш проект использовал Lombok и его @Slf4j аннотацию. Мы логировали выполнение бизнес операций, но нам не хватало контекста. Логи содержали что-то типа такого:

Create orderCreate orderOrder created.Failed to create order

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

REQ#1 Create orderREQ#2 Create orderREQ#2 Order created.REQ#1 Failed to create order

А теперь детективная история. Добро пожаловать в текстовый микрокомикс :)

Условный понедельник

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

Короче, всё по ТЗ. Ну ок, поехали.

Тимлид в отдельной ветке добавляет в один из классов пример использования MDC для решения поставленной задачи. Отдает свой код команде на ревью. Команда узнала что-то новое. Команда рада. Тимлид доволен. Ревью проходит успешно и код вливается в основную ветку.

Условный вторник

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

Условная среда

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

На обеденном перерыве тимлид вспоминает, что есть такая штука как AOP. Тимлид знает, что это особая эльфийская магия и что надо ей пользоваться аккуратно. Но тимлид верит в свою команду. Что вообще может пойти не так?

Условный четверг

Команда узнает от тимлида про AOP и о том, как это может помочь решить проблему дублирования кода. Один из разработчиков получает задание внедрить Spring AOP и прикрутить логирование запросов. Получилось что-то такое:

@Around("execution(public * super.pupper.web.api.*.*Api.*(..))")public void aroundApi(ProceedingJoinPoint jp) throws Throwable {    LogUtil.initTraceId();    jp.proceed()    LogUtil.clearTraceId();}

Для команды AOP штука новая. Команда смотрит на код, выглядит ок. Мерджим.

Условная пятница

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

Внимательный читатель уже знает в чем причина, давайте уже наконец раскроем карты. Все дело в коде (естественно):

@Around("execution(public * super.pupper.web.api.*.*Api.*(..))")public void aroundApi(ProceedingJoinPoint jp) throws Throwable {    LogUtil.initTraceId();    jp.proceed();    LogUtil.clearTraceId();}

Вся ошибка в том, что результат вызова тихо мирно умалчивается, и API метод ничего в буквально смысле не возвращает. Заголовок Content-Length: 0. Правильная реализация должна быть примерно такой:

@Around("execution(public * super.pupper.web.api.*.*Api.*(..))")public Object aroundApi(ProceedingJoinPoint jp) throws Throwable {    LogUtil.initTraceId();    try {        return jp.proceed();    } finally {        LogUtil.clearTraceId();    }}

Разработчик заливает фикс. Все рады. Успехов вам на код-ревью и на отладке! :)

Подробнее..

Энтузиаст добавил в ретроконсоль трассировку лучей

16.12.2020 16:22:14 | Автор: admin

Разработчик и энтузиаст Бен Картер добавил в Super NES аппаратный трассировщик лучей. Напомню что самой консоли уже 30 лет.

Для реализации этой идеи его надоумил друг и желание получше изучить Verilog и FPGA. Таким образом появился проект SuperRT. Блогер хотел сделать аналог чипа SuperFX - даже названия похожи. Чип SuperFX располагался в картридже и обрабатывал визуальные эффекты недоступные самой консоли из-за ограничения "железа".

В итоге, Картер собрал кастомную плату картриджа с тремя дополнительными вычислительными ядрами с частотой 50 МГц - они обеспечивают поддержку трассировку лучей. На КПДВ можно можно видеть их работу. Автор извиняется за качество видео - виновата плата видеозахвата.

На фото можно видеть снятый корпус для монтажа проводов, по словам автора, никаких изменений в железо не вносились. Для создания модифицированной платы, автор купил древний картридж с "ужасной игрой Pachinko", удалил ПЗУ с игрой и вставил туда кабели. Еще он использовал несколько логических преобразователей (level shifters) и программируемой логической схемы (FPGA) DE10-Nano. Большинство проводов на снимке выше обеспечивают коммутацию логических преобразователей, необходимых для конвертации напряжения с 5В, передаваемых SNES, в 3,3В допустимых для современных чипов.

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

Чип вычисляет и записывает в буфер RAM результаты своей работы. Дизассемблированный командный буфер выглядит так:

0000 Start0001 Plane 0, -1, 0, Dist=-20002 SphereSub OH 2, 1, 5, Rad=50003 SphereSub OH 4, 1, 4, Rad=40004 SphereSub OH 5, 1, 9, Rad=90005 SphereSub OH 2, 1, 2, Rad=20006 SphereSub OH -0.5, 1, 2, Rad=20007 RegisterHitNoReset 0, 248, 0, Reflectiveness=00008 Checkerboard ORH 48, 152, 48, Reflectiveness=00009 ResetHitState0010 Plane 0, -1, 0, Dist=-2.1501460011 RegisterHit 0, 0, 248, Reflectiveness=1530012 AABB 4, -2.5, 11,    8, 3.5, 130013 ResetHitStateAndJump NH 440014 Origin 6, 2, 120015 Plane -0.2929688, 0, -0.9570313, Dist=0.24975590016 PlaneAnd OH 0.2919922, 0, 0.9560547, Dist=0.250017 PlaneAnd OH 0, 1, 0, Dist=10018 PlaneAnd OH 0, -1, 0, Dist=40019 PlaneAnd OH -0.9570313, 0, 0.2919922, Dist=-10020 PlaneAnd OH 0.9560547, 0, -0.2929688, Dist=1.4997560021 RegisterHit 248, 0, 0, Reflectiveness=0

Максимально допустимая частота кадров - 30 FPS. Это связано с ограничением пропускной способности интерфейсов самой консоли. Каждый кадр с трассировкой "весит" 32 килобайта при ограничения интерфейса вывода в 16 килобайт, поэтому полное обновление картинки возможно только каждые два кадра. Автор планирует и дальше развивать свое детище, подробнее можно узнать в его личном блоге.

Подробнее..

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru