Привет, Хабр! Мы тут решили выйти из тени, на этот раз по-настоящему, технически, без маркетинговых текстов. А раз без маркетинга, то почитать про сам Brand Analytics можно на сайте или очень кратко под катом.
Меня зовут Островский Григорий, я CTO Brand Analytics. Сегодня расскажу, как за 4 недели мы запускали Детектор сбоев взамен ушедшему из рунета Downdetector: на какие задачки напоролись, как с ними боролись и как пришла идея — дать возможность сообществу улучшить определение сбоев на больших данных в нашем первом контесте.
Так как статью пишу здесь впервые, буду крайне признателен фидбеку, чтобы понять, на чём сделать больше акцент, нужно ли больше технических подробностей, какие темы остались не раскрыты и что ещё подкорректировать на будущее.
Кратко про Brand Analytics
Brand Analytics — это инструмент для анализа всех публичных, преимущественно русскоязычных, сообщений соцмедиа и СМИ.
Зачем вообще нужен Детектор сбоев?
Возьму смелость предположить, что у каждого была ситуация, когда где-то что-то не работает — или работает не так, как ожидаешь. И не понятно: не работает только у меня или ещё у кого-то? Стоит отметить, что речь не только про явные ошибки или вебсайты, которые можно проверить через множество разных соответствующих сервисов.
Вот, например, открыли вы приложение банка, и вроде само приложение работает, но на любой перевод выдаёт ошибку. А кто-то заказывает доставку еды, но оплата не проходит. Тут-то и можно узнать, что, оказывается, проблема такая не только у вас, да ещё и конкретику — проблемы с проведением оплаты у сервиса доставки еды или же общая проблема с платежами у банка.
Как? Да просто! Когда что-то не работает, пользователи интернета сразу бегут писать об этом в соцсети и на прочие площадки. И если зарубежный сервис определял сбои по таким сообщениям только из Твиттера, а также по комментариям и кнопке на своём сайте, то Детектор сбоев делает это на основе практически всех публичных русскоязычных сообщений социальных медиа.
Предвосхищая вопросы: да, этим “всем публичным сообщениям” русскоязычного сегмента интернета, видимо, стоит посвятить отдельную статью.
Первые шаги к реализации
Когда решение о разработке и запуске сервиса было принято, нужно было осознать, с чем придётся столкнуться технически и что понадобится:
Определить, что отслеживать
Для начала нужно было определить, какие сообщения считать за сбои, для каких сервисов их определять и какие аспекты присваивать. Аспекты нужны, чтобы показывать конкретную проблему, например, если не работает “вход” в интернет-банк или проблемы с “голосовой связью” у мобильного оператора — ведь остальное может в этот момент штатно работать.
В самом определении “сбоя” тоже не всё так просто. В соцсетях, например, пишут про невозможность войти в какой-либо аккаунт из-за потери пароля или блокировки аккаунта. А это, как правило, не является проблемой работоспособности сервиса. Также не стоит учитывать проблемы в работе двигателя автомобиля, а таких сообщений на разные тематики в соцсетях немало.
Почему вообще такие сообщения могут попадать? Вот наглядные примеры:
Ссылка на Телеграм не работает. А жаль.
Просто продажи через сайт/приложение РЖД на эти поезда нет. Почему? Ну это обсуждается здесь уже эдак года три. Потому что РЖД напрямую там не работает.
Ужасное приложение, глючит постоянно, не могут справиться с большим количеством людей,обновления не делают, заходить туда не хочется
Всё отлично очень нравится, но без розетки не работает. Может не до конца ещё разобрались
В каждом сообщении есть что-то похожее на сбой, но ни одно из них не говорит о том, что у какого-то сервиса что-то сломалось и не работает прямо сейчас.
Отдельная инфраструктура
Сервис полностью публичный, чем отличается от нашего основного продукта. А значит, на него, скорее всего, пойдёт высокий rps (и пошёл!), а это не должно мешать работе, собственно, Brand Analytics. Так я пришёл к выводу: нужны отдельные серверные мощности, отдельная сетевая инфраструктура и даже отдельный интернет-канал.
Решено — сделано. Отдельный пограничный маршрутизатор, коммутатор ядра и серверы. Железо менеджерим через MAAS, а виртуальные машины — через LXD, чтобы не городить сложную инфраструктуру.
Провели расчёты на потребление трафика, разделили сетевые интерфейсы так, чтобы они не перекрывали друг друга. А дальше — достаточно стандартная связка floating ip, балансировка HAProxy на несколько виртуальных серверов с Nginx. Серверы логически разделены на “внешние”, для отработки клиентских запросов, и “внутренние”, где идут непосредственно расчёты и подготовка данных.
Разработка базового функционала сайта
Backend- и frontend-разработка публичной части сайта и внутренней “админки” для управления сервисами, на которых отслеживаем сбои, и теми самыми аспектами. Вся продуктовая часть, включая дизайн, приходит от продакт-менеджера в виде подробного ТЗ с макетами, которое в процессе реализации, разумеется, немного менялось, не без этого.
Ключевое, что было решено — делать полный пререндеринг, чтобы при отработке запроса не заботиться о более сложном кешировании и неконсистентности динамических данных.
Помимо видимого функционала есть также более глубокая часть, которая касается хранения исторических данных о сообщениях со сбоями, которые нужны ещё и для создания “базовой линии”. Базовая линия — это такая “средняя” нормальная линия по количеству сообщений на каждый момент суток, превышение которой говорит о вероятном сбое. На самом деле там берётся не среднее значение, а 95-й процентиль. И превышение базовой линии считается не любое, а несколькими разными алгоритмами на каждый из статусов (“Возможен сбой”, “Сбой”, а также возврат к состоянию “Нет сбоя”).
ML-модель определения сбоев
На этот пункт изначально я не тратил время, потому что модель у нас такая уже была и хорошо работала в самом Brand Analytics. И план был простой — взять её за основу и выбрать только те сбои, которые нам нужны. Но в ней-то и крылся подвох: оказалось, что она хорошо работает на клиентских данных, а на полном, “сыром” потоке всё совсем не так. И если всё вышеописанное было сделано за 2 недели, то доведение точности определения сбоев до адекватной на полном потоке потребовало ещё дополнительные 2 недели.
Кстати, полный поток — это в среднем 82 млн сообщений в сутки, т.е. около тысячи сообщений в секунду, но в течение дня, а также в разные дни недели, поток неравномерен и скорость плавает от 600 до 1500 сообщений в секунду.
Подробнее про ML-модель и как исправляли недочёты
Итак, на клиентских данных эта модель показывала точность (accuracy) в 96%. Но когда я подсчитал её точность на полном потоке, то увидел лишь 47% и очень много нерелеванта: попадали рекламные сообщения, разный спам и даже сообщения с вакансиями — всё то, что клиенты отфильтровывают хорошо подобранными ключевыми словами, но на полном потоке такая схема не применима.
Тогда мы вспомнили, что у нас есть уже обученные наивные байесовские классификаторы, которые определяли подобные категории. Но и в этом случае ситуация была аналогична — обучены они были на клиентских сообщениях и не отлавливали другую часть нерелеванта на полном потоке.
Назревает вопрос: неужели такая большая разница между сообщениями потока и клиентскими, которые фильтруются из того же потока?
Да, это действительно так, разница существенная.
После сравнения и просмотра множества сообщений, оказалось, что сообщения, которые не попадают клиентам, содержат совершенно иную структуру текста, хотя по своей сути являются таким же спамом, как и то, что попадает под ключевые слова клиентских запросов.
Для наглядности:
![Спам-сообщение, которое попадает под клиентские ключевые слова. Вполне обычный текст. Спам-сообщение, которое попадает под клиентские ключевые слова. Вполне обычный текст.](https://habrastorage.org/getpro/habr/upload_files/3cd/3ab/766/3cd3ab7664286e132004e234de41cbf3.png)
![Спам-сообщение, которое не попадает под клиентские запросы. Имеет более "простой" текст. Спам-сообщение, которое не попадает под клиентские запросы. Имеет более "простой" текст.](https://habrastorage.org/getpro/habr/upload_files/531/785/18e/53178518e22e81a2caf4e10031e0e271.png)
Чистка нерелевантных сообщений
Для обучения практически любой модели нужен размеченный датасет, а качественная разметка, как правило, дело небыстрое. Но пришла идея как совместить необходимое с полезным.
Выше я упоминал, что на полном потоке точность модели оказалась 47%, и чтобы её посчитать, мы с командой уже разметили всё, что попало в Детектор сбоев за 2 недели, простыми категориями “релевант” и “нерелевант”. А дальше мы взяли только те сообщения, которые относились к нерелеванту и разметили их другими категориями, на основе которых обучили ещё 3 отдельных классификатора:
Новостной контент — это когда фактически новостной текст публикуется/репостится в соцсетях или в Telegram, когда однозначно нельзя определить, что это репост новости.
Спам — соответственно, тот, что попадал в Детектор сбоев в дополнение к существующему спам-классификатору
Мусор — с остатками нерелеванта мы боролись и пытались найти у них хоть какую-то логическую зависимость, но по тексту её будто не было. Тогда мы попробовали просто обучить классификатор на всех оставшихся сообщениях, которые не попали в предыдущие две категории, и ... модель отлично обучилась!
За счёт компоновки этих трёх моделей нам удалось поднять точность для сообщений, которые попадают в Детектор сбоев, до 93%. Но она варьируется, в зависимости от отслеживаемого сервиса, от 82% до 98%. Каждый классификатор, а также основная модель, определяющая сбои, выдаёт вероятность. Поэтому правила там не со строгим порогом, а именно совокупный учёт вероятностей от разных моделей несколькими формулами.
Про классификаторы
Наивные байесовские классификаторы у нас написаны на golang. Текст проходит некоторую предобработку: например, помимо того, что остаются только целые “слова”, ещё вырезаются ссылки, номера телефонов/карточек и т.д.
Не вся очистка работает одинаково и зависит от конкретного классификатора. Для классификатора спама, например, сохраняются также emoji, так как они часто используются в подобных текстах. А для классификатора новостных сообщений учитываются только слова длиною не менее 5 символов (привет юникод, эмодзи и длины строк!).
Здесь можно посмотреть примеры
? ПРОГРАММА ПО АВТОЗАГРУЗКЕ
*для торговых страниц & посредников? Автоматически загружает все новые товары от выбранных продавцов ТК Садовод
✅ Моментальный поиск товаров по закрытой ссылке
✅ Посты на стену
✅ Выбор категорий c возможностью разделить до 48 и 50+
✅ Выгрузка в × Инсту × × VK × × OK ×
✅ Соблюдение лимитов социальных сетей
✅ Из описания убрано все лишнее
✅ Описание товаров по пунктам - Цена - Название - Размеры - И т.д.
✅ × Выбор валюты × × Округление цен × × Накрутка ×
✅ Заменит все цены в тексте товара
✅ Обновление товаров - каждые 15 минут
Для классификатора спама получится так:
? программа по автозагрузке *для торговых страниц & посредников ? автоматически загружает все новые товары от выбранных продавцов тк садовод ✅ моментальный поиск товаров по закрытой ссылке ✅ посты на стену ✅ выбор категорий c возможностью разделить до и + ✅ выгрузка в × инсту × × vk × × ok × ✅ соблюдение лимитов социальных сетей ✅ из описания убрано все лишнее ✅ описание товаров по пунктам - цена - название - размеры - и т.д. ✅ × выбор валюты × × округление цен × × накрутка × ✅ заменит все цены в тексте товара ✅ обновление товаров - каждые минут
А для новостного классификатора иначе:
программа автозагрузке торговых страниц посредников автоматически загружает новые товары выбранных продавцов садовод моментальный поиск товаров закрытой ссылке посты стену выбор категорий возможностью разделить выгрузка инсту соблюдение лимитов социальных сетей описания убрано лишнее описание товаров пунктам название размеры выбор валюты округление накрутка заменит тексте товара обновление товаров каждые минут
Не моделью единой
Помимо определения сбоя, нужно ещё отнести сообщение со сбоем к тому или иному сервису, а также определить аспект сбоя, если он есть.
Реализовать подобное определение в виде модели с хорошей точностью за короткий срок нашей команде не удалось, поэтому выбор пал на то, с чем есть достаточно большой опыт работы — полнотекстовый поиск. Поэтому мы просто написали для каждого из отслеживаемых сервисов и аспектов поисковые запросы.
В нашей внутренней платформе можно писать достаточно сложные поисковые запросы с перемножением, расстоянием между словами и между скобками, но не буду углубляться и этому, возможно, стоит посвятить отдельную статью.
Как это улучшить? Предложить сделать это вам!
Исходя из всего описанного выше, можно понять, что получился эдакий не очень страшный, но всё же "Франкенштейн". Напомню, чтобы отнести сообщение ко сбою, приходится:
Применить базовые классификаторы.
Применить модель определения сбоев.
Применить 3 классификатора очистки.
Прогнать оставшиеся сообщения через полнотекст для определения сервиса.
Прогнать сообщения через полнотекст для выделения аспекта сбоя.
И здесь родилась идея — дать возможность вам решить эту задачу и поработать с нашими данными, а заодно побороться за призовой фонд!
Контест-площадку мы постарались сделать минималистичной. В качестве примера, как можно догадаться по внешнему виду, взяли известный телеграмовский contest.com. Лично мне он нравится своей ненагруженностью и акцентами на суть. Мы постарались добавить ещё больше прозрачности проведения самого контеста, поэтому для каждого решения участников будут опубликованы подробные данные и по статистике полноты и точности, и таймлайн по потреблению ресурсов в процессе тестового запуска, а также выводы stdout и stderr.
Подробное задание можно найти на странице контеста. Там же мы опубликовали ссылки на несколько датасетов с исходными данными, внутри которых кроется сбой какого-то сервиса!
На выбор инструментария или языка программирования ограничений нет, главное — обработать данные с необходимой скоростью и точностью.
Разумеется, все решения участников будут запускаться в абсолютно одинаковых условиях.
А лучшие решения (даже отдельные части) мы обязательно наградим и используем в сервисе Детектор сбоев.
Заключение
Запуская проект Детектор сбоев, мы на практике увидели разницу высоконагруженной обработки данных от высоконагруженного онлайн-сервиса. Также для нас стало неожиданностью, что “сырые” данные полного потока так сильно отличаются от тех сообщений, что отфильтровываются клиентам. Изначальное определение “сбой” и
“не сбой” для сообщений у нас превратилось в градацию аж из 9 категорий.
И теперь, мы рады дать возможность вам сделать это ещё лучше!
Постскриптум
Я и остальная команда хотели бы поделиться 10-летним опытом работы с достаточно большими кластерами Elasticsearch (и даже не в ELK стеке!), о способах обработки потоковых данных, разных подходах к NLP (от традиционной лингвистики до ML), хорошей сетевой архитектуре для бедных (не все же здесь как Яндексы и Сберы?), и даже о том как нас однажды вайпнули через хардварную закладку в маршрутизаторе.
Напишите, пожалуйста, какая из тем наиболее интересна!