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

Блог компании мтс

Из чего состоит набор для разработчиков NB-IoT DevKit?

26.06.2020 12:10:59 | Автор: admin
Набор вышел в начале июня. Он поможет разобраться, в чем преимущества сети интернета вещей NB-IoT, и научит работать с ней. В комплект входит аппаратная часть, коннективити, то есть доступ к сети NB-IoT и доступ к IoT-платформам. Главная фича DevKit демонстрационная прошивка, которая позволяет на практике разобраться, как работает система. В этой статье детально рассмотрим DevKit и его возможности.



Кому это надо?


Когда мы начали разворачивать сеть NB-IoT (почитать больше о сети NB-IoT можно здесь), на нас со всех сторон посыпались различные вопросы. Крупные производители, которые много лет работают на рынке M2M устройств, стартапы, начинающие разработчики и просто любители интересовались режимами работы сети, протоколами передачи данных, даже управлением радиомодулем АТ-командами. Нас спрашивали, какие частоты (band) используются, как работает режим power save mode, как устройство и сеть согласуют соответствующие таймеры, как, используя протокол транспортного уровня UDP, добиться гарантированной доставки сообщения, как задать APN и выбрать определенный band (частотный диапазон). И множество других вопросов.

В ходе тестов мы также обратили внимание, что многие устройства не адаптированы для работы в сети NB-IoT и в результате работают некорректно. Например, использование протокола передачи данных с транспортным уровнем TCP приводит к высокому объему передаваемого трафика, а также к трудностям при работе в сложных радиоусловиях. Другая распространенная проблема использование радиомодуля в режиме по умолчанию, в котором модуль сам включает eDRX: это вводит пользователя в заблуждение, так как он не может принять данные в произвольный момент времени.

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

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

Из чего состоит набор?


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

В состав аппаратной части входит радиомодуль Ublox SARA-R410, микроконтроллер STM32L152RE, кабели, антенны и программатор. На основной плате установлены акселерометр и температурный датчик. Плата расширения в форм-факторе Arduino-shield содержит GNSS модуль.

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

Также по запросу возможна активация функционала NIDD и возможность работы через узел SCEF (Service Capability Exposure Function) сети NB-IoT МТС. Сервис снимает с разработчика необходимость идентификации и аутентификации устройств и предоставляет возможность клиентским серверам приложений (Application Server) получать данные и управлять устройствами через единый API-интерфейс. В России ни один другой оператор интернета вещей не предоставляет такую возможность.

Возможности демонстрационной прошивки


Демонстрационная прошивка содержит функциональное меню, которое позволяет новичкам сразу приступить к работе. Достаточно лишь подключить плату и получить регистрационные данные. Прошивка реализует функциональное меню, доступ к которому мы получаем, подключившись через любую терминальную программу. Можно воспользоваться знакомой многим PuTTY. Мы также рекомендуем удобную и бесплатную утилиту от Ublox: m-center



Выглядит меню так:

*** Welcome to MTS NB-IoT Development Kit service menu ***
Firmware version: 2.3 beta 2, 28.05.2020

Current settings found in EEPROM:

Target IP: 195.34.49.22
Target port: 6683
Target URL: /api/v1/devkitNIDDtest03/telemetry
NIDD APN: devkit.nidd
Use NIDD for telemetry: 1
Board mode on startup: service menu
Telemetry interval
(in logger mode): 1000 ms
GNSS privacy mode: 0

Type in a function number from a list below and press enter.

Target server setup:
1 set the URL of the resource JSON data will be transmitted to
2 set the IP address
3 set the port
4 set an APN for NIDD access or turn NIDD mode ON or OFF
System functions:
5 force send telemetry packet
6 wait for incoming NIDD data during specified timeout
7 enter direct AT-command mode
8 enter true direct mode to access the RF module
CAUTION: to exit this mode you will have to reboot the board physically
9 show ICCID, IMEI, IMSI and MCU serial number
10 show network information
11 set telemetry transmission interval
12 set GNSS privacy mode
(hide actual location data when transmitting on server)
13 set firmware startup mode (setup or logger)
14 read on-board sensors and try to acquire GNSS data
15 reboot MCU
16 reboot RF module
17 factory setup & test
(do not use this unless you really know what you want)

Первые четыре пункта меню позволяют настроить параметры соединения с платформой (URI-path, IP, порт, параметры NIDD). Пятый пункт позволяет отправить пакет, содержащий данные с датчиков на плате.

Пример того, как выглядит результат отправки пакета по протоколу CoAP:

Using IP method.
Sending data to iotsandbox.mts.ru:6683/api/v1/devkitNIDDtest03/telemetry
Telemetry:
{'interface':'telemetry', 'ICCID':'89701012417915117807', 'Tamb_degC':24, 'aX':-14, 'aY':23, 'aZ':244, 'RSSI_dBm':-81, 'latitude':55.768848, 'longitude':37.715088, 'GNSS_data_valid':1}
(184 bytes)
Raw CoAP data (225 bytes):
5102000000B36170690276310D036465766B69744E4944447465737430330974656C656D65747279FF7B27696E74657266616365273A2774656C656D65747279272C20274943434944273A273839373031303132343137393135313137383037272C202754616D625F64656743273A32342C20276158273A2D31342C20276159273A32332C2027615A273A3234342C2027525353495F64426D273A2D38312C20276C61746974756465273A35352E3736383834382C20276C6F6E676974756465273A33372E3731353038382C2027474E53535F646174615F76616C6964273A317D
Server response code: 2.03, response time = 664 ms.
Server response dump:
5143067000

Переданные данные мы видим на платформе:



Пункт меню 14 позволяет считать данные с датчиков на основной плате и на плате расширения, вот пример того, что мы увидим:

On-board sensors data:
temperature: 23

accelerometer: X = -3 Y = 4 Z = 249
Accelerometer signature value is correct.

Testing GNSS option
GNSS string:
$GNGLL,5546.12120,N,03742.89412,E,133220.00,A,D*75
Parsed data:
latitude = 55.768687
longitude = 37.714902

Можно прочитать идентификаторы радиомодуля и микроконтроллера, используя пункт 7 меню. В таком случае ответ будет:

Board identification data
SIM card ICCID: 89701012417915117807
AT+CCID

+CCID: 89701012417915117807

OK
RF module IMEI: 359215103260015
AT+CGSN

359215103260015

OK
IMSI:
AT+CIMI

250011791511780

OK
MCU serial number:
0x393533307473832200

Используя пункт 10 меню можно считать сетевые параметры NB-IoT, вот пример вывода:

RSSI = -75 dBm (valid range is -111 to -51 dBm)
SNR = 22 dB
RSRP = -83 dBm (valid range is -141 to -44 dBm)
Cell ID = 753621
EARFCN = 1711

Также можно перейти в режим прямого управления радиомодулем посредством АТ-команд, используя пункт меню 8. Эта функция переводит Development kit в режим отладочной платы радиомодуля. Ниже пример прямого управления радиомодулем с командами обмена данными между устройством и сервером в режиме NIDD:

Entering true direct mode.
From now on everything you type into a terminal will be transferred to the RF module as is
(and similarly in reverse direction).
NOTICE: No special commands supported here, for nothing is between you and the RF module.
YOU NEED TO REBOOT THE BOARD PHYSICALLY TO EXIT THIS MODE.

at+cereg?
+CEREG: 0,1
OK

AT+COPS?
+COPS: 0,0,MTS RUS MTS RUS,9
OK

at+cgdcont?
+CGDCONT: 1,NONIP,devkit.nidd,0.0.0.0,0,0,0,0
OK

AT+CRTDCP=1
OK

AT+CSODCP=1,16,"{'test':'hello'}"
OK

+CRTDCP:1,5,Hi hi

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

Для продвинутых пользователей открыты исходные коды прошивки, можно оценить логику работы устройства на уровне кода, внести изменения и экспериментировать. Со стороны облачной платформы доступны инструменты для обработки данных: виджеты, панели управления, инструменты Интеграции, позволяющие принять данные в любом формате в протоколах UDP, TCP и Non-IP. Инструмент Конвертер данных позволяют привести получаемый поток данных к виду понятному платформе.

DevKit и Ардуино


Несмотря на критическое отношение части профессионалов к Ардуино, которые указывают на неоптимальный код и на то, что библиотеки написаны не профессиональными разработчиками, мы изначально хотели сделать DevKit совместимым с Ардуино. Arduino IDE пользуется популярностью среди разработчиковлюбителей, а также может применяться в учебных программах ВУЗами.

DevKit полностью совместим с Ардуино R3 по своему духу, архитектуре, и разьемам. Для устройства были разработаны все сопутствующие файлы поддержки, так что оно устанавливается в Arduino IDE штатным образом.



В состав пакета для Arduino IDE включены необходимые инструменты и библиотеки, а также ряд примеров с исходными текстами. Программная совместимость с другими платами Arduino на основе STM32 позволяет использовать написанные для них библиотеки, а также загружать рабочие скетчи практически без изменений. Для программирования DevKit из Arduino IDE необходимо установить ПО STMCubeProgrammer, которое можно скачать с сайта компании STM. Наши разработчики продолжают наполнять пакет для Arduino новыми библиотеками и примерами.

В качестве простейшего примера работы с Arduino IDE рассмотрим загрузку примера Blink (мигание светодиодом). На изображении ниже можно увидеть результат загрузки и компиляции данного скетча из меню Файл Примеры 01.Basics





Поддерживаемые интегрированные среды разработки


