Доброго времени суток!
Пишу сейчас один сервис, который будет круглосуточно выполнять всякие полезные действия.
Надо вести подробный лог.
Сейчас кодирую и вижу как буквально на глазах "полезный" код засоряется кодом логирования.
Подскажите, плиз, как вы боритесь с этой проблемной?
Про аспекты я, конечно, слышал, но не хочется под это дело сторонние библиотеки привлекать.
И, кстати, какой вариант код по-вашему предпочтительнее (на осмысленность сообщений пожалуйста внимания не обращайте):
S>В первом варианте, вроде бы логирование более централизованно, но код уж больно замусорен. S>Во втором случае код логирования слишком размазан...
S>Или все-таки на аспекты смотреть? Кто-нибудь этот функционал из BlToolkit пробовал? Я его для доступа к данным использую...
что логируем, там и пишем,в данном случае первый вариант, аспекты нужны, но не для трассировки, а в примерах именно она (никаких "бизнес" задач не решается)
"замусоривание" трейсами — вполне нормальное явление, взгляните на код, ну например System.Net.SmtpClient
Das Reich der Freiheit beginnt da, wo die Arbeit aufhört. (c) Karl Marx
Здравствуйте, ksg71, Вы писали:
K>что логируем, там и пишем,в данном случае первый вариант, аспекты нужны, но не для трассировки, а в примерах именно она (никаких "бизнес" задач не решается)
Ну в случае сервиса, если надо не просто знать нормально или НЕ нормально отработало, но еще и иметь возможность выяснить "почему отработало так, а не иначе" (я в том числе и о бизнес-логике говорю), разница между трассировкой и логами ИМХО невелика. Логи шибко подробные должны быть...
K>"замусоривание" трейсами — вполне нормальное явление, взгляните на код, ну например System.Net.SmtpClient
Слабое утешение... Потом код читать сложно...
Красота — наивысшая степень целесообразности. (c) И. Ефремов
Здравствуйте, stomsky, Вы писали:
S>Здравствуйте, ksg71, Вы писали:
K>>что логируем, там и пишем,в данном случае первый вариант, аспекты нужны, но не для трассировки, а в примерах именно она (никаких "бизнес" задач не решается) S>Ну в случае сервиса, если надо не просто знать нормально или НЕ нормально отработало, но еще и иметь возможность выяснить "почему отработало так, а не иначе" (я в том числе и о бизнес-логике говорю), разница между трассировкой и логами ИМХО невелика. Логи шибко подробные должны быть...
K>>"замусоривание" трейсами — вполне нормальное явление, взгляните на код, ну например System.Net.SmtpClient S>Слабое утешение... Потом код читать сложно...
ну почему так отработало, а не иначе, надо не логами выяснять, а тестами (я о бизнес логике)
а для диагностики — трейсы, и AOP тут, кмк, ни к чему
Das Reich der Freiheit beginnt da, wo die Arbeit aufhört. (c) Karl Marx
Здравствуйте, ksg71, Вы писали:
K>Здравствуйте, stomsky, Вы писали:
S>>Здравствуйте, ksg71, Вы писали:
K>>>что логируем, там и пишем,в данном случае первый вариант, аспекты нужны, но не для трассировки, а в примерах именно она (никаких "бизнес" задач не решается) S>>Ну в случае сервиса, если надо не просто знать нормально или НЕ нормально отработало, но еще и иметь возможность выяснить "почему отработало так, а не иначе" (я в том числе и о бизнес-логике говорю), разница между трассировкой и логами ИМХО невелика. Логи шибко подробные должны быть...
K>>>"замусоривание" трейсами — вполне нормальное явление, взгляните на код, ну например System.Net.SmtpClient S>>Слабое утешение... Потом код читать сложно...
K>ну почему так отработало, а не иначе, надо не логами выяснять, а тестами (я о бизнес логике) K>а для диагностики — трейсы, и AOP тут, кмк, ни к чему
хотя, конечно, согласен — всех ситуаций не отловить,
но и аспектами можно код усложнить и замусорить
Das Reich der Freiheit beginnt da, wo die Arbeit aufhört. (c) Karl Marx
Здравствуйте, stomsky, Вы писали:
S>Слабое утешение... Потом код читать сложно...
Я вот честно говоря не нашел в литературе подтверждение своих наработок, но давно считаю, что трассировка начала и конца функции — это плохая практика. Такое трассирование само по себе мусор, поэтому и код замусоривается. Я ниже написал какую-то конкретику. Мб она для вас тоже не подойдет. Но ключевая идея — не трассируйте тогда, когда практически очевидно, что все 3 трейса например или пройдут одновременно или не пройдут, кроме случая очевидной описки. Каждый трейс должен быть индивидуально полезен, особенно если вы его пишете вручную, а не юзаете модные библиотеки.
Наиболее полезные трэйсы/логи:
1) утверждения на предусловия
public bool IsNeedToPayBonus(Context context)
{
if (context == null)
{
Warning("Я имел в виду что тут контекст всегда задан");
return;
}
if (context.CurrentOrder == null)
{
Warning("Я имел в виду что тут у контекста есть ордер");
return;
}
return context.CurrentOrder.Price > 1000;
}
4) Трассировка конкретных значений, например, при взаимодействии с источниками данных. Короче тех значений, которые потом можно как-то где-то посмотреть
public bool IsNeedToPayBonus(Context context)
{
//...
Save(context.CurrentOrder);
Trace("Сохранил в базу ордер {0}. Цена - {1}", context.CurrentOrder.Id, context.CurrentOrder.Price);
//...
}
Здравствуйте, ksg71, Вы писали:
K>ну почему так отработало, а не иначе, надо не логами выяснять, а тестами (я о бизнес логике)
Тестирование не прокатит. Попробую изложить подробности вкратце...
Мой сервис занимается перекачкой данных из одной базы данных (древнючей-древнючей), назовем ее "Источник", в другую (MS SQL), назовем "Приемник".
Если в "Источнике" появилась новая запись, то она через некоторое время T должна оказаться в "Приемнике".
И в "Источнике" и в "Приемнике" постоянно работают пользователи.
В идеале, после копирования строки в "Приемник", пользователи не должны вносить изменения в "Источнике".
Но технически реализовать такое невозможно.
Единственный разумный выход — пометить измененную строку в "Приемнике", а GUI приложения, работающего с БД "Приемника", просигнализирует пользователю о недопустимой ситуации, чтобы дальше включился "генератор докладных записок" (ну т.е. пусть пользователи, работающие с "Приемником" предъявляют претензии пользователям, работающим с "Источником").
Так вот, в логе хотелось бы отразить обнаружение факта изменения скопированной строки.
И таких "мелочей", которых быть не должно, но они есть, потому что недопустить их возникновения НЕ возможно, много.
Поэтому лог должен быть подробный.
Красота — наивысшая степень целесообразности. (c) И. Ефремов
Здравствуйте, stomsky, Вы писали:
S>Здравствуйте, ksg71, Вы писали:
K>>ну почему так отработало, а не иначе, надо не логами выяснять, а тестами (я о бизнес логике) S>Тестирование не прокатит. Попробую изложить подробности вкратце... S>Мой сервис занимается перекачкой данных из одной базы данных (древнючей-древнючей), назовем ее "Источник", в другую (MS SQL), назовем "Приемник". S>Если в "Источнике" появилась новая запись, то она через некоторое время T должна оказаться в "Приемнике". S>И в "Источнике" и в "Приемнике" постоянно работают пользователи. S>В идеале, после копирования строки в "Приемник", пользователи не должны вносить изменения в "Источнике". S>Но технически реализовать такое невозможно. S>Единственный разумный выход — пометить измененную строку в "Приемнике", а GUI приложения, работающего с БД "Приемника", просигнализирует пользователю о недопустимой ситуации, чтобы дальше включился "генератор докладных записок" (ну т.е. пусть пользователи, работающие с "Приемником" предъявляют претензии пользователям, работающим с "Источником"). S>Так вот, в логе хотелось бы отразить обнаружение факта изменения скопированной строки. S>И таких "мелочей", которых быть не должно, но они есть, потому что недопустить их возникновения НЕ возможно, много. S>Поэтому лог должен быть подробный.
почему не прокатит?
сервис получает строку из источника, проверяет есть ли версия в приемнике, если есть — помечает и бросает исключение, нет — сохраняет в приемнике,
вся эта логика легко юнит-тестируется (при должном дизайне сервиса), а логирование сводится к минимуму
имхо и с остальными "мелочами" можно также поступить
Das Reich der Freiheit beginnt da, wo die Arbeit aufhört. (c) Karl Marx
Здравствуйте, ksg71, Вы писали:
K>почему не прокатит?
K>сервис получает строку из источника, проверяет есть ли версия в приемнике, если есть — помечает и бросает исключение, нет — сохраняет в приемнике, K>вся эта логика легко юнит-тестируется (при должном дизайне сервиса), а логирование сводится к минимуму K>имхо и с остальными "мелочами" можно также поступить
Да я не об этом!
Просто в "Приемнике" есть битовый флаг "Запись изменена в 'Источнике'".
Но что именно изменилось? Какое именно поле?
Вот в лог я и напишу, что у платежного поручения изменилась, например, сумма.
В моем случае лог ведется не только и не столько для отладки и технической диагностики, но и с целью выявления неких обстоятельств в сфере бизнес-логики.
Красота — наивысшая степень целесообразности. (c) И. Ефремов
Здравствуйте, stomsky, Вы писали:
S>Здравствуйте, ksg71, Вы писали:
K>>почему не прокатит?
K>>сервис получает строку из источника, проверяет есть ли версия в приемнике, если есть — помечает и бросает исключение, нет — сохраняет в приемнике, K>>вся эта логика легко юнит-тестируется (при должном дизайне сервиса), а логирование сводится к минимуму K>>имхо и с остальными "мелочами" можно также поступить S>Да я не об этом! S>Просто в "Приемнике" есть битовый флаг "Запись изменена в 'Источнике'". S>Но что именно изменилось? Какое именно поле? S>Вот в лог я и напишу, что у платежного поручения изменилась, например, сумма. S>В моем случае лог ведется не только и не столько для отладки и технической диагностики, но и с целью выявления неких обстоятельств в сфере бизнес-логики.
ну и какие после этого вопросы, куда помещать код логирования?
Das Reich der Freiheit beginnt da, wo die Arbeit aufhört. (c) Karl Marx
Здравствуйте, Nuseraro, Вы писали:
N>Я вот честно говоря не нашел в литературе подтверждение своих наработок, но давно считаю, что трассировка начала и конца функции — это плохая практика. Такое трассирование само по себе мусор, поэтому и код замусоривается.
Гм... Об этом я, честно говоря, не задумывался... Надо посмотреть на проблему с этой стороны. Уже спасибо, за свежую мысль!
N>
N> public bool IsNeedToPayBonus(Context context)
N> {
N> if (context == null)
N> {
N> Warning("Я имел в виду что тут контекст всегда задан");
N> return;
N> }
N> if (context.CurrentOrder == null)
N> {
N> Warning("Я имел в виду что тут у контекста есть ордер");
N> return;
N> }
N> return context.CurrentOrder.Price > 1000;
N> }
N>
А я в таких случаях ArgumentNullException'ы выбрасываю. Потому как "context == null" — в данном случае ИМХО откровенный косяк.
и здесь: N>4) Трассировка конкретных значений, например, при взаимодействии с источниками данных. Короче тех значений, которые потом можно как-то где-то посмотреть N>
как раз и есть тот мусор от которого хотелось бы избавиться!!! (это я про "Trace")
Это как лишние комментарии: из кода и так понятно что там делается! Только код читать мешают.
Но в лог-то вывести надо...
Красота — наивысшая степень целесообразности. (c) И. Ефремов
Здравствуйте, ksg71, Вы писали:
K>ну и какие после этого вопросы, куда помещать код логирования?
Да я вообще от него избавиться хочу, от кода этого!
Или поместить его в такое место, чтобы он был подальше отделен от бизнес-логики и не мешал читать код, относящийся к ней...
Ну ладно... уговорили: я, как обычно, сам не знаю чего хочу!
Красота — наивысшая степень целесообразности. (c) И. Ефремов
Здравствуйте, adontz, Вы писали:
A>Первый вариант не позволит настраивать журналирование по классам.
Не понял, что значит словосочетание "журналирование по классам"... По классам чего? Или по классам каким?
Красота — наивысшая степень целесообразности. (c) И. Ефремов
Здравствуйте, stomsky, Вы писали:
S>Здравствуйте, adontz, Вы писали:
A>>Первый вариант не позволит настраивать журналирование по классам. S>Не понял, что значит словосочетание "журналирование по классам"... По классам чего? Или по классам каким?
По классам которые "class". И log4net, и NLog при правильном использовании позволяют фильтровать сообщения по классам.
Здравствуйте, stomsky, Вы писали:
S>Доброго времени суток! S>Пишу сейчас один сервис, который будет круглосуточно выполнять всякие полезные действия. S>Надо вести подробный лог. S>Сейчас кодирую и вижу как буквально на глазах "полезный" код засоряется кодом логирования. S>Подскажите, плиз, как вы боритесь с этой проблемной?
Имхо, достаточно буквально трёхстрочной "библиотеки", чтобы превратить вашу лапшу в:
УАУ!!! ВОТ ЭТО КРУТО!!!
Я серьезно: каждый раз убеждаюсь, что этот форум — кладезь оригинальных и красивых решений!
Спасибо большое!
Тока скажите честно, ВЫ САМИ такое стали бы использовать???? Нет, это ПРАВДА красиво на мой взгляд! Но, по-моему, какой-то огород на ровном месте... Хотя, я, конечно, сам просил чего-нибудь эдакого в рамках стандартного фреймворка...
Красота — наивысшая степень целесообразности. (c) И. Ефремов
Здравствуйте, stomsky, Вы писали:
s> Доброго времени суток! s> Пишу сейчас один сервис, который будет круглосуточно выполнять всякие полезные действия. s> Надо вести подробный лог. s> Сейчас кодирую и вижу как буквально на глазах "полезный" код засоряется кодом логирования.
... s> Или все-таки на аспекты смотреть? Кто-нибудь этот функционал из BlToolkit пробовал? Я его для доступа к данным использую...
Вообще то вначале нужен ответ на вопрос для чего это мне нужно?
Если нужно просто разобраться с какой то проблемой в реальной работе, то лучше делать индивидуальные логи в тексте которые можно отключать через препроцессор, если важно время. У нас в каждом проекте есть файл с описанием отладочных директив. Можно например трассировать передачу данных и/или прием и/или конвертирование. Спец. трассировка "спрятана" в регионах. Аспектами было бы сложно, так как в данном случае почти каждый метод имеет индивидуальных подход логирования наиболее удобный для поставленной задачи.
Если же нужен просто глобальный обзор одинаковый для многих, то постшапр с аспектами довольно хорошее решение. Буквально недавно только пробовал. Достаточно одной строки в ассебли инфо (ну и аспект), чтобы получить в логе вход, выход, параметры и возможное исключение для всех классов и методов в библиотеке. Мусора конечно полно, но зато бывают видны "интересные вещи".
Здравствуйте, abibok, Вы писали:
a> N>3) Логирование ошибки a> N>
a> N> public bool IsNeedToPayBonus(Context context)
a> N> {
a> N> try
a> N> {
a> N> //...
a> N> }
a> N> catch (Exception e)
a> N> {
a> N> Error(e.Message + e.StackTrace);
a> N> throw;
a> N> }
a> N> }
a> N>
a> Не делайте так. Происходит потеря информации о месте возникновения исходного исключения.
А можно пояснить, что то мысль про место не совсем понятна. И как нужно правильно?