last day (28 days later) » 

12:55
Здравствуйте, а можно Вам пару вопрос по поводу моего вчерашнего вопроса?
Задавайте
я понял не состоятельность своего вопроса, и причина, скорее в моем не понимании концепции логов, но хочу разобраться в Вашем предложении
Для начала скопирую Ваши сообщения, по которым у меня вопросы
Возможности расширить Nlog в этом месте нет, но никто не запрещает сделать свой LogManagerEx, который по нужным данным "имя логгера+контекст" выдавать обернутый логгер Nlog или же копию обертки, если логгер разделен по уровням – vitidev 15 часов назад


Меня вот в pet-проекте утомило, что все сообщения пишутс одновременно и я использовал контекстные врапперы-логгеры доступные через ambient context - на старте using(var logger=new ...) устанавливаем контекст, а на Dispose отдаем нижележащему логгеру все, что накопилось
"или же копию обертки, если логгер разделен по уровням" - вот эту часть не понял
уровни типа debug, info, error? эти?
Вы хотите сделать накопительный логгер а-ля StringBuilder только для логов. Нет проблем, если все логи пишутся на одном уровне выполнение- получили логгер, обернули и используем. Но у нас могут быть вызовы другим методов внутри которых мы тоже хотим чтобы логировалось в эту же обертку. А значит обертку нужно либо передать через параметр при вызове метода либо в своем LogManagerEx отслеживать это, хранить копию обертки и отдавать копию, ну или еще как - вариантов тут не один
@vitidev, а понял, типа статический LogManagerEx управляет инстансами моих врапперов?
угу. по имени и данным контекста он будет возвращать обертку или обертку и дочерние обертки. По необходимости.
13:09
@vitidev, и дочерние обертки?
это зависит от вашего кода. если вы вернете тот же инстанс обертки и другим частям системы, то все они будут писать в одну очередь сообщений. А если породите для них дочерние обертки, то они будут заполнять свои очереди и только потом сольют все воедино. Дочерняя обертка хотя бы полезна тем что будет автоматически вписывать имя дочернего логгера
@vitidev, "имя логгера+контекст" - это тот же самый контекст, что и "ambient context" из второго сообщения?
нет. контекст это контекст типа id юзера, сессии и так далее. Ambient Context это фича дотнета. Например TransactionScope яркий пример. Мне нужно было в многопоточном приложении на UI выводить реалтайм детальный лог для каждого "логического потока". Так я в начале операции стартую using(var logger=new ContextLogger) а внутри он доступен через ContextLogger.Current и внутренней части приложение не нужно знание в каком контексте его используют
Без этого мне пришлось бы таскать по уровням свой логгер для каждого "логического потока".
13:32
@vitidev, а вот тут я совсем потерялся...
что такое "логический поток"?
@vitidev
4. Ambient Context (фоновый контекст)
Идея Ambient Context заключается в создании pubic static свойства или метода, предоставляющих экземпляр объекта определенного типа и доступного любому объекту в приложении. По смыслу такой подход применим для зависимостей, предоставляемых framework и прочими глобальными объектами приложения.

Примеры шаблона в .NET: Application.Current, Thread.CurrentCultureand, Thread.CurrentUICulture, System.Web.Http.GlobalConfiguration.Configuration, Microsoft.AspNet.SignalR.GlobalHost.DependencyResolver, OperationContext.Current и т.п.
ну код благодаря async/await проходит по многим потокам пула
это "поток выполнения"
вообще то считается некоторым антипаттерном в силу неясности "в каком контексте выполняется код"
но тут уже фломастеры
в вашем случае он просто может добавить удобства стартовав на верхнем уровне обертку и на нижнем уровне просто обращаться через Logger.Current и потом по Dispose сбросится все в логгер или не сбросится
фреймворк сам следит за потоком выполнения.
Я не могу сказать что это хорошее решение в общем случае ( для вашего то точно неплохое), но таскать по всем уровням идентификаторы контекста для логгеров тоже не самое приятное занятие.
@vitidev, я более-менее знаю как работает async/await, и лучше понимаю, если что-то объяснять на его примере