Разработка демонстрационной прошивки производилась в интегрированной среде Em::Bitz. Программный код примера рассчитан на компиляцию с помощью GCC. Для разработки пользовательского кода пригодны любые IDE, поддерживающие семейство микроконтроллеров STM32L15x. Например, Arduino IDE, IAR Embedded Workbench, Keil uVision MDK ARM и другие.

Расширение функциональности


Функциональность можно расширять как с помощью шилдов, так и подключая любые дискретные датчики.



Установка GNSS-шилда превращает DevKit в GPS/GLONASS трекер.



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



Можно подключить специальный шилд и добавить функциональность Ethernet и карту памяти.



Подключая датчики скорости и направления ветра получаем NB-IoT метеостанцию



Подключаем ультразвуковой датчик и реле управления насосом получаем автомат контроля уровня жидкости в емкости.



В следующем материале покажем на практике, как собрать на основе NB-IoT DevKit устройство интернета вещей. Заказать NB-IoT Development Kit можно уже сейчас на нашем сайте.

Авторы:
старший менеджер группы планирования сети IoT Виталий Бачук
ведущий эксперт направления МТС Виктор Лучанский
руководитель группы планирования сети IoT Андрей Плавич
Подробнее..

Мой МТС. Продуктовая трансформация

12.04.2021 18:13:34 | Автор: admin
Всем привет! Мы продуктовая команда Мой МТС, занимаемся разработкой основного мобильного приложения компании МТС (iOS/Android) и сайта mts.ru. Месячная аудитория активных пользователей (MAU) на всех платформах свыше 23 млн. пользователей.

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

До трансформации

Погрузимся немного в исторический контекст. Изначально приложение Мой МТС разрабатывала команда внешнего поставщика. В 2016 году мы перевели продукт в In House разработку и начали планомерные работы по совершенствованию кодовой базы, команды и процессов.

На начало 2020 года команда продукта Мой МТС состояла из 63 человек, которые были организованы следующим образом:



Разработка велась по зачаточному Scrum'у с двухнедельными итерациями и основными командными ритуалами. Однако, как заметит внимательный читатель, на схеме отсутствуют scrum master'а у нас это роль, которую выполнял и продолжает выполнять кто-то из членов feature team. Также была в наличии строгая изолированность Владельцев продукта и разработчиков. Мостиком между двумя мирами служили системные аналитики и технический лидер команды. Веб-разработкой полностью занимался подрядчик. Так совпало, что начало активной фазы избавления от внешних зависимостей началось одновременно с трансформацией.

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

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

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


С технической точки зрения у нас имелись следующие вводные, которые хотелось бы обозначить в контексте трансформации:

  • Монолитные решения на всех платформах (iOS, Android, Web)
  • Полное отсутствие UI тестирования
  • Хаотичный процесс проверки pull request'ов без SLA


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

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


Цели трансформации

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

Среди формальных целей руководством компании были обозначены два фактора, которые нужно было улучшить:

  • Общая прозрачность работы команды на всех уровнях понимание процессов и артефактов команды, в широком смысле этого слова, всеми сотрудниками, которым это может быть нужно, начиная с самих членов команды и заканчивая Советом директоров компании.
  • Уменьшение показателя Time-to-Market путем поиска и устранения узких мест в рабочем процессе и изменения подхода к работе в целом.


Достаточно быстро мы поняли, что для себя нам так же нужно определить и понять цели. То есть сократить T2M, чтобы что? повысить прозрачность зачем? и другие подобные вопросы. Начали обсуждать это с CPO, Владельцами продуктов и к тому времени уже прошло несколько месяцев работы в новой парадигме. Так как получилось собрать достаточно много интересной фактуры, мы собрали всю большую команду Мой МТС и рассказали, как же на самом деле команда управления продуктом видит цели и ожидаемые результаты трансформации, какие небольшие победы уже можно отпраздновать, а так же где наоборот стало хуже и что потерялось из фокуса. Вот некоторые выводы, к которым мы пришли после первого такого подхода:

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


С точки зрения целей трансформации, для себя мы определили, что самое главное не цифры и T2M (на начальном этапе так точно), а изменение нашего подхода к работе, мышления, и, как сказал CPO, раскачивание лодки, чтобы понимать, где она протекает. То есть сокращение Time2Market на этот период времени стало для нас не самоцелью, а процессом раскачивания устоявшейся системы с целью поиска узких мест и их разрешения. Звучит странно, но нам это помогло расставить все на свои места. Мы поняли, что:

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


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

Трансформация

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

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

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

Все задачи следующего квартала предварительно обсуждаются, верхнеуровнево декомпозируются, а также оцениваются командами разработки. Одним из открытий наведения порядка в планировании для нас стало понимание, что в квартале 6 Спринтов, один из которых () уходит на тех. долг (сумма 20-ти % в Спринт), второй для тестировщиков команды на релиз (сейчас релиз делается по всему приложению, релизное знамя переходит от команды к команде, но это временное явление, мы почти от этого избавились).

По итогам Квартального планирования мы получаем перечень задач, которые:

  • Обсуждены и согласованы со всеми участниками вне наших команд, например, с другими продуктами, по которым есть зависимости в реализации фичей
  • Обсуждены и предварительно проработаны командой разработки
  • Распределены по Спринтам внутри квартала
  • Презентованы всем заинтересованным лицам. В конце квартального планирования мы рассказываем о своих планах, зависимостях и рисках на встрече, где помимо остальных продуктов и команд присутствуют топ-менеджеры. Синхронизация очень масштабная в последний раз только на B2C направление было 44 продукта/платформы.

После окончания процесса Квартального планирования мы продолжаем регулярную синхронизацию по задачам на PO sync (еженедельная встреча Product Owner'ов и Chief Product Owner'а, технических лидеров, скрам-мастеров). Там же обсуждаем прогресс в достижении целей: если есть новые вводные или вскрылись не найденные ранее риски у нас есть возможность узнать об этом и повлиять как можно раньше.

Помимо Квартального планирования и PO sync, у нас в Мой МТС прижилась традиция проведения ежедневных чек-инов команды трансформации. В эту команду входят: CPO, технические лидеры, скрам-мастера. Иногда туда приглашаем и других участников, если того требует задача. Как уже говорилось, мы встречаемся этим составом ежедневно в конце рабочего дня, на 15-45 минут, обсуждаем и решаем вопросы, связанные с кадровыми изменениями, отзывами пользователей, новыми инициативами (например, перезапуск Discovery процесса, но об этом в следующих статьях), инициативами от членов команды и т.д. Крайне редко на чек-инах рассматриваются проблемы какой-то конкретной фичи, так как это более низкоуровневая повестка.

В силу размера компании нам не удалось внедрить новый подход везде и сразу, что привело к рассинхронизации при запуске нового механизма планирования у разных направления B2C, B2B и IT платформы.

Если говорить о структуре команды, то после трансформации продуктовая команда Мой МТС стала выглядеть следующим образом:



Разумеется, переход к новой структуре был поэтапным, нужно было нанять большое количество сотрудников и постепенно формировать новые команды. К сожалению, бурный рост не мог не сказаться на текучке кадров, и отток в 2020 году был самым большим за последние 4 года. Однако если рассмотреть последние месяцы 2020, когда найм по большей части был уже завершен, то ситуация заметно выправилась. Если говорить о цифрах, то в 2020 году текучка составила 30%, а в предыдущие годы (2018-2019) держалась на уровне 18%.

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

  • Основным изменением стал переход на юниты обособленные scrum команды, состоящие из технических специалистов, дизайнера и владельца продукта.
    Юниты собираются вокруг направлений бизнеса (например, фиксированная связь, финтех и так далее). В теории, подобная трансформация должна была привести к большей вовлеченности всех участников команды в специфику своих направлений и более качественной проработке продуктовых гипотез.
  • В команде продукта появились выделенные scrum-мастера. Они выполняют важные функции:
    • коррекция процесса трансформации
    • консультирование по вопросам Agile
    • связующую функцию с корпоративным центром продуктовой культуры.
  • Выделенная команда автоматизации UI тестирования.
    Значительный рост количества команд привел быстрому развитию приложения, вместе с которым также стремительно увеличивается количество тест-кейсов в регрессе. На данный момент автоматизировано 25% основных сценариев.
  • Мы начали активно работать в направлении перехода на In House разработку WEB.
    Процесс оказался значительно сложнее, чем в случае с мобильным приложением, в силу исторического и юридического наследия. Также ожидания бизнеса не позволили замедлить или остановить разработку нового функционала.
  • В 2021 году планируем провести эксперимент по созданию гибридных команд app+web.


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

Результаты

Если формально подводить итоги трансформации, то поставленные цели были достигнуты:
1. Процесс стал прозрачным для всех
2. Time-to-market сокращен в 1,5 раза

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

  • Излишняя прозрачность может быть вредной
    Применимо в случае, например, когда у стейкхолдеров есть некий технический бэкграунд (или они так думают) и они пытаются, экстраполируя свой старый опыт, активно влиять на рабочие процессы команды.Стоит отметить, что прозрачность планирования в полной мере не была достигнута. Квартальное планирование сейчас запущено параллельно на различных срезах (B2C, B2B, платформы), хотя остро стоит потребность в синхронизации.
  • Абсолютные значения показателей в вакууме
    Нам, конечно, удалось уменьшить time-to-market, но параллельно с трансформацией активно улучшались и подходы к работе владельцев продукта. Это привело к уменьшению среднего размера задачи и ускорило скорость доставки инкремента до пользователя. Даже не смотря на оговорки, подобный результат для нас очень ценен: отказ от больших и толстых задач, которые становятся неактуальными за время доставки до пользователей, является огромным плюсом. Также за прошедший год был сделан очень мощный рывок в работе с техническим долгом. Изолированные команды требуют по возможности изолированных песочниц в коде, поэтому модульность приложения стала основным техническим вектором для нас наравне с автоматизацией тестирования.


