В первую очередь меня интересует LogEntry и принцып ее реализации, а не конкретные имплементации ILogger.
S>Здравствуйте, Константин Ленин, Вы писали:
КЛ>>Здравствуйте, srggal, Вы писали:
S>>>Здравствуйте, Константин Ленин, Вы писали:
S>>>Сюда Re: Я индус?
смотрели ? КЛ>>а вы конец моего сообщения смотрели?
S>Дык в том треде , я вскользь писал про накрутку разных policy, и как пример — упоминал MT policy
Полиси могут накручиваться как на имплементации ILogger, так и на LogEntry. В частности, MT policy это полиси конкретного ILogger, к LogEntry она не должна иметь никакого отношения. Это я к тому, что я говорил выше о приоритетах интересов.
S>Как это будет выглядеть в Вашем случае ?
Об этом я еще не думал. Да и выглядеть должно как "обычно".
S>И насколько это будет удобно ?
Использовать разные полиси? Не знаю. Как видите, точное указание типа логгера(и его стратегий) требует небольшого синтаксического оверхэда.
Че-то мало оценок... Либо в лом читать, либо это уже где-то есть.
"Константин Ленин" <44487@users.rsdn.ru> wrote in message news:1813474@news.rsdn.ru... ><skipped> > Че-то мало оценок... Либо в лом читать, либо это уже где-то есть.
Вечная нехватка времени. Пример достаточно объемистый, а оценивать не разобравшись не хочется.
Posted via RSDN NNTP Server 2.0
--
Не можешь достичь желаемого — пожелай достигнутого.
S>>Дык в том треде , я вскользь писал про накрутку разных policy, и как пример — упоминал MT policy
КЛ>Полиси могут накручиваться как на имплементации ILogger, так и на LogEntry. В частности, MT policy это полиси конкретного ILogger, к LogEntry она не должна иметь никакого отношения. Это я к тому, что я говорил выше о приоритетах интересов.
Здравствуйте, srggal, Вы писали:
S>Здравствуйте, Константин Ленин, Вы писали:
S>>>Дык в том треде , я вскользь писал про накрутку разных policy, и как пример — упоминал MT policy
КЛ>>Полиси могут накручиваться как на имплементации ILogger, так и на LogEntry. В частности, MT policy это полиси конкретного ILogger, к LogEntry она не должна иметь никакого отношения. Это я к тому, что я говорил выше о приоритетах интересов.
S>Отчасти Вы правы, но это комбинаторный взрыв.
Ну шаблонные классы с несколькими параметрами тоже комбинаторный взрыв. Ну кто-нить хоть код посмотрит?
Здравствуйте, Константин Ленин, Вы писали:
КЛ>Решил тут логгинг переделать.Старый был неудобен и основывался на макросах.
КЛ>Кое-что получилось . Хочу послушать мнения по поводу пригодности.
КЛ>Набросал за час, так что пинать не сильно КЛ>Из достоинств — неограниченное добавление записей в строку, можно прикрутить манипуляторы. КЛ>Идея взята здесь
Я кстати в той теме всё-же остановился на макросах.
Плюс: позволяет автоматически залоггировать прототип функции из которой был произведен логгинг. А так-же файл, номер строки и т.д.и т.п
Здравствуйте, Константин Ленин, Вы писали:
КЛ>Решил тут логгинг переделать.Старый был неудобен и основывался на макросах.
КЛ>Кое-что получилось . Хочу послушать мнения по поводу пригодности.
По поводу потокового синтаксиса — согласен полностью.
В конце каждого вывода хотелось бы видеть автоматическое добавление перевода строки. По крайней мере я привык к такой фиче — не жаловался ни разу.
Пользовательский код, который логирует, абсолютно не должен знать о логгерах, и уж точно не должен выбирать тип конкретного логгера. Это можно делать только централизованно на уровне приложения. Имхо.
Учитывая, что HRESULT — это unsigned int, пользователя могут ждать приключения.
Выход — завести обёртку
struct HResult
{
HRESULT hr;
explicit HResult(HRESULT h) : hr(h) {}
String verbose() const;
// За словесными описаниями можно слазить в ::FormatMessage(),
// а чтобы не делать это слишком часто - используй кэш
// И не забывай, что есть коды не только ошибок, но и удач - S_OK, S_FALSE и другие, которые SUCCEEDED(hr)
};
и уже написать перегрузку operator<< для этого типа.
Кстати говоря, лучше, чтобы перегрузки были для чего-то одного: либо operator<<, либо AppendRecord.
И ещё кстати, если operator<< перегружен — то сделать его свободной функцией, чтобы пользователи могли добавлять свои сигнатуры.
А может быть, неплохо разделить все три составляющих:
— синтаксический сахар (operator <<)
— перевод типа в строку (скажем, функция String verbose(T) — перегруженная по-всякому или шаблонная)
— добавление строки в лог (метод LogEntry.AppendRecord(String))
Тогда оператор будет выглядеть вот так:
Спасибо за ссылку, но что-то типа этого у меня и было. Хотелось избавиться от вызова именно методов с фиксированным кол-ом параметров, и, следовательно, с конкатенацией строк.
Я привел пару операторов << только в качестве примера и они не претендуют на завершенность.
За HRESULT спасибо, я пока не концентрировался на конкретных типах.
Здравствуйте, remark, Вы писали:
R>Здравствуйте, Константин Ленин, Вы писали:
КЛ>>Решил тут логгинг переделать.Старый был неудобен и основывался на макросах.
КЛ>>Кое-что получилось . Хочу послушать мнения по поводу пригодности.
R>По поводу потокового синтаксиса — согласен полностью.
R>В конце каждого вывода хотелось бы видеть автоматическое добавление перевода строки. По крайней мере я привык к такой фиче — не жаловался ни разу.
Это может делать как LogEntry, так и конкретный ILogger::WriteEntry
R>Не согласен по поводу:
R>Не понятно как расширять логирование для пользовательских типов?
Я об этом пока не сильно думал
R>Зачем в LogEntry секция protected? И зачем в нём динамическое создание pBuffer_?
хз)
Маленькая оптимизация. Вместо копирования содержимого строки в LogEntry::LogEntry( LogEntry& ) я копирую только указатель. Если ты заметил, на каждый вызов LogEntry::operator<< создается новый объект LogEntry. Т.е на
LogWarning<<_T("")<<_T("");
мы получаем 5 временных объектов LogEntry и 4 вызова LogEntry::LogEntry( LogEntry& ) с 4мя копированиями строки. ИМХО копирование указателя на строку лучше чем копирование строки.
R>Пользовательский код, который логирует, абсолютно не должен знать о логгерах, и уж точно не должен выбирать тип конкретного логгера. Это можно делать только централизованно на уровне приложения. Имхо.
ИМХО, не всегда. Иногда требуется что-то записать в EventLog, когда в обычных случаях пишем в файл, например.
R>>Пользовательский код, который логирует, абсолютно не должен знать о логгерах, и уж точно не должен выбирать тип конкретного логгера. Это можно делать только централизованно на уровне приложения. Имхо.
КЛ>ИМХО, не всегда. Иногда требуется что-то записать в EventLog, когда в обычных случаях пишем в файл, например.
Нет, так у тебя ничего не получиться.
Тогда такой вид вывода в лог должен быть выделен в отдельную перпендикулярное множество абстракций.
Т.е. надо сделать некое множество {CommonLog, UserEventLog, ...}.
Весь код пишет некий CommonLog, а некоторые записи идут в UserEventLog. Но при этом приложение всё равно должно централизовано управлять, что CommonLog сейчас идёт в файл, а UserEventLog сейчас идёт в EventLog Windows или он может идти в тот же файл, что и CommonLog, если другово не требуется.
При этом всегда можно в одном месте настроить, что CommonLog мы например хотим изменить с консоли в файл, т.к. приложение перестало быть консольным. А UserEventLog теперь надо поменять на что-то другое, т.к. приложение стало работать не под Windows.
Если же ты будешь по всему коду упоминать имена конкретных логгеров, то тем самым ты "убьёшь" код.
А в некоторых ситуациях это будет просто невозможно. Ты сейчас думаешь только о коде проекта. Представь такую ситуацию. У тебя есть один проект, который пишет лог в файл. И второй, который пишет лог на консоль. Тебе надо написать некий общий код, который ты хочешь использовать в обеих проектах. Куда ты будешь выводить лог? В FileLog? В ConsoleLog? Единственный возможный вариант в CommonLog! А каждый проект уже сам разберётся куда конкретно это вывести.
__>>http://logging.apache.org/log4cxx/
КЛ>Спасибо за ссылку, но что-то типа этого у меня и было. Хотелось избавиться от вызова именно методов с фиксированным кол-ом параметров, и, следовательно, с конкатенацией строк.
В log4cxx вывод идёт через std::strstream — никаких методов с фиксированным кол-вом параметров.