но у меня вопросов все больше)
1) в силу неясности "в каком контексте выполняется код" - в syncronizationContext'е же, не?
2) таки syncronizationContext - это типичный пример "ambient context"?
3) логический поток - это тот самый "поток выполнения"?
4) что значит фреймворк сам следит за потоком выполнения?
13:48
1) я не об этом. Например с транзакциями Transaction.Current не должен быть null. То есть вызвав этот код где то вне транзакции получим NRE
2) Типичный пример это TransctionScope+Transction,Current
Transction,Current всегда указывает на правильный инстанс транзации даже если паралельно было запущен это код много раз
3) ну да. я неясно выразился. терминология не мой конек
4) это значит что если вы запустите параллельно одновременно метод DoSome где внутри будет using(var tran=new TransactionSope) то во вложенных методах Transction,Current будет указывать на правильное значение и никакие пар
Для обычных потоков есть хранилище ThreadLocal вроде где следит чтобы данные для разных потоков не пересекались даже если у них одно имя. Так и для потока выполнения есть то же самое.
там все просто
@vitidev acyncLocal?
CallContext
@vitidev, ох, сейчас как-то смешалось в одну кучу...
"Мне нужно было в многопоточном приложении на UI выводить реалтайм детальный лог для каждого "логического потока". Так я в начале операции стартую using(var logger=new ContextLogger) а внутри он доступен через ContextLogger.Current и внутренней части приложение не нужно знание в каком контексте его используют" - типа когда создается объект ContextLogger, то создается какая-то запись в CallContext, потом мы к ней можем обращаться через ContextLogger.Current, а во время dispose эта запись удаляется? так?
С ambient context абсолютно верно. вот вам набросок paste.org.ru/?xcxcrt
внутри кода вызываете SharedLogger.Current?.Info(...) и заполняете очередь logeEvents. Если Warn или Error то ставите флаг, что нужно сливать в нижележащий логгер и в Dispose сливаете. А можете и просто Flush метод сделать. CallContext позаботится о том чтобы был правильнй инстанс логгера.
очень удобно в этот инстанс пихать айди операции, а не таскать ее везде.
ну и про защиту нижележащего логгера от многопоточного доступа подумайте. или пишет в разные файлы или еще как. А то 2 параллельные операции Flush перемешают строки...что не проблема если у каждой строки вписан id операции
14:12
@vitidev, раньше не встречался с transactionScope и callcontext.
transactionScope тоже реализован через callcontext? реализация через callcontext можно считать фишкой Ambient Context?

а как реализован сам callcontext? и использовался ли он до async/await?
@vitidev, и что Вы имели в виду, когда говорили "Ambient Context это фича дотнета"?
Ну что там такое есть и можно его использовать. В пхп, питоне, руби и так далее подобного вот нет.
а проблемы логгинга те же - но там только стандартные способы типа "передадим логгер через параметр"
правда там и многопоточности обычно нет
@vitidev, а там выше вопросы про callcontext
а как устроен transactionScope я не разбирался. он родился до эпохи async
ну то что предоставляет callcontext в дотнете называется ambient context. Не я придумал
в смысле предоставляет?
слежение за потоком выполнение и правильное содержимое CallContext.LogicalGetData(Name)

вы же понимаете что в 1 метод может параллельно войти 1000 потоков выполнения
14:23
понимаю
а до async/await как применялся call context?
если бы я делал вашу задачу (забудем про пролему XY) то это 3 варианта
1) создаю обертку с flush и передаю ее как параметр. то есть таскаю везде
2) LogManagerEx при первом вызове по имени даст мне обертку, а для других будет копию давать или дочерние обертккологгеры. Но тогда я должен передать id операции в места вызовов этих логгеров. То есть снова что то передавать
3) я создаю обертку используя CallContext и тогда внутри используется доступ через статик поле. Ничего передавать нигде не нужно.
до них использовались потоки. Потому TransactionScope, Monitor и прочее требуют одного потока. В TransactionScope потом добавили флаг чтобы он умел async проходить.
за подробностями вам лучше к VlaD и другим. я не специалист в дотнете чтобы ух.
@vitidev, 1) обертку над чем?
@Qutrix Это номер сообщения 40000000, поздравление
@fredley ох, спасибо) надо бежать за лотерейным билетиком с такой удачей)
1) над обычным логгером. Обертка будет накапливать сообщения логов и слать их дальше только если нужно
14:35
@Qutrix Большинство коэффициентов лотереи лучше 40 миллионов к одному!
(Простите мои переводы Google)
@vitidev, можно подробнее про 2? какой id и куда передавать? типа тот контекст, по которому отдавать определенный логгер?
@fredley 4 billion:1 maybe?
@fredley I'm afraid that I spent my limit on luck today :(
это проблема многопоточных приложений. допустим у вас сайт и туда пришли 100 человек одновременно и заказали товар. Как вы потом в логах отличите где кто?
для этого нужно вписывать в сообщения лога id запроса пользователя. А это значит этот id нужно таскать по всей системе.