Новые проблемы

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

Также раньше мы очень большое внимание уделяли детальной проработке всех требований к фиче до старта разработки. Основные недостатки такого подхода это сужение пропускной способности всей команды и слишком тепличные условия для разработчиков и тестировщиков. В юнитах уже на первых порах стало видно, что старый подход к ТЗ не работает и нужно что-то менять аналитик не успевал готовить проработанные задачи. Для решения этой проблемы мы разделили ТЗ на две части must have для старта разработки и всё остальное. Этот подход несколько снял напряжение, но не закрыл все вопросы, поэтому дальнейшие проверки различных гипотез дело времени.

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

Планы

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

  • Вся разработка должна быть In House. На наш взгляд, это аксиома, аутсорсинг всегда непрозрачно и почти всегда неуправляемо.
  • Техническое развитие продукта
    • автоматические UI тесты для снятия лишней нагрузки с unit'ов при подготовке релизов
    • единый интеграционный backend для снижения затрат на подключения к другим системам ландшафта компании
    • дальнейшее развитие модульности приложения для упрощения работы структуры в целом. Для ускорения и стабилизации этого процесса мы планируем создать выделенную команду развития платформ.
  • Автоматизация сбора различных метрик работы unit'ов и продуктовой команды целиком.
  • Создание кросс-команды, в которую будет входить полный спектр специалистов для реализации функционала в app и web части нашего продукта.


Авторы Артем Андреев, Наталья Егорова, Алексей Кретов
Подробнее..

Who is mr. Marvin?

03.09.2020 10:04:27 | Автор: admin
В июне этого года мы выпустили на рынок умную колонку с голосовым помощником по имени Марвин. Она может работать до 2 часов без подзарядки. У колонки шесть микрофонов для обработки голосовых команд. ПО полностью разработано внутри МТС без использования сторонних коммерческих решений. В этом посте разберем основные функции и технические характеристики новинки.



Что может Марвин?


По голосовому запросу виртуальный ассистент Марвин можете отвечать на разные вопросы, позволяет слушать более 60 радиостанций, узнавать прогноз погоды, устанавливать напоминания и будильники, включать голосовые игры, узнавать о последних новостях. Для колонки можно выбрать один из трех режимов контента: 18+ полностью свободный от цензуры в отношении песен, новостей (контент доступен в исходном авторском виде), Без мата режим для взрослых, но с фильтром, блокирующим специфическую лексику, Детский установлены ограничения на выдачу контента для взрослых (песни без мата, без новостей, книги сказки).

Также колонка оборудована встроенным модулем системы Умного дома от МТС и поддерживает ZigBee- и Bluetooth Low Energy-устройства. Для подключения системы не требуется посредник-партнер, не нужны сторонние аппаратные решения. Это первая портативная колонка центр управления умным домом, который, в свою очередь, управляется голосовыми командами, и через приложение МТС Smart Нome.

Что со звуком?


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

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

Колонку можно подключить к любому мобильному устройству или ноутбуку с помощью Bluetooth и Airplay в качестве устройства вывода звука.


Изображение акустического пакета колонки

Про зарядку


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

ПО


Команда Центра искусственного интеллекта интегрировала в умную колонку ПО, которое позволяет активировать Марвина. Программное обеспечение обрабатывает голосовой запрос с массива микрофонов на расстоянии 4-5 метров от человека при включенном контенте, устройство может работать в шумных условиях. ПО было разработано внутри МТС специально для умного устройства без применения методов лицензирования сторонних решений. Команде разработчиков удалось создать полностью сквозное решение по обработке акустического сигнала без передачи данных третьей стороне, что позволяет одновременно управлять колонкой голосовыми командами и использовать ее в режиме Bluetooth-гарнитуры или проигрывать музыку через Airplay.

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

Начинка


Устройство состоит из трех электронных плат и обладает высокой производительностью, общая спецификация представлена в таблице:



Безопасность


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

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

Юзабельность


Запуск работы умной колонки не требует сложных манипуляций: после установки и регистрации в приложении МТС Марвин пользователь может активировать устройство. Во время активации Марвин продиктует секретный код дополнительное средство защиты при авторизации.

Умную колонку можно подключать сразу к нескольким Wi-Fi-сетям, при этом поддерживаются сети диапазонов 2.4 ГГц и 5 ГГц. При подключении к нескольким сетям активируется программный роуминг, благодаря которому колонку можно перемещать между зонами действия этих сетей устройство будет переключаться между ними автоматически. Такой функционал делает использование устройства удобным при перемещении внутри большого помещения, а также обеспечивает более стабильную работу при загруженности Wi-Fi-канала. При этом активация колонки надежно защищена, она не передает никаких данных акустического спектра в стиле dial-up-модема.

Продолжение следует


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

Роман Жуков, начальник отдела разработки AI-утсройств Центра искусственного интеллекта МТС.
Подробнее..

Обзор на статью Visual Transformers новый подход к тренировке моделей компьютерного зрения на основе visual tokens

24.07.2020 10:04:54 | Автор: admin
Эта работа интересна тем, что авторы в ней предлагают новый подход к тренировке моделей на изображениях использовать не только пиксели и конволюции, но ещё и представлять изображения в виде визуальных токенов и тренировать на них трансформеры. По сравнению с использованием просто архитектуры ResNet предложенный подход уменьшает MAC (multiply and accumulate operations) в 6,9 раз и увеличивает топ-1 точность на 4,53 пункта на задаче классификации ImageNet.

image


Мотивация подхода


Общепринятый подход к задачам компьютерного зрения использовать картинки как 3D array (высота, ширина, количество каналов) и применять к ним конволюции. У такого подхода есть ряд недостатков:

  • не все пиксели одинаково полезны. Например, если у нас задача классификации, то нам важнее сам объект, чем фон. Интересно, что авторы не говорят о том, что Attention уже пробуют применять в задачах компьютерного зрения;
  • Конволюции не достаточно хорошо работают с пикселями, находящимися далеко друг от друга. Есть подходы с dilated convolutions и global average pooling, но они не решают саму проблему;
  • Конволюции недостаточно эффективны в очень глубоких нейронных сетях.


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

image

  • Вначале используется обычный backbone для получения feature maps
  • Далее feature map конвертируется в визуальные токены
  • Токены подаются в трансформеры
  • Выход трансформера может использоваться для задач классификации
  • А если объединить выход трансформера с feature map, то можно получить предсказания для задач сегментации


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

Visual transformer


Теперь рассмотрим работу модели подробнее.
Как уже говорилось выше, backbone извлекает feature maps, а они передаются в слои visual transformer.
Каждый visual transformer состоит из трёх частей: токенизатор, трансформер, проектор (projector).

Токенизатор



image

Токенизатор извлекает визуальные токены. По сути мы берем feature map, делаем reshape в (H * W, C) и из этого получаем токены

image

Визуализация коэффициентов при токенах выглядит вот так:
image

Position encoding


Как обычно, трансформерам нужны не только токены, но ещё и информация об их позиции.

image

Вначале мы делаем downsample, потом домножаем на тренируемые веса и конкатенируем с токенами. Для корректировки количества каналов можно добавить 1D конволюцию.

Transformer


Наконец, сам трансформер.
image

Объединение visual tokens и feature map


Это делает projector.
image
image

Динамическая токенизация


После первого слоя трансформеров мы можем не только извлекать новые visual tokens, но и использовать извлеченные с предыдущих шагов. Для их объединения используются тренируемые веса:

image

Использование visual transformers для построения моделей компьютерного зрения


Дальше авторы рассказывают как именно применяется модель к задачам компьютерного зрения. Блоки трансформера имеют три гиперпараметра: количество каналов в feature map C, количество каналов в visual token Ct, количество visual tokens L.

Если при переходе между блоками модели количество каналов оказывается неподходящим, то используются 1D и 2D конволюции для получения необходимого количества каналов.
Для ускорения расчетов и уменьшения размера модели используют group convolutions.
Авторы в статье прикладывают **псевдокод** блоков. Полноценный код обещают выложить в будущем.

Классификация изображений


Берем ResNet и на его основе создаем visual-transformer-ResNets (VT-ResNet).
Оставляем stage 1-4, лишь вместо последней ставим visual transformers.

Выход из backbone 14 x 14 feature map, количество каналов 512 или 1024 в зависимости от глубины VT-ResNet. Из feature map создаются 8 visual tokens на 1024 канала. Выход трансформера идёт в голову для классификации.

image

Семантическая сегментация


Для этой задачи в качестве базовой модели берут panoptic feature pyramid networks (FPN).

image

В FPN конволюции работают на изображениях с высоким разрешением, поэтому модель тяжелая. Авторы заменяют эти операции на visual transformer. Опять же 8 токенов и 1024 канала.

Эксперименты


Классификация на ImageNet

Тренируют 400 эпох с RMSProp. Начинают с learning rate 0,01, в течение 5 эпох разогрева увеличивают до 0,16, а потом каждую эпоху домножают на 0,9875. Используют batch normalization и размер батча 2048. Label smoothing, AutoAugment, stochastic depth survival probability 0,9, dropout 0.2, EMA 0,99985.

Это ж сколько экспериментов пришлось прогнать, чтобы все это подобрать

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

image

image

Названия статей для сравниваемых моделей:

ResNet + CBAM Convolutional block attention module
ResNet + SE Squeeze-and-excitation networks
LR-ResNet Local relation networks for image recognition
StandAlone Stand-alone self-attention in vision models
AA-ResNet Attention augmented convolutional networks
SAN Exploring self-attention for image recognition

Ablation study


