В Web SDK отсутствует возможность полностью выключить логгирование в консоль браузера

Axel

Member
Здравствуйте.

В Web SDK отсутствует возможность полностью отключить логгирование, возможно лишь изменить severity логгера. Как следствие, в конфиге по-умолчанию, в консоли браузера видно много "внутренней кухни" SDK, что само по себе уже плохо, и может быть совершенно неуместным в случае, если поверх Web SDK пишется обёртка для предоставления партнёрам, инкапсулирующая многие аспекты работы с ним.

Частично проблема решается установкой severity, скажем, в "WARN", но это костыль, так как логгер https://github.com/flashphoner/flashphoner_client/blob/wcs_api-2.0/src/util.js#L171 безальтернативно использует "console.log()" для всех уровней.

Второй стороной проблемы является невозможность перехвата этих логов. Скажем, если на фронтенде используется какой-либо трекер ошибок вроде Sentry или система сбора телеметрии, то было бы очень здорово иметь возможность зароутить логи из SDK в эти системы. Отчасти, это можно сделать подпиской на все события различных объектов SDK, но это лишь малая часть доступной информации (особенно в сравнении с severity "TRACE") и придётся писать много boilerplate-кода. Для решения этой задачи было бы неплохо иметь возможность подменять логгер на свою реализацию, либо позволить передавать коллекцию инстансов таких логгеров с интерфейсом того, который лежит в упомянутом выше "util.js", что бы вызов метода текущего внутреннего логгера (info(), debug(), etc.) сопровождался вызовом аналогичного метода и "внешнего" логгера.

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

- для метода "Flashphoner.init()" добавить новое свойство в объект конфигурации логгера "logger", которое позволит отключить запись логов всех уровней в консоль браузера. Предусмотреть управление этой опцией логгера через объект, получаемый методом "Flashphoner.getLogger()", что бы была возможность включать и выключать эту опцию вне этапа конфигурирования Flashphoner через вызов "init()"
- в дополнение к предыдущему пункту, для метода "Flashphoner.init()" добавить новое свойство-массив в объект конфигурации логгера "logger", которое позволит указывать список инстансов собственных логгеров для сбора информации от SDK, как было сказано выше.

Пример кода для STR:

Code:
Flashphoner.init();
Сообщения в консоли браузера:

Code:
INFO webrtc -  Initialized
INFO websocket -  Initialized
INFO core -  Initialized
 

Max

Administrator
Staff member
Добрый день.
Спасибо за подробный вопрос, мы рассмотрим возможность расширенных настроек логирования в WebSDK и сообщим вам о результате. По обращению создан внутренний тикет WCS-2340.
Если вам необходимо реализовать указанный функционал в данный момент, рекомендуем самостоятельно собрать WebSDK с необходимыми изменениями.
 
Last edited:

Max

Administrator
Staff member
Добрый день.
В сборке 0.5.28.2753.131 (исходный код на GitHub доступен по тэгу 05cb5bd) добавлены:
- возможность отключения логирования (как на этапе инициализации API, так и на ходу вызовом функции)
- определения кастомного логгера
Подробности см в документации.
 

Axel

Member
Здравствуйте.

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

В моём случае, для конечных пользователей поставляется библиотека, которая абстрагирует их от тонкостей работы с Flashphoner WebSDK, упрощая интеграционные моменты с нашим продуктом. В библиотеке используется две простых абстракции - Publisher и Player. Каждая из этих абстракций имеет в конструкторе класса примерно такой код (упрощён):

Code:
// Для Player то же самое

