Pull to refresh

Comments 29

сейчас перехватчики точно поддерживаются из коробки Autofac и Castle.Windsor, про остальные не знаю

В Unity interception просто свой.

Да, возможно. Unity уж больно медленный, поэтому много лет его не использую

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

Не вижу проблемы в зависимости от IoC контейнера. Контейнер выбирается как раз за специфические фичи. Так же как и логгер собственно.

… и именно поэтому последующая смена одного или другого обходится дорого.

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

Глупо. А вот не дать этим фичам просочиться в клиентский код — уже не глупо.


И эти компоненты обычно не меняются часто, если вообще меняются.

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

Что вы подразумеваете под просочиться и под клиентский код ;)?

По второму пункту думал примерно так же как и вы. Абстракция над логгером прожила 3 года. Потом перешли на Serilog и она превратилась в тыкву :)
Например, когда начинают использовать инъекции в property с атрибутом [Dependency]. Моя ненависть к Unity началась с этого.
Нууу это ай ай ай конечно. Но абстракция от контейнера вас тут не спасет.

Вот тут на почитать: https://simpleinjector.org/blog/2016/07/working-around-the-asp-net-core-di-abstraction/
Что вы подразумеваете под просочиться и под клиентский код

Я имею в виду, что когда у меня в системе есть 100500 мест, использующих логгирование, все они начинают зависеть от (например) Serilog.ILogger. И в этот момент выбрасывание серилога начинает стоить денег.

А есть ли смысл выбрасывать? Я за 12 лет менял логгер 3 раза. 3! А вот абстракций видел на 20 лет вперед ;)
При том что в принципе даже абстракция вас не спасет, так как Serilog использует свое форматирование. Тоесть даже если прокинуть MyFanceAbstractLogger и написать,
Logger.Info("Something went wrong during {@Something} because user is {Reason}", Something, Reason)

то вы все равно упретесь в переписывание всех сообщений. Опять вас абстракция не спасет :)

Сейчас я использую абстракции вида LibLog для распространяемых библиотек.
Серверный код просто использует специфичные для Serilog врапперы для удобного DI типа ILogger.

А есть ли смысл выбрасывать? Я за 12 лет менял логгер 3 раза. 3!

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


При том что в принципе даже абстракция вас не спасет, так как Serilog использует свое форматирование.

Ну так абстракция форматирование тоже должна абстрагировать.


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

Я как раз пришел к выводу, что излишние абстракции не помогают, а наоборот вредят в среднесрочной и долгосрочной перспективе. Сам использую простые обертки для более удобного DI типа ILogger. Но фишки Serilog используются во всю. И в принципе их просто так не заменить. Но вот за них то Serilog и выбран :)

Форматирование очень тяжело абстрагировать, так как старое поколение (Log4Net, NLog2) не являются структурными логгерами, а SLAB — тихий ужас :)

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

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

Я не загадываю. Просто понимаю, смена основных инфраструктурных компонентов не бывает бесплатной, сколько бы не абстрагировались от них :) KISS and YAGNI :)
> Ну так абстракция форматирование тоже должна абстрагировать.

Можно с этого места поподробнее? Я вижу 3 варианта:
1) писать Logger.Info(«Something went wrong during {@Something} because user is {Reason}», Something, Reason), то есть использовать синтаксис того, что под руками
2) писать Logger.Info(«Something went wrong during {0} because user is {1}», Something, Reason), как более «стандартное», с оверхедом и надеждой, что следующий логгер будет совместим.
3) писать Logger.Info(«Something went wrong during %%0%% because user is %%1%%», Something, Reason) — придумать свой синтаксис, который потом поддерживать в каждом логгере.

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

Вы каким путём идёте?

Мы пока не идем никаким путем, мы размышляем. Но одна из веток размышления выглядит как "взять семантически подходящий синтаксис (Serilog-овский выглядит подходящим), затем адаптировать его для тех, кто его не поддерживает".

А можете подробно рассказать, откуда необходимость в большом количестве логов? Фин/гос сектор, каждый пук надо записывать?

Типа того. Плюс много неподконтрольных инсталляций (продукт, а не сервис), поэтому для пост-мортем логи помогают.

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

Мы вообще пошли радикальным путем и написали абстракцию от инфраструктуры: https://github.com/hightechtoday/costeffectivecode. Теперь нам все-равно откуда будут данные — из БД, соц.сети, Yandex Market'а. Берем и пишем реализацию IQuery. Так-же пофиг на ORM клиента, потому что она в итоге все-равно скрыта за IQuery. И ILog и IMapper, Pub/Sub тоже наши. Для наших задач подход себя оправдал на все 100%.
Если у вас heavy logic — то возможно имеет смысл. У меня в проектах в основном такой логики нет и поэтому стараемся минимизировать абстракции И максимально использовать фичи тех компонентов, что используются.
Причины было три:
  1. да, часто вагон и маленькая тележка БЛ.
  2. более чем в половине случаев работа с унаследованными системами, нужен какой-то repair-toolkit для рефакторинга
  3. необходимость в быстром прототипировании
Поэтому и имеет смысл, если нет необходимости в специфике. Плюс у вас фреймворк — тоесть вы решаете обобщенные задачи, поэтому вам необходимо предоставлять интерфейсы для интеграции. Для продукта, который не является фреймворком, смысла в этом не особо много.
На мой взгляд реализация через докораторы гораздо наглядней и менее зависит от IOC. Вот прекрасный
пример

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


А при чем тут множественное наследование?

Так тоже можно. Разница в том, что логирование любых методов с помощью одного декоратора не сделать, а так можно.
Хм, так вроде postsharp на Interceptor и сделан? В его функциональности чего то не хватает, или просто нет желания платную библиотеку в код добавлять?
Postsharp переписывает IL при компиляции
Sign up to leave a comment.

Articles