Для ускорения экспериментов брали VT-ResNet-{18, 34} и тренировали 90 эпох.

image

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

Результаты сегментации


image

Как видим, метрика выросла лишь чуть-чуть, но модель потребляет в 6,5 раз меньше MAC.

Потенциальное будущее подхода


Эксперименты показали, что предложенный подход позволяет создавать более эффективные модели (в плане вычислительных затрат), которые при этом достигают лучшего качества. Предложенная архитектура успешно работает для разных задач computer vision, и можно надеяться, что её применение поможет улучшить симтемы, использующие comuter vision AR/VR, автономные автомобили и другие.

Обзор подготовил ведущий разработчик МТС Андрей Лукьяненко.
Подробнее..

Туториал по uplift моделированию метрики. Часть 3

23.03.2021 14:22:27 | Автор: admin

В предыдущих туториалах (часть 1, часть 2) мы изучали методы, моделирующие uplift. Это величина, которая оценивает размер влияния на клиента, если мы взаимодействуем с ним. Например, смс или пуш уведомление. Давайте обсудим: как измерять качество uplift моделей?

Использовать классические метрики качества для оценки обученной модели не получится, так как нет ground truth по каждому объекту выборки или реальных, настоящих значений uplift. Это значит, что если мы предскажем значение, сравнить его будет не с чем. В этом заключается особенность uplift моделирования: нельзя одновременно прокоммуницировать и не прокоммуницировать с клиентом и посмотреть разницу в его реакции. Поэтому все метрики мы будем рассчитывать, так или иначе группируя объекты выборки. Например, рассматривая 10% выборки, 20% и так далее.

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

Описание датасета

Для примера возьмем датасет от Ленты. Датасет был представлен на хакатоне BigTarget от Ленты и Microsoft летом 2020 года и теперь доступен для скачивания. В нем собраны обезличенные и аггрегированные данные о поведении клиентов супермаркетов до проведения акции на определенную группу товаров. Есть данные о факте взаимодействии с клиентом и факты совершения целевого действия после коммуникации.

Более детально на данные можно посмотреть в документации и ноутбуке.

Метрики

uplift@k

Самая простая и понятная метрика - размер uplift на топ k процентах выборки.

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

Для расчета uplift@k нужно отсортировать выборку по величине предсказанного uplift и посмотреть разницу средних значений таргета Y (в англоязычных статьях использую термин response rate, мы его тоже будем использовать в дальнейшем) в целевой и контрольной группах.Целевая группа - группа, которая получила коммуникацию. Контрольная группа - которая не получила.

Формула uplift@k
uplift@k = response\ rate @ k_{(treatment)} - response\ rate@k_{(control)} \\ response\ rate@k = mean(Y@k) \\Y@k - таргет\ на\ k\%

Теоретический uplift@k принимает значения от -1 (когда в целевой группе нет реакций Y=1, а в контрольной группе все клиенты имеют реакцию Y=1) и может достигать величины 1 (противоположная ситуация: в целевой группе все клиенты откликнулись: Y=1, в то время как в контрольной - ни одного случая с Y=1).

На практике uplift@k принимает значения от 0 до 1, в зависимости от выбранного значения k, особенностей датасета и качества модели.

Рассчитывать эту метрику можно двумя различными способами: сначала сортировать по предсказанному uplift и далее считать разницу response rate двух групп. Или наоборот, изначально сортировать объекты из контрольной и целевой групп по отдельности.

Обучим простую uplift модель и предскажем величину uplift на валидации

Подробности в этом ноутбуке

Обозначения переменных:

# y_val - столбец таргета на валидации# trmnt_val - столбец флага коммуникации на валидации# uplift_ct - предсказанный uplift методом ClassTransformation на валидации

Тогда метрику uplift@k можно импортировать и посчитать таким образом:

from sklift.metrics import uplift_at_k# k = 10%k = 0.1# strategy='overall' sort by uplift treatment and control togetheruplift_overall = uplift_at_k(y_val, uplift_ct, trmnt_val,                              strategy='overall', k=k)# strategy='by_group' sort by uplift treatment and control separatelyuplift_bygroup = uplift_at_k(y_val, uplift_ct, trmnt_val,                              strategy='by_group', k=k)print(f"uplift@{k * 100:.0f}%: {uplift_overall:.4f}"      f"(sort groups by uplift together)")print(f"uplift@{k * 100:.0f}%: {uplift_bygroup:.4f}"      f"(sort groups by uplift separately)")

Получим

uplift@10%: 0.1484 (sort groups by uplift together)uplift@10%: 0.1521 (sort groups by uplift separately)

Uplift by percentile

Бывает так, что со стороны бизнеса не известно значение порога kи хочется посмотреть, как будет вести себя метрика при разных значениях порога k. Такая метрика в литературе [1] упоминается как uplift by decile. Также ее называютuplift by percentile или uplift by bin.

При построении действуем по аналогии с uplift@k:

  1. Сортируем по предсказанному значению uplift

  2. Делим отсортированные данные на перцентили / децили / бины.

  3. В каждом перцентиле отдельно оцениваем uplift как разность между средними значениями целевой переменной в тестовой и контрольной группах.

Стоит отметить, что в большинстве источников [1] [2] аплифт по перцентилям оценивается независимо в каждом перцентиле, но ничего не мешает вам оценить его кумулятивно.

Результатом этой метрики, как правило, является таблица [3] или ее визуальное представление в виде графика. Давайте также для каждого перцентиля рассчитаем следующие показатели:

  • n_treatment - размер целевой (или treatment) группы

  • n_control - размер контрольной (control) группы

  • response_rate_treatment - среднее значение таргета целевой группы

  • response_rate_control - среднее значение таргета контрольной группы

  • uplift = response_rate_treatment - response_rate_control

Дополнительно добавим расчет среднеквадратичного отклонения для каждой метрики (std_treatment, std_control, std_uplift) для того, чтобы оценивать разброс метрики в каждом перцентиле (формулы вы найдете ниже).

С помощью кода ниже можно рассчитать таблицу uplift by percentile. Кроме метрик по каждому перцентилю в последней строке total расположены итоговые метрики для всей выборки.

from sklift.metrics import uplift_by_percentileuplift_by_percentile(y_val, uplift_ct, trmnt_val,                      strategy='overall',                      total=True, std=True, bins=10)

График uplift by percentile

Если визуализировать таблицу, то получится график uplift by percentile. По нему удобно оценивать эффективность модели. Как его можно интерпретировать? Так как коммуникация будет проводиться с клиентами, получившими наибольшую оценку uplift, то слева на графике должны быть максимальные по модулю положительные значения uplift и в следующих перцентилях значения уменьшаются.

Для отрисовки можно использовать bar plot. Для удобства отобразим две графика. На верхнем нарисуем uplift, а на нижнем - соответствующий response rate в тестовой и контрольной группах, разница которых и является оценкой uplift.

Код построения plot_uplift_by_percentile
from sklift.viz import plot_uplift_by_percentileplot_uplift_by_percentile(y_val, uplift_ct, trmnt_val,                           strategy='overall', kind='bar');

Тогда на графике response rate для целевой и контрольной группы (нижний bar plot) доля реакций клиентов Y = 1 из целевой группы (зеленый цвет) должна быть максимально большой в первых перцентилях и потом убывать. А доля Y = 1 контрольной группы (желтый цвет) - минимальной в первых перцентилях и затем, в идеале, возрастать. Чем больше в первых перцентилях разница двух response rate, тем больше uplift (красный цвет), а значит, тем лучше модель находит клиентов, которые положительно откликаются на коммуникацию.

Если вспомнить разделение по типам клиентов из первого туториала, то в левой части графика как раз находятся убеждаемые - тот тип, которых мы хотим найти. В терминах целевого действия и коммуникации это Y=1 при W=1 или Y=0 при W=0.

На графике могут быть и отрицательные значения uplift. Нетрудно понять, что это случится в том перцентиле, в котором response rate в контрольной группе больше, чем в целевой. Это значит, что коммуникация с этой группой имела негативный эффект и модель нашла тип клиентов, которые негативно реагируют на коммуникацию - тип не беспокоить, Y=0 при W=1, Y=1 при W=0.

Для случайной аплифт модели график uplift by percentile будет выглядеть как линия, параллельная оси Х.

График для идеальной uplift модели выглядел бы так:

На графике между типом убеждаемые в левой части и типом не-беспокоить в правой части лежат два оставшихся типа, которые модель не различает между собой: лояльные и потерянные. Если в выборке их количество будет одинаково, то uplift, равный нулю, должен быть посередине, так как их response rate уравновесит друг друга. Это произойдет потому, что лояльные всегда реагируют и выполняют целевое действие Y=1, а потерянные - наоборот, никогда этого не сделают Y=0.

Uplift по перцентилям можно визуализировать не только как bar plot, но и как line plot:

График uplift by percentile в виде line plotГрафик uplift by percentile в виде line plot

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

Выведем формулу стандартного отклонения

По определению

uplift = E[Y | treatment] - E[Y|control]

Чтобы найти стандартное отклонение, вычислим дисперсию и потом возьмем из нее корень:

D[uplift] = D[E[Y|treatment] - E[Y|control]] = D[E[Y|treatment]] + D[E[Y|control]]

Так как

D[E[X]] = D\left[ \frac{X_1 + ... + X_n}{n} \right] = \frac{nD[X]}{n^2} = \frac{D[X]}{n}

и бинарный таргет распределен по закону Бернулли, получаем