class Publisher {
    constructor(config) {
        Flashphoner.init({logger: /** create Flashphoner logger config here from "config" arg});
    }
}
Для программиста-пользователя библиотеки эти абстракции прозрачны в контексте практик ООП: два раздельных инстанса двух разных объектов каждый используют независимо свой логгер. И, при передаче туда инстанса логгера через конфиг, пользователь ожидает, что каждый инстанс логгера будет использован изолированно, т.е., то, что пишет в лог Publisher, не будет никак влиять на то, что пишет в лог Player, и наоборот.

Однако, под капотом у обеих классов используется метод "Flashphoner.init()", который внутри себя проверяет статус "инициализированности" и устанавливает логгер лишь единожды, глобально, для всех адаптеров. В конечном счёте, когда на странице одновременно используется и Publisher, и Player, только один из логгеров будет задействован - тот, который попал в вызов "Flashphoner.init()" первым.

В примере выше описана базовая ситуация, в реальности же есть ещё несколько абстракций, которые требуют вызова "Flashphoner.init()" и подвержены такой же проблеме.

В мире разработки (не только веб) хорошей практикой обоснованно считается, что использовать глобальное состояние где бы то ни было - весомый антипаттерн. Да, в браузере есть window и прочие, но это легаси. В случае с логгером, теряется возможность разделить каналы информации, так как всё сыпется в один логгер; теряется гибкость конфигурирования; невозможно понять, кто записал этот лог - паблишер, плеер, кто-то ещё? Попытки написать какие-либо абстракции поверх Web SDK обречены на подобные "протекающие абстракции" (это касается не только логгирования, об этом ниже).

Собственно, вопрос в следующем: возможно ли изменить кодовую базу Web SDK так, что бы логгеры при вызове "Flashphoner.init()" всё же были независимы? Беглый просмотр кода этого метода показал, что внутри него заранее создаются объекты всех медиапровайдеров, которые в дальшейшем не реинициализируются и берутся из кеша, в эти же объекты прокидывается и единый инстанс логгера.

Как компромиссный по трудозатратам вариант решения, можно изменить workflow работы с Web SDK, убрав глобальный стейт, создающийся через "Flashphoner.init()", и заменить его хотя бы на что-то вроде "new Flashphoner()", что позволило бы создавать несколько независимых инстансов, тем не менее загружая некие общие структуры в глобальное состояние, если это потребуется для оптимизации производительности.

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

Понимаю, что выбранный мной подход использования Web SDK не является истинно верным, и можно сказать, что надо использовать его иначе. Но, перечисленные выше нюансы могут ограничивать пользователя и при других подходах, тогда как отказ от глобального состояния добавил бы необходимую гибкость, которая была бы применима во всех возможных случаях.
 
Last edited:

Max

Administrator
Staff member
Добрый день.
Действительно, в настоящее время используется общий логгер, поскольку независимое логирование для паблишера и подписчика на одной странице не предполагается. Кроме того, медиапровайдер на страницу должен быть один, т.е. нельзя публиковать поток по WebRTC и играть его по MSE на той же странице. Мы создали тикет WCS-2434, но, скорее всего, какие-то изменения в этой части будут в следующей мажорной версии WebSDK.
Что касается одновременного подключения с одной страницы к двум WCS серверам, это возможно, т.к. объекты Session разделены.
 

Axel

Member
Здравствуйте.

Кроме того, медиапровайдер на страницу должен быть один, т.е. нельзя публиковать поток по WebRTC и играть его по MSE на той же странице.
А если требуется публиковать два потока с одной страницы, с различными медиапровайдерами, скажем, WebRTC и Flash, и их же проигрывать на той же странице так же каждый со своим медиапровайдером?

Что касается одновременного подключения с одной страницы к двум WCS серверам, это возможно, т.к. объекты Session разделены.
Подключения - да, но я писал именно о логгере, он ведь будет общим для обеих подключений в этом случае, так как устанавливается на уровне инициализации всего Web SDK, а не сессии.

Мы создали тикет WCS-2434, но, скорее всего, какие-то изменения в этой части будут в следующей мажорной версии WebSDK.
Текущая версия - 0.*, что, согласно SemVer вполне допускает радикальные изменения API "здесь и сейчас":

Code:
Major version zero (0.y.z) is for initial development.
Anything MAY change at any time. 
The public API SHOULD NOT be considered stable.
Понимаю, что это не совсем тривиальная задача, потому хочу уточнить, какой у неё приоритет и ЕТА?
 

Max

Administrator
Staff member
А если требуется публиковать два потока с одной страницы, с различными медиапровайдерами, скажем, WebRTC и Flash, и их же проигрывать на той же странице так же каждый со своим медиапровайдером?
Пример одновременной публикации WebRTC потока и воспроизведения Flash есть на GitHub.
По сути, с наступающего года года в браузерах должно остаться три медиапровайдера: WebRTC (публикация и воспроизведение), MSE (воспроизведение) и HLS (воспроизведение), если Adobe прекратит поддержку Flash. WebRTC и HLS вполне уживаются на одной странице, проблемы в текущей реализации могут быть только при скрещивании с MSE.
Понимаю, что это не совсем тривиальная задача, потому хочу уточнить, какой у неё приоритет и ЕТА?
Приоритет одинаковый для запросов с форума. У задач клиентов расширенной поддержки (Priority Support) он выше.
 

Axel

Member
Пример одновременной публикации WebRTC потока и воспроизведения Flash есть на GitHub.
Но я писал о другой ситуации: одновременная публикация одного потока через WebRTC и второго через Flash на одной странице в браузере. Или одновременное воспроизведение двух потоков на той же странице, один из которых где-то ранее, в другом месте, публикуется через WebRTC и через него же воспроизводится, а второй - аналогично через Flash. Или всё вместе - и публикация, и воспроизведение. Выше вы писали, что "медиапровайдер на страницу должен быть один", в примере на GitHub, похоже, так и есть, т.е., паблишить сразу два потока, используя разные протоколы (WebRTC и Flash\RTMP, например), всё же нельзя?

если Adobe прекратит поддержку Flash
Уже прекратили, в том числе, и протокола RTMP, который объявлен как deprecated. Но браузеры ещё будут поддерживать, по крайней мере, до конца 2020 года (Google Chrome).
 

Max

Administrator
Staff member
паблишить сразу два потока, используя разные протоколы (WebRTC и Flash\RTMP, например), всё же нельзя?
Можно. Вы реализуете свою флэшку для публикации и воспроизведения и просто подгружаете ее на страницу в div-элемент, как это и делается в примере, а WebRTC поток публикуете или играете средствами WebSDK.
 

Axel

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

Max

Administrator
Staff member
Добрый день.
Через WebSDK RTMP не публикуется в принципе, только WebRTC. Публиковать два WebRTC потока с одной страницы можно, при условии создания двух отдельных сессий.
Для публикации/проигрывания RTMP в браузере необходимо использовать Flash. В этом случае два потока также можно публиковать с одной страницы.
Проблемы могут возникнуть при одновременном воспроизведении WebRTC и MSE из-за общей настройки preferredMediaProvider, но этот случай в реальности маловероятен, поскольку MSE для проигрывания используется там, где открыт только один 443 порт, через который и надо пропихнуть весь медиатрафик к клиенту, и WebRTC у такого клиента работать не будет.
Таким образом, единственной проблемой при публикации двух и более WebRTC потоков с одной страницы остается общий лог для двух сессий, тикет по этому поводу заведен, об изменениях мы сообщим в данной теме.
 

Axel

Member
Через WebSDK RTMP не публикуется в принципе, только WebRTC.
По существу вопроса всё понятно, но, тем не менее, Flash-медиапровайдер в коде Web SDK существует, и в контексте вашего утверждения "медиапровайдер на страницу должен быть один", я предположил, что это касается и RTMP.

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

Упомянутый выше "preferredMediaProvider" тоже можно попутно исправить, если будет вдохновение :)
 
Top