у вас же мы должны получить одну и ту же обертку с разных мест по имени логгера + id операции. То есть снова придется таскать его как то. или параметрами или как в ASP сделано там вроде бы текущий пользователь тоже через callcontext сделан. можно так и айди операции организовать.
в asp есть HttpContext.Current в котором вся информация и сложена. и если ее использовать при получени логгера, то будет получен верный логгер. Но опять же дать логгеру контекст непонятно как - приходится в каждом лог сообщении вписывать id операции/юзера. Это надоедает и рождается обертка, которая вписывает это за нас
вот примерно у меня такая paste.org.ru/?w95t2p для Nlog. но это мы уже в сторону ушли
15:00
@vitidev, с логерами вроде как понятно, но остались маленькие вопросики по обсуждению
@vitidev так ведь благодаря callcontext ясно же, не?
@vitidev что значит требуют одного потока?
>так ведь благодаря callcontext ясно же

TransactionScope и callcontext могут не использовать один другого, а использовать какой то общий внутренний механизм.

>что значит требуют одного потока?

Именно требуют того же физического потока. Нельзя монитором захватить лок одним потоком и освободить в другом потоке.
15:22
@vitidev, спасибо Вам, благодаря Вам что-то стало понятно и что-то новое узнал
а откуда Вы знаете про callcontext и про ambient context? может из книги какой? я бы почитал
Нет. Я из тех кто умеет быстро гуглить и адаптировать
https://aabs.wordpress.com/2007/12/31/the-ambient-context-design-pattern-in-net/
вам хватит более чем для понимания как использовать
древняя вещь раз статья 2007года
и еще. Logger.Current пусть возвращает логгер из которого нужно будет породить дочерние логгеры с именем логера. Тогда в логах будет все красиво и имена логгеров будут прописаны. Иначе придется все это вписывать в сообщения, что неудобно
ну это у вас и у меня вот такие задачи. а обычно сводится к "пишем логи кучей в разные файлы и для того чтобы потом найти кто где дописываем к сообщению лога контекст, то бишь какой то id операции/пользователя/итд.".
а может и нет. чет я не вижу в той статье CallContext
ну неважно. вы знаете про паттерн и про CallContext. у вас даже пример есть. нагуглите все что нужно
15:45
@vitidev породить из логера дочерние логеры?
можете не порождать. но если вам захочется в логах видеть какой сегмент приложения оставил сообщение то придется вписать это в сообщение иначе. В андроид например передается TAG как имя того, кто владелец этого сообщения в логе
я не люблю в каждом сообщении это вписывать потому делаю обертку где вписывается за меня
тот же Nlog вписывает имя логгера за вас, а вы ему имя даете при получении логгера и больше не таскаетесь с ним
15:59
@vitidev я просто не понимаю: логер, который создает логер? можно пример?
ну да. логгер который создает логгер с заданным именем. и сообщения дочернего логгера попадают в родительский логгер + имя логгера добавляется для удобства.

если у вас будет один инстанс логгера, а он у вас они в Logger.Current, то вам придется подумать как прописывать информацию о месте в приложении где рождается сообщение. Можете вписывать прямо в сообщение, а можете просто создать легковесный дочерний логгер с именем, который будет вписывать за вас
@vitidev а, все, спасибо Вам огромное)
16:24
@Qutrix congratulations for being the message with id 40000000 :P
17:09
@LeakyNun Thanks :)

  last day (28 days later) »