D[uplift] = \frac{D[Y | treatment]}{N^T} + \frac{D[Y | control]}{N^C} = \frac{p_{treatment}(1 - p_{treatment})}{N^T} + \frac{p_{control}(1 - p_{control})}{N^C} \sigma(uplift) = \sqrt{D[uplift]} = \sqrt{ \frac{p_{treatment}(1 - p_{treatment})}{N^T} + \frac{p_{control}(1 - p_{control})}{N^C} }

Где

p_{control} = response\ rate_{control} \\ p_{treatment} = response\ rate_{treatment}

Weighted average uplift

Часто хочется иметь метрику, посчитанную в виде единого значения на всей тестовой выборке. Для этого опять пригодится таблица uplift by percentile. Давайте с помощью значений в столбцах uplift и n_treatment рассчитаем усредненный uplift на всей выборке, взвешенный на размер целевой группы - weighted average uplift [3].

Формула weighted average uplift
weighted\ average\ uplift = \frac{1}{\sum_iN^T_i}\sum_iN^T_i uplift_i \\ N^T_i - размер\ целевой\ группы\в\ i-ом\ перцентиле \\ uplift_i - величина\ uplift\ в\ i-ом\ перцентиле
from sklift.metrics import weighted_average_upliftuplift_full_data = weighted_average_uplift(y_val, uplift_ct,                                            trmnt_val, bins=10) print(f"weighted average uplift on full data: {uplift_full_data:.4f}")

Получим

weighted average uplift on full data: 0.0189

Weighted average uplift лежит в пределах от [-1, 1]и отображается на графике uplift by percentile в названии. Если метрика принимает значение 1, это значит, что реакций Y=1 в контрольной группе нет ни в одном перцентиле: пользователи никогда не выполняют целевое действие самостоятельно, а только при коммуникации. При таком значении метрики нет смысла решать задачу с помощью uplift моделирования, лучше свести постановку задачи к обучению response или look-alike модели.

Значение метрики может доходить до граничного значения -1. Это будет означать, что во всех перцентилях uplft был равен -1. Такое происходит, когда в целевой группе нет реакций Y=1, а в контрольной группе все клиенты имеют реакцию Y=1. Получается, что значения метрики, которые нас устраивают в рамках решения uplift задачи, лежат в пределах [0, 1).

Uplift curve

Uplift кривая строится как функция от количества объектов, нарастающим итогом. В каждой точке кривой можно увидеть накопленный к этому моменту uplift

Формула uplift curve
uplift\ curve(t) = \left( \frac{Y^T_t}{N^T_t} - \frac{Y^C_t}{N^C_t} \right)(N^T_t + N^C_t) \\ t - накопившееся\ количество\ объектов \\ Y^T_t, Y^C_t - таргет\ в\ treatment\ группе, таргет\ в\ control\ группе \\ N^T_t, N^C_t - размер\ treatment\ группы, размер\ control\ группы

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

Код отрисовки uplift curve
from sklift.viz import plot_uplift_curve# with ideal curve# perfect=Trueplot_uplift_curve(y_val, uplift_ct, trmnt_val, perfect=True);
Uplift curve: идеальная, реальная и случайнаяUplift curve: идеальная, реальная и случайная

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

Как выглядит кривая uplift без отрисовки идеальной кривой

Qini curve

Еще одной довольно распространенной кривой при оценке uplift моделей является Qini кривая, впервые введенная в статье [4] и определяющаяся следующим образом:

Формула qini curve
qini\ curve (t) = Y^T_t - \frac{Y^C_t N^T_t}{N^C_t} \\ Y^T_t, Y^C_t - таргет\ в\ treatment\ группе, таргет\ в\ control\ группе \\ N^T_t, N^C_t - размер\ treatment\ группы, размер\ control\ группы

Qini curve, как и другие аплифт метрики, рассчитывается кумулятивно сразу для набора объектов. Кривую Qini для модели тоже сравнивают со случайной кривой (на графике черной линией) и с идеальным случаем (на графике красной линией). Аналогично с uplift кривой, чем выше кривая над случайной кривой, тем лучше.

Код отрисовки qini curve
from sklift.viz import plot_qini_curve# with ideal Qini curve (red line)# perfect=Trueplot_qini_curve(y_val, uplift_ct, trmnt_val, perfect=True);

Физический смысл qini кривой в том, чтобы не давать модели поднимать наверх в ранжировании только целевую (treatment) группу, штрафуя ее за это множителем Nt/Nc, который уменьшает итоговое значение, если Nt сильно больше, чем Nc.

Можно провести очевидную параллель между uplift и qini кривыми:

uplift\ curve(t) = \frac{qini\ curve\ (t)(N^T_t + N^C_t)}{N^T_t}

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

Qini curve без идеальной кривой

От кривых к числам

Итак, теперь мы знаем, как строить qini и uplift кривые, с помощью которых можно оценить качество модели. При этом сравнивать модели хочется не "на глаз", а с помощью чисел. Как и во многих других метриках машинного обучения, основанных на кривых, предлагается рассчитывать площадь под модельными кривыми и нормировать ее на площадь под идеальной кривой [5]. При этом обычно из площадей под модельной и идеальной кривыми вычитают площадь под случайной кривой, которую называют baseline.

Qini coefficient или AUQC

В случае площади под qini кривой можно посчитать коэффициент qini, или area under qini curve (AUQC). Схематично его расчет можно нарисовать так:

Расчет qini coefficientРасчет qini coefficientКод qini_auc_score
from sklift.metrics import qini_auc_score# AUQC = area under Qini curve = Qini coefficientauqc = qini_auc_score(y_val, uplift_ct, trmnt_val) print(f"Qini coefficient on full data: {auqc:.4f}")
Qini coefficient on full data: 0.0695

Area under uplift curve, AUUQ

Для uplift кривой коэффициент называется AUUQ - area under uplift curve и считается аналогичным образом.

Код uplift_auc_score
from sklift.metrics import uplift_auc_score# AUUQ = area under uplift curveauuc = uplift_auc_score(y_val, uplift_ct, trmnt_val) print(f"Uplift auc score on full data: {auuc:.4f}")
Uplift auc score on full data: 0.0422

Как вы могли заметить, коэффициенты AUQC и AUUC также отображаются на графиках кривых в названии графиков.

Заключение

Целью наших статей (часть 1, часть 2, часть 3) был рассказ об основах uplift моделирования и кейсах его применения. Мы подробно разобрали не только основные методы и метрики, но и дизайн эксперимента для сбора обучающей выборки. Первые части были без кода, поэтому рекомендуем посмотреть практические туториалы здесь.

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

Статья написана в соавторстве с Максимом Шевченко @maks-sh

Источники

[1] PierreGutierrez, Jean-Yves Grardy. Causal Inference and Uplift Modeling A review of the literature. JMLR: Workshop and Conference Proceedings 67:113, 2016

[2] Verbeke, Wouter & Baesens, Bart & Bravo, Cristin. Profit Driven Business Analytics: A Practitioner's Guide to Transforming Big Data into Added Value, 2018.

[3] Ren Michel, Igor Schnakenburg, Tobias von Martens. Targeting Uplift. An Introduction to Net Scores. Springer, 2019.

[4] Nicholas J. Radcliffe. Using control groups to target on predicted lift: Building and assessing uplift model. Direct Market J Direct Market Assoc Anal Council, 1:1421, 2007.

[5] Floris Devriendt,Tias Guns,Wouter Verbeke. Learning to rank for uplift modeling. IEEE Transactions on Knowledge and Data Engineering, 2020

Подробнее..

Не те игрушки как мы научили нейросеть бороться с порно в стримах

13.08.2020 14:10:01 | Автор: admin
Всем привет, меня зовут Олег, я занимаюсь компьютерным зрением в команде Видеоаналитики МТС и сегодня расскажу вам, как мы защищаем от небезопасного контента стриминговую платформу WASD.tv, в частности про детектирование порнографии в постановке задачи action recognition.




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

И правил платформы, за соблюдением которых следят модераторы.


Зачем нужно модерировать небезопасный контент? На это есть две причины. Первая это действующее российское законодательство, по которому распространение порнографии незаконно. Вторая причина user experience. Платформа ориентирована на людей всех возрастов, и мы не можем себе позволить взрослый контент на главной странице.

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

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

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

Исходя из этих соображений, мы начали смотреть, как можно решить эту задачу. Из интересных открытых решений уже несколько лет существует обученная на закрытых данных модель Open NSFW от Yahoo (имплементация на TF). Ещё есть классный открытый репозиторий Александра Кима nsfw data scraper, из которого можно получить несколько сотен тысяч изображений с реддита, imgur и вроде бы каких-то других сайтов. Изображения разбиты на пять классов: порно, хентай, эротика, нейтральный и рисунки. На основе этих данных появилось много моделей, например раз, два
Опенсорсные решения страдают от нескольких проблем в целом невысокое качество некоторых моделей, некорректное срабатывание на вышеупомянутых сложных кейсах и безопасных изображениях вроде тверкающих девушек и мемов с Рикардо Милосом, а также проблематичность доработки, потому что либо модели устаревшие и обучены на закрытых данных, либо данные очень шумные и с непредсказуемым распределением.



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

Распознавание действий


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

Как вообще решают эту задачу? В восемнадцатом году вышёл отличный обзор от qure.ai, и кажется, что с тех пор радикального прогресса в области не произошло, так что рекомендую. Более интересный ресерч на тему видео перешёл в более сложную задачу понимания и пересказа видео. Там и графовые сетки, и self-supervised learning этому даже был полностью посвящен второй день на последнем Machines Can See.

Так вот, классификация действий. История прогресса в нейросетевых моделях примерно следующая: сначала проводили обучение трехмерных сверточных сетей с нуля (С3D), затем стали пробовать свёртки с какой-нибудь рекуррентной архитектурой или механизмом внимания; в какой-то момент Андрей Карпатый предложил разными способами мержить представления с разных кадров, еще позже стандартом стало делать двуглавые модели, где на один вход подается последовательность кадров в BGR/RGB, а на другой посчитанный на них плотный оптический поток. Еще были приколы с использованием дополнительных признаков и специальных слоёв вроде NetVLAD. В итоге мы смотрели на модели, лучше всего показавшие себя на бенчмарке UCF101, где видео разбиты по 101 классу действий. Такой моделью оказалась архитектура I3D от DeepMind, она зашла лучше всего и у нас, поэтому расскажу о ней подробнее.

DeepMind I3D


Как бейзлайны мы пробовали обучать C3D и CNN-LSTM обе модели долго обучаются и медленно сходятся. Затем мы взяли I3D, и жизнь стала лучше. Это две трёхмерные сверточные сети для BGR и оптического потока, но есть особенность в отличие от предыдущих моделей, эта предобучена на ImageNet и собственном датасете от Deepmind Kinetics-700, в котором 650 тысяч клипов и 700 классов. Это обеспечивает крайне быструю сходимость модели в несколько часов к хорошему качеству.

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

Мы подаем в модель 16 кадров, а не 64. Раньше у нас был квадратный вход, но, учитывая специфику платформы, мы поменяли соотношение сторон входа на 16:9. Задача бинарная классификация, где нулевой класс это не порно, а единичный порно. Обучали с помощью SGD с моментумом, он показал себя чуть лучше Адама. Аугментации минимальные горизонтальные флипы и JPEG-компрессия. Тут ничего особенного.

Завершая тему моделей после I3D еще выходили модели EVANet Neural Architecture Search для последовательности кадров, SlowFast Networks сеть с двумя каналами с разным фреймрейтом, и статья Google AI Temporal Cycle-Consistency Learning , но мы их не исследовали.

На чём обучали-то?


Как я уже писал выше, с данными туго. Никто их публиковать не хочет, это сложно с юридической и этической точек зрения начиная от лицензий и заканчивая согласием каждого причастного к контенту лица. Датасеты, их лицензии и публикация это вообще весело. Если кто-то хочет написать об этом статью, я с удовольствием почитаю. Из значимых академических датасетов есть только бразильский NPDI, и он, к сожалению, маленький по объему, его распределение данных недостаточно разнообразно, он состоит из ключевых кадров, и процедура его получения не самая простая. А мы ведь еще и датасет из видео хотим! Пришлось собирать самостоятельно.

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

Скрапинг обеспечит нам потенциально гораздо большее разнообразие в данных, и мы можем получить разметку достаточно дёшево, сказав, что все кадры всех видео с условного порнхаба небезопасные, а все кадры всех видео с ютуба безопасные. Есть минусы это всё надо где-то хранить, из этого надо как-то собирать датасет, и самое существенное в наивной разметке порнороликов есть шум. Это как прямые ошибки: интро, сцены, где все одеты, крупные планы без половых признаков, меню хентай-игр так и элементы, на которые модель может переобучиться: логотипы, черные экраны, монтажные склейки. Такого шума несколько процентов, и в случае терабайтов видео избавиться от него дорого. Об этом мы ещё поговорим.

Второй подход это ручная сборка. Ее плюсы заключаются в том, что мы можем моделировать любое желаемое распределение данных, данные более предсказуемы, и их проще размечать просто потому, что их меньше. Но есть и минусы. Очевидно, данных при таком подходе получается меньше, и помимо этого они могут страдать от biasа сборщиков, так как он моделирует распределение и может что-то упустить.
Мы выбрали второй подход. Составили список того, что потенциально могло бы оказаться на стриминговой платформе: самые разные игры, анимация, аниме, игра на музыкальных инструментах, реакции, мемы, хайлайты стримов и попытались покрыть самые разные возможные типы небезопасного контента от чего-то обычного до трэша в духе порно с птеродактилями. Отдельно упомянули компьютерные игры, по которым часто делают 3д-хентай Overwatch, например. И начали собирать. В итоге могу выделить два инсайта.

Фетишисты неплохие сборщики данных


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

Да и ютуберы тоже


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

Итерации данных


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

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

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

Как размечали почти для всех роликов использовали инструмент от OpenCV CVAT.

Пять копеек про CVAT
Расшифровывается как Computer Vision Annotation Tool. Разрабатывается в Нижнем Новгороде. Запускается в докере, можно сделать свою мини-Толоку. Проблема он предназначен для сегментации и детекции, но не для классификации. Пришлось парсить их XML. Потом написали для разметчика свой простенький инструмент.


Затем мы в ходе работы собрали ещё видео, обновили каталог игр, и в итоге сейчас у нас есть несколько сотен часов видео по нескольким десятками разных категорий, и мы знаем, что они состоят из ~30000 уникальных сцен, плюс данные со звездочкой, о которых мы поговорим чуть ниже.

Отлично, у нас есть сырые размеченные данные! Как нам из них получить хороший датасет? Ролики разной длины, для каждой категории собраны видео разного хронометража и степени разнообразия как это всё связать воедино? Сколько сэмплов мы можем взять из датасета? Его разнообразие как-то фундаментально ограничено (как максимум количеством кадров видео), как нам понять, что мы берем лишнего?

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

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

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

Давайте будем искать монтажные склейки

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

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

Собрали датасет из 20000 сэмплов в трейне, 2000 в валидации и 2000 в тесте, обучили модель, нам понравились метрики на тесте, отправили в продакшн.

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

Это и есть данные со звездочкой. Они позволили нам заточиться на разнообразный контент платформы и снизить нагрузку на модераторов. Теперь в основном ложные срабатывания происходят на новых играх так, мы одно время чаще ловили Death Stranding и Valorant.

Текущий датасет состоит из 30000/5000/3000 сэмплов train/val/test.

Эволюция наших метрик на нашем тесте, разбитым по категориям, и сравнение с открытыми решениями (кликабельно)


В качестве метрики мы используем f1-меру с подвохом. Мы стараемся делать так, чтобы precision наших моделей стремился к единице, и в таком случае f1-мера становится прокси полноты.



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

Fin.



Видеоверсию материала можно увидеть здесь
Подробнее..

Контроль соблюдения контракта API ограничения или возможности

30.12.2020 20:10:58 | Автор: admin
Из этой статьи вы узнаете, какие преимущества предоставляет контроль контракта API, что можно и нужно контролировать и как организовать процедуры контроля для исключения негативного влияния на производство.

Когда в 1825 году Англия первыми из всех запустила железнодорожное сообщение между городами, мир еще жил по солнечному времени, ориентируясь на полдень момент верхней кульминации солнца. Фактическая разница во времени между городами в одной географической полосе могла достигать 30 минут. Отсутствовала синхронизация.

Поезд, который отправлялся из Лондона в 12:00 по местному времени и должен был прибыть в Бристоль в 13:00, по местному времени прибывал в 13:30. Для местных жителей и пассажиров поезда это не было критичным явлением, но для компании-перевозчика, которая строит бизнес вокруг расписаний, планировать работу с каждым новым маршрутом становилось дорогим удовольствием. К стандартным проблемам, как опоздания, сбои в работе или аварии, прибавилась еще одна каждый новый маршрут кратно увеличивал затраты на перевозку.

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

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

Каждый разработчик API знает, что такое обратная совместимость, что контракт необходимо соблюдать и что в этот контракт включить, чтобы он был ожидаем потребителем. Но представьте вы учли все Best Practices, подробно расписали суть сервиса, добились соответствия сервиса контракту API, но сроки интеграции при этом не сократились, а затраты на интеграцию остались прежними.

Попробуем разобраться.

Но сперва договоримся о терминах. В рамках текущего материала контрактом API обозначается любая цифровая информация (цифровой артефакт), который описывает программный интерфейс, его поведение и изменения во времени. Такой артефакт, в зависимости от решаемой задачи, называется API Documentation, API Specification, API Definition, API Agreements или API Reference. Однако мы, чтобы упростить картину восприятия интеграционного домена и систематизировать знания, объединим их в один термин контракт API.

Под интеграцией подразумевается процесс или состояние стыка двух и более программных продуктов.

Сервис означает исполняемый модуль, предоставляющий точку для удаленного вызова (SOAP, REST и т.д.)

Ниже речь идет об HTTP API, но концепция применима и к другим типам.

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

Начнем

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



Другими словами, цифровой продукт это цепочка интеграций из множества разных протоколов и, соответственно, типов API REST, RPC, SOAP и т.д. Все узлы цепи, в свою очередь, отдельные продукты со своими возможностями. А каждый узел это история: продукта, интеграции, кода.



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

Какая бы история ни была, без описания API она не произойдет.

С другой стороны, если история продукта привела к описанию оригинального контракта API, отличающегося от неких общепринятых индустриальных стандартов, вы получаете долгую и мучительную интеграцию. Усилий на подключение необходимо прикладывать больше.

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



Приведу пример описания API в OpenAPI спецификации (исходный текст: swagger.io/docs/specification/describing-request-body).



Что определяет соответствие контракта вашего API некоему стандарту? Каковы критерии соответствия контракта API этому стандарту? Достаточно ли описать сервис в OpenAPI спецификации или в GraphQL и считать, что задача выполнена?

Как и в любой задаче с неизвестными, определим ключевые объекты предметной области и события. Для этого обозначим ключевой объект API, участников интеграции, их действия и инструменты, которые обеспечивают их действия.

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

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



Но вне зависимости от способа описания и используемого стандарта, суть содержимого контракта API всегда одна и включает три категории информации:

  • ЧТО предоставляется (данные, функции, ресурсы);
  • КАК предоставляется (условия использования);
  • ГДЕ предоставляется (расположение).


В общем, как и с любым договором купли-продажи товара.

Если погружаться в детали, состав контракта API можно разделить на множество категорий:
1. Атрибуты и их описание именование, типизация (например, в зависимости от семантики);
2. Версионирование, обратная совместимость;
3. Условия доступности авторизация, квоты, гранулярность, монетизация.

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

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



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

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

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

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

Если глобально, интеграция состоит из трех этапов: подготовка, согласование и управление.



Первый этап все виды операций владельца API и потребителя, которые в итоге запустят процедуру интеграции.

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

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

На этом этапе контракт API закрывает потребность Владельца как быстрее объяснить возможности сервиса и потребность Потребителя получить подробную информацию о возможности сервиса и подключиться.

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

Как Регулятор от контроля качества (QA), я должен подтвердить соответствие уровня доступности сервиса (SLA) моим требованиям. Например, если сервис приема платежей будет доступен только 50% времени, тогда только каждый второй платеж будет доходить по назначению, что в итоге может привести не только к потере репутации компании.

Как Регулятор от корпоративной архитектуры (Enterprise Architect), я должен подтвердить, что модели данных публичных сервисов идентичны. Например, если выводится еще один сервис работы с платежами, но наименование атрибутов запроса-ответа отличается от предыдущего, потребителю придется реализовать mapping параметров для работы с обоими сервисами одновременно.

Как Регулятор от информационной безопасности, я должен проверить наличие чувствительной информации в сервисе. Например, если он возвращает персональные данные, но выставлен за обычным TLS каналом, то компания может получить серьезный штраф за нарушение законов Российской Федерации (ФЗ-152).

Контракт, как описание API может и должен описывать каждую деталь в зависимости от потребности Регулятора. Эту информацию он будет искать в любом случае и подтверждать, но ее наличие в контракте кратно сокращает сроки согласования.

По факту согласования интеграции происходит получение доступа к сервису и первый вызов.

Третий этап управление потреблением.

Хотя подключение состоялось и задача решена, у каждого участника все еще возникают вопросы, и ответить на них может только контракт API.

Как Владелец API, я хочу понять, к какой версии сервиса подключен партнер Х, а к какому Y, чтобы определить условия потребления у этих сервисов и могу ли я их изменить.

Как Потребитель API, я хочу понимать свои права в случае нарушения SLA.

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

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



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

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



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



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

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

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



Владелец сервиса (бизнес-владелец): хочу, чтобы партнер нажатием кнопки в своем приложении мог вызвать такси;

Информационная безопасность: персональные данные только в определенно защищенном канале;

Контроль качества: доступность сервиса должна соответствовать заявленному уровню.

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

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

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

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

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

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



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

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



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

Но как подтвердить, что контракт содержит необходимые данные и что сервис соответствует контракту, чтобы доверять ему?

Решение простое, как в истории с железнодорожным временем, но внедрение скорее будет крайне сложным.



Определяете необходимый состав контракта API, встраиваете его наполнение в процессы производства, контролируете соответствие контракта необходимой схеме в design time, и контролируете поведения сервиса на соответствие контракту в run time.

Разберем контроль контракта на примере OpenAPI спецификации (для подхода CodeFirst) в DesignTime:

1. Допустим у вас есть репозиторий с описанием корпоративной модели данных:
a. В нем указано, что все методы работы с платежами содержат в имени ресурса pay, а все атрибуты, оперирующие номером счета, имеют строковый тип длиной ровно 10 символов и называются pay_number.
b. Для всех методов работы с платежами уровень доступности не менее 99%.
c. Определенным паттернам входных/выходных данных соответствует категория данных по ИБ и определенные категории могут быть доступны только за своими каналами. Например, набор из паспортных данных и ФИО однозначно определяется как персональные и могут быть доступны только за ГОСТ TLS.
d. К методам, которые возвращают скоринговую информацию, необходима расширенная авторизация по атрибутам партнера и обязательно проверка баланса при вызовы, т.к. потребление платное. Так же здесь же можно указать допустимый rate limit и т.д.
2. В процессе производства, в зависимости от названия методов и указанных переменных, в спецификацию добавляются необходимые разделы, описывающие схему авторизации, уровень доступности, категория данных;
3. На выходе получаете описанный API, который содержит необходимую информацию о потоке данных, способах авторизации и уровнях доступности. И каждый раздел контракта можно проверить и провалидировать автоматически.

Пример категоризации метода через extensions в OpenAPI


И контроль поведения сервиса контракту в режиме RunTime:
1. Организуете инфраструктуру, которая содержит элементы API Gateway, Microgateway, Observability
2. При выводе сервиса на ИТ-ландшафт, в зависимости от категории данных в аннотации, сервис прописывается за соответствующими хостами
3. В момент потребления
a. схема данных в транзакции сверяется со схемой в контракте
b. определяется уровень доступности сервиса
c. определяется интенсивность потребления сервиса
d. определяются свойства потребителя
4. И в случае несоответствия требованиям контракта, сервис будет доступен или не доступен для потребления с описанием причины

Пример валидации схемы запроса, на соответствие схеме контракта


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



Как итог, от контроля контракта и соответствия сервиса контракту вы получаете:
1. Сокращение времени и затрат на интеграцию (всех участников);
2. Сокращение затрат на поддержку сервиса;
3. Масштабирование потребителей без увеличения стоимости продукта;
4. Источник монетизации продукта.

В случае несоблюдения контракта затраты и ошибки будут расти с каждой новой интеграцией.
Подробнее..
Категории: Api , Блог компании мтс , Мтс

OpenTelemetry на практике

18.01.2021 16:06:50 | Автор: admin
Совсем недавно два стандарта OpenTracing и OpenCensus окончательно объединились в один. Появился новый стандарт распределенного трейсинга и мониторинга OpenTelemetry. Но несмотря на то, что разработка библиотек идет полным ходом, реального опыта его использования пока не слишком много.

Илья Казначеев, который занимается разработкой восемь лет и работает backend-разработчиком в МТС, готов поделиться тем, как применять OpenTelemetry в Golang-проектах. На конференции Golang Live 2020 он рассказал о том, как настроить использование нового стандарта для трейсинга и мониторинга и подружить его с уже существующей в проекте инфраструктурой.



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

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



Для трейсинга и мониторинга существует множество вендорских решений. До недавнего времени было два открытых стандарта: OpenTracing от CNCF, который появился в 2016, и Open Census от Google, появившийся в 2018.

Это два довольно неплохих стандарта, которые конкурировали между собой некоторое время, пока в 2019 году они не решили объединиться в один новый стандарт, который называется OpenTelemetry.



Этот стандарт включает в себя распределенный трейсинг и мониторинг. Он совместим с первыми двумя. Более того, OpenTracing и Open Census прекращают поддержку в течение двух лет, что неотвратимо приближает нас к переходу на OpenTelemetry.

Сценарии использования

Стандарт предполагает широкие возможности совмещения всего со всем и является по сути активной прослойкой между источниками метрик и трейсов и их потребителями.
Давайте взглянем на основные сценарии.

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



Если трейсинг транслируется напрямую, можно использовать config и просто заменить библиотеку.

В случае, если ваше приложение уже использует OpenTracing, можно воспользоваться OpenTracing Bridge оберткой, которая будет конвертировать запросы к OpenTracing API в OpenTelemetry API на верхнем уровне.



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



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

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

Для этого достаточно настроить в приложении экспортер в формате OTLP. Это grpc-схема для передачи данных в формате OpenTracing. Со стороны коллектора можно настроить формат и параметры экспорта метрик и трейсов конечным потребителям, либо в другие форматы. Например, в OpenCensus.



Коллектор позволяет подключать большое количество видов источников данных и множество приемников данных на выходе.



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

Стандартный коллектор расширяем. Поэтому у большинства вендоров уже готовы экспортеры в их собственные решения, если они есть. Вы можете использовать OpenTelemetry, даже если применяете сбор метрик и трейсов от какого-то закрытого вендора. Таким образом решается проблема с vendor lock-in. Даже если что-то еще не появилось непосредственно для OpenTelemetry, это можно пробросить через OpenCensus.

Сам коллектор очень просто конфигурируется через банальный YAML конфиг:



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



Экспортеры получатели данных.
Процессоры методы обработки данных внутри коллектора:



И pipelines, которые непосредственно определяют, как будет обрабатываться каждый поток данных, который протекает внутри коллектора:



Давайте рассмотрим один показательный пример.



Допустим, у вас есть некий микросервис, к которому вы уже прикрутили OpenTelemetry и настроили его. И еще один сервис с аналогичной фрагментацией.

Пока все легко. Но появляются:

  • legacy-сервисы, которые работают через OpenCensus;
  • база данных, которая отдает данные в своем формате (например, напрямую в Prometheus, как это делает PostgreSQL);
  • еще какой-то сервис, работающий в контейнере и отдающий метрики в своем формате. Вам не хочется перебилдить этот контейнер и прикручивать sidecars, чтобы они переформатировали метрики. Вы хотите просто брать и отправлять их.
  • железо, с которого вы тоже собираете метрики и хотите как-то использовать их.


Все эти метрики можно объединить одним коллектором.



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

Теперь мы хотим использовать эту информацию. В качестве экспортера трейсов можно указать Jaeger, а метрики отправлять в Prometheus, или что-то совместимое. Допустим, всеми любимую VictoriaMetrics.

Но что, если мы вдруг решили переехать в AWS и использовать местный трейсер XRay? Не проблема. Это можно пробросить через OpenCensus, в котором есть экспортер для XRay.

Таким образом, из этих кусков можно собрать всю вашу инфраструктуру для метрик и трейсов.

С теорией покончено. Поговорим о том, как использовать трейсинг на практике.

Инструментация Golang приложения: трейсинг

Сначала нужно создать корневой span, от которого и будет расти дерево вызовов.

ctx := context.Background()
tr := global.Tracer(github.com/me/otel-demo)
ctx, span := tr.Start(ctx, root)
span.AddEvent(ctx, I am a root span!)
doSomeAction(ctx, 12345)
span.End()

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

Дальше создается корневой span с указанием названия:


ctx, span := tr.Start(ctx, root)


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

Данные о span также кладутся в контекст:


ctx, span := tr.Start(ctx, root)
span.AddEvent(ctx, I am a root span!)
doSomeAction(ctx, 12345)


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

ctx, span := tr.Start(ctx, root)
span.AddEvent(ctx, I am a root span!)
doSomeAction(ctx, 12345)
span.End()

Так наш span выглядит в Jaeger:



Его можно развернуть и посмотреть логи и атрибуты.

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

func doSomeAction(ctx context.Context, requestID string) {
span := trace.SpanFromContext(ctx)
span.AddEvent(ctx, I am the same span!)

}
Обратите внимание, что закрывать здесь его не нужно, потому что он закроется в том же методе, где был создан. Мы просто берем его из контекста.

Записываем сообщение в корневой span:



Иногда нужно создать новый дочерний span, чтобы он существовал отдельно.

func doSomeAction(ctx context.Context, requestID string) {
ctx, span := global.Tracer(github.com/me/otel-demo).
Start(ctx, child)
defer span.End()
span.AddEvent(ctx, I am a child span!)

}

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

Дальше создается дочерний span из контекста, и ему присваивается имя по аналогии с тем, как мы делали это в начале:


Start(ctx, child)


Не забудьте, что span нужно закрыть в конце метода, в котором он был создан.


ctx, span := global.Tracer(github.com/me/otel-demo).
Start(ctx, child)
defer span.End()


Пишем в него сообщения, которые попадают в дочерний span.



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

В нем показываются атрибуты, которые можно писать в span:

func doSomeAction(ctx context.Context, requestID string) {

span.SetAttributes(label.String(request.id, requestID))
span.AddEvent(ctx, request validation ok)
span.AddEvent(ctx, entities loaded, label.Int64(count, 123))
span.SetStatus(codes.Error, insertion error)
}

Например, сюда попал наш request. id:



Можно добавлять events:


span.AddEvent(ctx, request validation ok)


Кроме того, сюда можно добавлять label. Это работает примерно также, как структурный лог в виде logrus:


span.AddEvent(ctx, entities loaded, label.Int64(count, 123))


Здесь мы видим свое сообщение в логе span. Можно развернуть его и посмотреть labels. В нашем случае сюда добавился label count:



Потом это будет удобно использовать при фильтрации в поиске.

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


span.SetStatus(codes.Error, insertion error)


Раньше стандарт использовал коды ошибок из OpenCensus, и они были из grpc. Сейчас оставили только OK, ERROR и UNSET. OK ставится по умолчанию, ERROR в случае ошибки добавляете вы.

Здесь видно, что трейс ошибки помечен красным значком. Есть код ошибки и сообщение о ней:



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

Трейсинг микросервисов

В OpenTelemetry уже есть множество set party реализаций interceptors и middleware для различных фреймворков и библиотек. Их можно найти в репозитории: github.com/open-telemetry/opentelemetry-go-contrib

Список фреймворков, для которых есть interceptors и middleware:

  • beego
  • go-restful
  • gin
  • gocql
  • mux
  • echo
  • http
  • grpc
  • sarama
  • memcache
  • mongo
  • macaron


Как это использовать, посмотрим на примере стандартного http клиента и сервера.

middleware client

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

client := http.Client{
Transport: otelhttp.NewTransport(http.DefaultTransport),
}
req, _ := http.NewRequestWithContext(ctx, GET, url, nil)
resp, err := client.Do(req)

middleware server

На сервере добавляется небольшой middleware с названием библиотеки:

http.Handle("/", otelhttp.NewHandler(
http.HandlerFunc(get), root))
err := http.ListenAndServe(addr, nil)

Дальше как обычно: получаете span из контекста, работаете с ним, пишите в него что-то, создаете дочерние spans, закрываете их и т.д.

Так выглядит простой запрос, проходящий через три сервиса:



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

А так выглядит ошибка:



Легко отследить, где она произошла, когда и сколько времени прошло.
В span можно посмотреть подробную информацию о контексте, в котором произошла ошибка:



Более того, поля, которые относятся ко всему span (различные id запроса, ключевые поля в таблице в запросе, еще какие-то мета данные, которые вы хотите положить) можно вкладывать в span при его создании. Грубо говоря, не нужно копипастить все эти поля в каждое место, где вы обрабатываете ошибку. Можно записать данные о ней в span.

middleware func

Вот небольшой бонус: как сделать middleware, чтобы можно было использовать его в качестве глобального middleware для таких вещей как Gorilla и Gin:

middleware := func(h http.Handler) http.Handler {
return otelhttp.NewHandler(h, root)
}

Инструментация Golang приложения: мониторинг

Пришло время поговорить о мониторинге.

Подключение к системе мониторинга настраивается аналогично тому, что делается для трейсинга.

Измерения делятся на два типа:

1. Синхронные, когда пользователь явно передает значения в момент вызова:
  • Counter
  • UpDownCounter
  • ValueRecorder


int64, float64

2. Асинхронные, которые SDK считывает в момент коллекта данных из приложения:
  • SumObserver
  • UpDownSumObserver
  • ValueObserver


int64, float64

Сами метрики бывают:

Аддитивные и монотонные (Counter, SumObserver), которые суммируют положительные числа, и они не уменьшаются.

Аддитивные, но не монотонные (UpDownCounter, UpDownSumObserver), которые могут суммировать положительные и отрицательные числа.

Неаддитивные (ValueRecorder, ValueObserver), которые просто записывают последовательность значений. Например, какое-то распределение.

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

meter := global.Meter(github.com/ilyakaznacheev/otel-demo)
floatCounter := metric.Must(meter).NewFloat64Counter(
float_counter,
metric.WithDescription(Cumulative float counter),
).Bind(label.String(label_a, some label))
defer floatCounter.Unbind()

Дальше создается метрика:


floatCounter := metric.Must(meter).NewFloat64Counter(
float_counter,
metric.WithDescription(Cumulative float counter),
).Bind(label.String(label_a, some label))


Ей указывается название:


float_counter,


Описание:


metric.WithDescription(Cumulative float counter),


Набор лейблов, по которым вы потом можете фильтровать запросы. Например, при построении дашбордов в Grafana:


).Bind(label.String(label_a, some label))


В конце программы также нужно вызвать Unbind для каждой метрики, что освободит ресурсы и правильно ее закроет:


defer floatCounter.Unbind()


Записывать изменения просто:

var (
counter metric.BoundFloat64Counter
udCounter metric.BoundFloat64UpDownCounter
valueRecorder metric.BoundFloat64ValueRecorder
)

counter.Add(ctx, 1.5)
udCounter.Add(ctx, -2.5)
valueRecorder.Record(ctx, 3.5)

Это положительные числа для Counter, любые числа для UpDownCounter, которые он будет суммировать, и также любые числа для ValueRecorder. Для всех видов инструментов в Go поддерживаются int64 и float64.

Вот что мы получаем на выходе:

# HELP float_counter Cumulative float counter
# TYPE float_counter counter
float_counter{label_a=some label} 20

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

Инструментация Golang приложения: библиотеки

Последнее, о чем хочется сказать это возможность, которую стандарт дает для инструментирования библиотек.

Раньше, когда использовались OpenCensus и OpenTracing, вы не могли инструментировать ваши отдельные библиотеки, особенно опенсорсные. Потому что в этом случае у вас получался vendor lock-in. Тот, кто плотно работал с трейсингом, наверняка обращал внимание на то, что большие клиентские библиотеки, или крупные API к облачным сервисам, время от времени падают с трудно объяснимыми ошибками.

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

OpenTelemetry решает эту проблему.



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

Не нужно заботиться о vendor lock-in, не нужно переживать по поводу того, как будет использована эта информация и будет ли использована вообще. Библиотеки и приложения инструментируются заранее, а конфигурация экспорта данных указывается при инициализации приложения.

Таким образом видно, что настройки конфигурации задаются в SDK приложении. Дальше нужно заняться экспортерами трейсинга и метрик. Это может быть один экспортер через OTLP, если вы экспортируете в OpenTelemetry коллектор. Потом все необходимые трейсы и метрики попадают в контекст, а он пропагируется по дереву вызова другим методом вниз.

Приложение наследует от корневого span остальные spans, просто используя OpenTelemetry API и данные, которые лежат в контексте. При этом импортируемые библиотеки получают на вход методы контекст, пытаются считать из этого метода информацию о корневом span. Если его нет, создают свой, и дальше инструментируют логику. Таким образом, вы можете сначала инструментировать свою библиотеку.

Более того, вы можете инструментировать все, но не настраивать экспортеры данных, и просто задеплоить это.

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

Таким образом, если у вас какая-то опенсорсная библиотека, вы можете инструментировать ее при помощи OpenTelemetry. Потом люди, которые ее используют, настроят у себя OpenTelemetry и будут использовать эти данные.

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

У нас в компании активно применяется стандарт OpenCensus для трейсинга и мониторинга микросервисного ландшафта компании. Планируется внедрение OpenTelemetry после его релиза.
Подробнее..

Категории

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

  • Имя: Макс
    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