Свежая версия R.SAT — http://files.rsdn.ru/5161/R.SAT-r166.7z
Основные изменения — поддержка Моно, убрана зависимость от FW 3.5, добавлена механика хранения служебных данных на диске.
... << RSDN@Home 1.2.0 alpha 2 rev. 837 on Windows Vista 6.0.6001.65536>>
У меня нет времени им заниматься, так что пока выложил то что есть ввиде архива с исходниками — http://files.rsdn.ru/5161/R.Server.7z (2.3М). Вкратце — сервер построен на платформе .NET + WCF в качестве коммуникационного слоя. Проектировался в расчете на максимальную расширяемость. На данным момент реализован базовый слой, подсистема конфигурации, базовый механизм для подключения и использования сетевых сервисов, аутентификация (поддерживается аутентификация по конфигу, по пользователям Windows, по собственной БД и анонимный доступ), фреймворк для авторизации и авторизация по конфигу и по БД, проверка прав при обращении к сетевым сервисам, логирование, механизм серверных задач, и, в основном в качестве примера, шедулер.
Предполагается использование сервера примерно в такой инфраструктуре (правда картинка основательно устарела):
Кому лень качать весь архив — отдельно документация на некоторые подсистемы: Аутентификация Авторизация Сетевые сервисы Логирование Серверные задачи
... << RSDN@Home 1.2.0 alpha rev. 725 on Windows Vista 6.0.6000.0>>
Здравствуйте, AndrewVK, Вы писали:
AVK>Авторизация
Возможность нескольких провайдеров — безусловно важная и нужная опция которой часто востребована. Еще часто востребована опция — проверка прав на бизнес-объекты. Сделать какой-нибудь декларатив например, для генерации LINQ запросов — было-бы интересно.
Здравствуйте, GlebZ, Вы писали:
GZ>Сделать какой-нибудь декларатив например, для генерации LINQ запросов — было-бы интересно.
Это пока только в планах — задачка, мягко говоря, не маленькая и однозначного решения не имеет. Пока что там есть кое какие зачатки, которые мы с IB придумали, которые позволяют, основываясь на контекстах, получать политику проверки прав. Собственно, поверх этой механики сейчас работает проверка прав при сетевом доступе (см. исходник в конце). Но на этом все заканчивается, никакой конкретики применительно к проверке прав по бизхнес-объектам пока нет. Да и непонятно как оно должно работать универсально — универсально эта задачка с приемлемой производительностью не решается. А неуниверсально — максимум, что можно сделать, это предоставить некий набор базового инструментария для ряда типовых моментов, не более того.
private bool CheckCommAccess(string serviceName, Type serviceType, string methodName,
IRServerPrincipal principal)
{
if (_commPolicies.Length > 0)
{
var ctx = new CommPolicyContext(serviceName, serviceType, methodName);
foreach (var policy in _commPolicies)
if (!_policyMgr.IsPermitted(_serviceManager, principal, ctx, policy))
return false;
}
return true;
}
Код перебирает все указанные в конфиге политики и спрашивает у каждой из них (посредством PolicyManager) — разрешен ли для данного экземпляра контекста доступ. Если хотя бы одна политика выдаст отказ — доступ не разрешен.
Примерно то же самое должно быть и для доступа к бизнес-объектам, только дополнительно,в случае запроса списка до выполнения запроса, во-первых нужно производить контроль дерева запроса (и если там есть явное обращение к запрещенным типам — сразу выдавать отказ до обращения к БД) и дописывать к запросу фильтр. Но как конкретно это должно выглядеть в коде — отдельный большой вопрос.
... << RSDN@Home 1.2.0 alpha rev. 725 on Windows Vista 6.0.6000.0>>
Здравствуйте, AndrewVK, Вы писали:
AVK>Примерно то же самое должно быть и для доступа к бизнес-объектам, только дополнительно,в случае запроса списка до выполнения запроса, во-первых нужно производить контроль дерева запроса (и если там есть явное обращение к запрещенным типам — сразу выдавать отказ до обращения к БД) и дописывать к запросу фильтр. Но как конкретно это должно выглядеть в коде — отдельный большой вопрос.
Посмотрите как сделан Acegi Security для Spring'а. Там есть понятие "голосовальщиков" — они могут выдать "Allow"/"Disallow" и "Ignore". К голосовальщикам добавляются политики: "пускать если хоть один разрешит", "пускать, если никто не запретит" и т.д.
Для запроса это вряд ли подойдет — очень часто нужно фильтровать результаты запроса. Тут ничего универсального нет
Здравствуйте, AndrewVK, Вы писали:
AVK>Логирование
В стандартном логгере — мне не хватает.
1. Управления в рантайм. Нужно иметь возможность переключать некоторые switch в процессе выполнения, чтобы прослеживать определенные функции которые сбоят. И это должно быть просто, чтобы выполнял администратор плохо владеющий системой.
2. В файловом логгере — необходимо иметь систему переключения файлов. Ну например как в логере IIS. Каждый день начинается новый лог файл. Чтобы не было одного 10 гигобайтного файла о котором вспомнили когда стало не хватать пространства, и к тому же для его убийства нужно останавливать систему.
3. Не хватает масштабируемости. Но тут вопрос не только в отдельном треде. Вопрос в размерах буфера от количества информации помещаемой в лог. Например, если раз в 1 секунду помещается более 100 записей — то буфер увеличиваем. Если менее, то уменьшаем вплоть до одной записи. Иначе логирование берет на себя много ресурсов.
4. Разность свитчей по типу листенера. Например, в mail загоняем только ошибки. В текст как ошибки так и само логгирование.
5. Неработаспособность логирования не должно отражаться на работоспособность системы. Неработоспособность mail сервера не должно никоим образом посылать exception во внешний мир, но должно отражаться в других логах.
Здравствуйте, Cyberax, Вы писали:
C>Посмотрите как сделан Acegi Security для Spring'а.
Да я уж всяких решений пересмотрел столько... Этот, кажется, тоже смотрел.
C> Там есть понятие "голосовальщиков" — они могут выдать "Allow"/"Disallow" и "Ignore". К голосовальщикам добавляются политики: "пускать если хоть один разрешит", "пускать, если никто не запретит" и т.д.
Это что то дает? Просто, на практике, правило "все политики должны разрешать" работает вполне приемлемо и нужды в чем то более сложном ен возникало.
C>Для запроса это вряд ли подойдет — очень часто нужно фильтровать результаты запроса. Тут ничего универсального нет
О том и речь.
... << RSDN@Home 1.2.0 alpha rev. 725 on Windows Vista 6.0.6000.0>>
Здравствуйте, GlebZ, Вы писали:
GZ>1. Управления в рантайм. Нужно иметь возможность переключать некоторые switch в процессе выполнения, чтобы прослеживать определенные функции которые сбоят. И это должно быть просто, чтобы выполнял администратор плохо владеющий системой.
Можно поподробнее?
GZ>2. В файловом логгере — необходимо иметь систему переключения файлов. Ну например как в логере IIS. Каждый день начинается новый лог файл. Чтобы не было одного 10 гигобайтного файла о котором вспомнили когда стало не хватать пространства, и к тому же для его убийства нужно останавливать систему.
Это как раз задачка для желающих. Ничего хитрого в ней нет, просто нужно сесть и сделать.
GZ>3. Не хватает масштабируемости. Но тут вопрос не только в отдельном треде. Вопрос в размерах буфера от количества информации помещаемой в лог. Например, если раз в 1 секунду помещается более 100 записей — то буфер увеличиваем. Если менее, то уменьшаем вплоть до одной записи. Иначе логирование берет на себя много ресурсов.
Я не планировал делать тяжелый логгинг, это задача для специализированных логгеров, рассчитаных на высокую нагрузку.
GZ>4. Разность свитчей по типу листенера. Например, в mail загоняем только ошибки. В текст как ошибки так и само логгирование.
Это в планах.
GZ>5. Неработаспособность логирования не должно отражаться на работоспособность системы. Неработоспособность mail сервера не должно никоим образом посылать exception во внешний мир, но должно отражаться в других логах.
Так там вроде как раз специальный механизм есть выкидывания сбоящих логов. Или нужно какой то более хитрый алгоритм?
... << RSDN@Home 1.2.0 alpha rev. 725 on Windows Vista 6.0.6000.0>>
Здравствуйте, AndrewVK, Вы писали:
C>> Там есть понятие "голосовальщиков" — они могут выдать "Allow"/"Disallow" и "Ignore". К голосовальщикам добавляются политики: "пускать если хоть один разрешит", "пускать, если никто не запретит" и т.д. AVK>Это что то дает? Просто, на практике, правило "все политики должны разрешать" работает вполне приемлемо и нужды в чем то более сложном ен возникало.
Например, может быть "requisite"-политика. То есть, пользователя можно пускать, если у него правильный SSL-ключ, даже если у него не указан пароль.
Или еще стандартный вариант: из локальной сети пускать в любом случае, а из внешней — требовать безопасный протокол.
Здравствуйте, Cyberax, Вы писали:
C>Например, может быть "requisite"-политика. То есть, пользователя можно пускать, если у него правильный SSL-ключ, даже если у него не указан пароль. C>Или еще стандартный вариант: из локальной сети пускать в любом случае, а из внешней — требовать безопасный протокол.
Ну, если вдруг кого то заинтересует, то можно подумать в этом направлении. Пока там все в зачаточном состоянии.
... << RSDN@Home 1.2.0 alpha rev. 725 on Windows Vista 6.0.6000.0>>
Здравствуйте, AndrewVK, Вы писали:
AVK>Можно поподробнее?
Ну например. Начал сбоить модуль импорта. Для того чтобы понять в чем дело, запрашиваем у администратора — изменить switch для подробного логирования подсистемы импорта. При изменении — сама система полностью работоспособна. При Net 1.1 — под логгирование у меня был отдельный конфигурационный файл, чтобы не перегружался ASP.NET(когда он выполнялся в контексте ASP.NET). Сейчас — я особенно не вникал в управление конфигами, вроде есть рычаг для поднятия новых параметров на лету. Второй способ — безусловно опубликование управления системы логгирования, и управление внешней утилитой. Мне было важно — что система 24/7, и остановку/перегрузку надо предотвращать любыми способами.
GZ>>3. Не хватает масштабируемости. Но тут вопрос не только в отдельном треде. Вопрос в размерах буфера от количества информации помещаемой в лог. Например, если раз в 1 секунду помещается более 100 записей — то буфер увеличиваем. Если менее, то уменьшаем вплоть до одной записи. Иначе логирование берет на себя много ресурсов. AVK>Я не планировал делать тяжелый логгинг, это задача для специализированных логгеров, рассчитаных на высокую нагрузку.
Ничего сложного в этом нет. Просто когда передаешь в поток — делаешь это через очередь. И сбрасываешь не постоянно работающим потоком, а по таймеру. Если очередь пуста — уменьшаешь ее. Если большая — удлиняешь. Если пришла ошибка — то сбрасываешь очередь в лог независимо от таймера и в своем потоке.
В принципе у меня где-то есть такой личнописанный логгер без лицензии. В архивах у себя посмотрю, может адаптировать можно будет.
GZ>>5. Неработаспособность логирования не должно отражаться на работоспособность системы. Неработоспособность mail сервера не должно никоим образом посылать exception во внешний мир, но должно отражаться в других логах. AVK>Так там вроде как раз специальный механизм есть выкидывания сбоящих логов. Или нужно какой то более хитрый алгоритм?
Честно говоря сам не знаю.
Здравствуйте, Cyberax, Вы писали:
C>Посмотрите как сделан Acegi Security для Spring'а. Там есть понятие "голосовальщиков" — они могут выдать "Allow"/"Disallow" и "Ignore". К голосовальщикам добавляются политики: "пускать если хоть один разрешит", "пускать, если никто не запретит" и т.д.
+1
C>Для запроса это вряд ли подойдет — очень часто нужно фильтровать результаты запроса. Тут ничего универсального нет
Ну в рамках линки невозможного стало меньше. Вопрос в том, что для постоения наиболее обобщенного придется сильно пошевелить мозгами. Всех конечно не удовлетворит (как впрочем и теперешняя ролевая без-сть), но многим поможет. Неприятная вещь секьюрити.
Здравствуйте, GlebZ, Вы писали:
AVK>>Можно поподробнее? GZ>Ну например. Начал сбоить модуль импорта. Для того чтобы понять в чем дело, запрашиваем у администратора — изменить switch для подробного логирования подсистемы импорта. При изменении — сама система полностью работоспособна.
Тут одно из двух — либо это фича самого модуля (не каждый модуль умеет такое), либо это просто вопрос настройки фильтра лога (которого пока нет) на предмет соотношения источника и приоритета.
GZ> При Net 1.1 — под логгирование у меня был отдельный конфигурационный файл, чтобы не перегружался ASP.NET(когда он выполнялся в контексте ASP.NET). Сейчас — я особенно не вникал в управление конфигами, вроде есть рычаг для поднятия новых параметров на лету. Второй способ — безусловно опубликование управления системы логгирования, и управление внешней утилитой. Мне было важно — что система 24/7, и остановку/перегрузку надо предотвращать любыми способами.
Опять же — я предполагал все же несколько иные условия применения. Архитектура высоконагруженных систем, где перегрузка карается расстрелом, это отдельный большой вопрос, для которого нужны отдельные решения.
AVK>>Я не планировал делать тяжелый логгинг, это задача для специализированных логгеров, рассчитаных на высокую нагрузку. GZ>Ничего сложного в этом нет. Просто когда передаешь в поток — делаешь это через очередь.
Оно там и так через очередь.
GZ> И сбрасываешь не постоянно работающим потоком, а по таймеру.
А что это даст кроме того, что увеличатся задержки сброса? Throttling при перегрузке там и так можно приделать, без таймера, в том числе и с учетом приоритета. Просто, скажем, лимитируем размер очереди, и, если он на очередной итерации превышен, то начинаем выкидывать низкоприоритетные сообщения до тех пор пока очередь не придет в норму. Если у нас есть логи с разным временем отклика, то тут нужно уже вводить несколько потоков для сброса, в которых обрабатываются логи с примерно одинаковым временем записи. С другой стороны, если специфичные тормозные логи реализуют свою собственную очередь, это будет эффективнее, потому что при этом можно учесть намного больше специфики (например, очередь мейлера лучше вообще в БД писать, а не в памяти держать).
GZ>В принципе у меня где-то есть такой личнописанный логгер без лицензии. В архивах у себя посмотрю, может адаптировать можно будет.
Это запросто, при условии что не ухудшатся хактеристики при низкой нагрузке.
AVK>>Так там вроде как раз специальный механизм есть выкидывания сбоящих логов. Или нужно какой то более хитрый алгоритм? GZ>Честно говоря сам не знаю.
Вот и я тоже не знаю, поэтому реализовал пока самый примитивный вариант — выкидывание лога при первом сбое с записью об этом во всех остальных.
P.S. Кстати, а как ты представляешь себе описание фильтра лога? Простого логического выражения со всеми свойствами события будет достаточно? Или нужно что то еще?
... << RSDN@Home 1.2.0 alpha rev. 725 on Windows Vista 6.0.6000.0>>
Здравствуйте, AndrewVK, Вы писали:
AVK>Опять же — я предполагал все же несколько иные условия применения. Архитектура высоконагруженных систем, где перегрузка карается расстрелом, это отдельный большой вопрос, для которого нужны отдельные решения.
А тут вопрос даже не в чистой 24/7. По любому для админа процесс перегрузки заключается в том, что он раззванивает по возможности всем кто сидит в системе чтобы вышли, и только после этого перегружает. Процедура очень неудобная. И нужны веские основания чтобы заставлять их делать перегрузку.
AVK>А что это даст кроме того, что увеличатся задержки сброса? Throttling при перегрузке там и так можно приделать, без таймера, в том числе и с учетом приоритета. Просто, скажем, лимитируем размер очереди, и, если он на очередной итерации превышен, то начинаем выкидывать низкоприоритетные сообщения до тех пор пока очередь не придет в норму.
Нет. Выбрасывать с файловых логов ничего нельзя. И приоритетность в принципе не нужна и даже вредна(если я правильно понял что ты имел ввиду под приоритетностью). При обнаружении ошибки, лог переключается администратором в режим наиболее полной информации. В этом случае мы имеем нехилую нагрузку на лог. Но в замен мы получаем точный порядок выполнения того или иного действия в момент ошибки. И в том числе параллельных задач. То есть, тут нельзя ни менять порядок, ни сжирать сообщения. Иначе мы не достигаем конечной цели — получение максимум информации о возникшей в процессе эксплуатации ошибке.
AVK>Если у нас есть логи с разным временем отклика, то тут нужно уже вводить несколько потоков для сброса, в которых обрабатываются логи с примерно одинаковым временем записи. С другой стороны, если специфичные тормозные логи реализуют свою собственную очередь, это будет эффективнее, потому что при этом можно учесть намного больше специфики (например, очередь мейлера лучше вообще в БД писать, а не в памяти держать).
В случае же mail или event — нам более важен факт ошибки. И в случае если очередь заполнена, то учитывая что некоторые ошибки мы уже отправили, я думаю не криминально если мы вообще на некоторое время отрубим генерацию сообщений и очередь. Здесь более важно именно наличие ошибки а не из количество.
AVK>Вот и я тоже не знаю, поэтому реализовал пока самый примитивный вариант — выкидывание лога при первом сбое с записью об этом во всех остальных.
+1
AVK>P.S. Кстати, а как ты представляешь себе описание фильтра лога? Простого логического выражения со всеми свойствами события будет достаточно? Или нужно что то еще?
Немного не понял что такое фильтр лога с лог. выражением. В принципе у логов есть три цели:
1. Информация о текущей работе
2. Нотификация о ошибке
3. Информация о ошибке с максимальным кол-вом информации о выполнении.
Фактически, в TraceLevel — дана достаточно хорошая квалификация информации(по крайней мере для меня).
В случае если система находится в рабочем режиме, включена логгирование информационных сообщений, ошибок. В случае если система находится в режиме поиска ошибок — дополнительно verbose.
Еще нужна параллельная классификация. То есть, если мы хотим проверить сервис импорта, то мы можем включить поставить флаг import. Но это может быть и не только сервисно-зависимые флаги. Типа, если ставишь флаг DAL — то в лог кладуться все запросы к БД с параметрами от всех сервисов которые работают с БД.
Классификация стандартного лога мне значительно больше нравится чем например log4net. Если бы не вышеперечисленные замечания. Фильтр по тексту как в log4net — вещь ненужная и ненадежная. Лучше по текстовым флагам+обозначение TraceLevel.
Здравствуйте, GlebZ, Вы писали:
GZ>Нет. Выбрасывать с файловых логов ничего нельзя.
А куда деваться, если диск не справляется?
GZ> И приоритетность в принципе не нужна и даже вредна(если я правильно понял что ты имел ввиду под приоритетностью).
Под приоритетностью имеется ввиду приоритетность конкретного события, которое явно указывается при его создании.
GZ> При обнаружении ошибки, лог переключается администратором в режим наиболее полной информации. В этом случае мы имеем нехилую нагрузку на лог. Но в замен мы получаем точный порядок выполнения того или иного действия в момент ошибки. И в том числе параллельных задач. То есть, тут нельзя ни менять порядок, ни сжирать сообщения. GZ>Иначе мы не достигаем конечной цели — получение максимум информации о возникшей в процессе эксплуатации ошибке.
Вобще то нормальное функционирование системы значительно важнее записи в лог какой нибудь трассировочной информации.
AVK>>P.S. Кстати, а как ты представляешь себе описание фильтра лога? Простого логического выражения со всеми свойствами события будет достаточно? Или нужно что то еще? GZ>Немного не понял что такое фильтр лога с лог. выражением.
Это способ реализации твоих 1 и 5 пунктов. В конфиге, при описании лога, задается выражение, которое описывает какую информацию следует в этот лог помещать.
GZ>Фактически, в TraceLevel — дана достаточно хорошая квалификация информации(по крайней мере для меня).
Ты сам себе противоречишь. В предыдущем письме ты утверждал, что тебе важно, скажем, получить временно информацию об отдельном модуле более подробно. Ожним level такого не добиться, нужна фильтрация по источнику информации.
GZ>Классификация стандартного лога мне значительно больше нравится чем например log4net. Если бы не вышеперечисленные замечания. Фильтр по тексту как в log4net — вещь ненужная и ненадежная. Лучше по текстовым флагам+обозначение TraceLevel.
Это все понятно. Вопрос в том как это долно выглядеть в конфиге.
... << RSDN@Home 1.2.0 alpha rev. 725 on Windows Vista 6.0.6000.0>>
Здравствуйте, AndrewVK, Вы писали:
GZ>>Нет. Выбрасывать с файловых логов ничего нельзя. AVK>А куда деваться, если диск не справляется?
Чтобы диск не справлялся по производительности в условиях буферизации — это нужно очень постараться. Если максимум буфера превышен — до свиданья логгер, как неоправдавший надежд на детерменированное выживание в столь сложных условиях. Но это касается только информационных мессаг. Какой прок от информации если мы ей не можем доверять. Мессаги же об ошибке должны писаться синхронно. Они должны явно сбрасывать очередь информации и записываться. Они важны для функционирования самого сервера.
В одном логгере я делал категорию мессаг — FATAL для ошибок загрузки сервисов. Только он сбрасывал синхронно. Но потом пришлось сделать синхронными все error, так как бывали ситуации что происходило зависание и ошибки оставались в буфере.
GZ>> И приоритетность в принципе не нужна и даже вредна(если я правильно понял что ты имел ввиду под приоритетностью). AVK>Под приоритетностью имеется ввиду приоритетность конкретного события, которое явно указывается при его создании.
Если в данном случае имеется ввиду просто информационное поле по которому можно квалифицировать — то почему бы и нет. А вот если оно влияет на порядок записи, то безусловно нет.
AVK>Вобще то нормальное функционирование системы значительно важнее записи в лог какой нибудь трассировочной информации.
Трассировки — да. Но вот ошибки — нет. Какой прок от системы которая делает нелокализуемые ошибки.
GZ>>Фактически, в TraceLevel — дана достаточно хорошая квалификация информации(по крайней мере для меня). AVK>Ты сам себе противоречишь. В предыдущем письме ты утверждал, что тебе важно, скажем, получить временно информацию об отдельном модуле более подробно. Ожним level такого не добиться, нужна фильтрация по источнику информации.
Безусловно, я имел ввиду TraceLevel + флаги в комплексе. Флаги — квалификация ошибок в том числе и по модулям.
GZ>>Классификация стандартного лога мне значительно больше нравится чем например log4net. Если бы не вышеперечисленные замечания. Фильтр по тексту как в log4net — вещь ненужная и ненадежная. Лучше по текстовым флагам+обозначение TraceLevel. AVK>Это все понятно. Вопрос в том как это долно выглядеть в конфиге.
Что-то типа:
Здравствуйте, GlebZ, Вы писали:
GZ>>>Нет. Выбрасывать с файловых логов ничего нельзя. AVK>>А куда деваться, если диск не справляется? GZ>Чтобы диск не справлялся по производительности в условиях буферизации — это нужно очень постараться.
Тогда чего ты тога боишься? Что не справится с нагрузкой диспетчер? по сравнению со временем работы диспетчера время обращения к диску это вечность. Или что не справится какой то специфичный логгер? Так это сфера ответственности этого логгера, а не диспетчера.
GZ>Мессаги же об ошибке должны писаться синхронно.
Зачем?
GZ> Они должны явно сбрасывать очередь информации и записываться. Они важны для функционирования самого сервера.
Для функционирования сервера они не имеют никакого значения? Они имеют значение только для пользователя. А ему пофигу та микрозадержка, которая получится из-за немгновенной отработки диспетчера. Главное — последовательность обеспечить. А вот если из-за тормозов диска при сбросе лога у нас тормозится основной код, это никуда не годится.
GZ>так как бывали ситуации что происходило зависание и ошибки оставались в буфере.
Как может зависнуть поток сброса на диск при ошибках в прикладном коде?
AVK>>Под приоритетностью имеется ввиду приоритетность конкретного события, которое явно указывается при его создании. GZ>Если в данном случае имеется ввиду просто информационное поле по которому можно квалифицировать
Именно
GZ>А вот если оно влияет на порядок записи, то безусловно нет.
Нет, на порядок не влияет. Просто удобно троттлинг делать не тупой, а с учетом значения этого поля, наименее приоритетные события глушить первыми.
AVK>>Вобще то нормальное функционирование системы значительно важнее записи в лог какой нибудь трассировочной информации. GZ>Трассировки — да. Но вот ошибки — нет.
Ну значит при троттлинге события с уровнем важности выше некоторого никогда не удаляются. Это все детали. Обычно просто, если уж логи начали захлебываться от критических ошибок, то дальше детально что то фиксировать смысла уже нет никакого — полный приплызд, система просто не способна выполнять свои функции. А так, чтобы надо было бороться за скорость записи критических ошибок в лог — это, ИМХО, какая то весьма экзотическая ситуация.
AVK>>Ты сам себе противоречишь. В предыдущем письме ты утверждал, что тебе важно, скажем, получить временно информацию об отдельном модуле более подробно. Ожним level такого не добиться, нужна фильтрация по источнику информации. GZ>Безусловно, я имел ввиду TraceLevel + флаги в комплексе. Флаги — квалификация ошибок в том числе и по модулям.
Вот. А теперь встает вопрос — как описать правила анализа level и флагов.
AVK>>Это все понятно. Вопрос в том как это долно выглядеть в конфиге. GZ>Что-то типа:
GZ>
Здравствуйте, AndrewVK, Вы писали:
AVK>Тогда чего ты тога боишься? Что не справится с нагрузкой диспетчер? по сравнению со временем работы диспетчера время обращения к диску это вечность. Или что не справится какой то специфичный логгер? Так это сфера ответственности этого логгера, а не диспетчера.
Сфера у нас одна. Обеспечить цели средствами. Фактически цели с которые мне нужно было достичь — я опубликовал.
Немного не понял что такое фильтр лога с лог. выражением. В принципе у логов есть три цели:
1. Информация о текущей работе
2. Нотификация о ошибке
3. Информация о ошибке с максимальным кол-вом информации о выполнении.
Это не есть истина в последней инстанции, поскольку тут я руководсвуюсь только своим опытом, и сфера деятельности моя достаточно узка(делопроизводство/документооборот). Вполне возможно существуют и другие цели которые следовало бы достичь с помощью логгера. Пользователем информации логгера являются администраторы сервера, служба сопровождения, и конечно мы, бренные разработчики. Аудит предназначенный для пользователя(по крайней мере в моем отсеке) несколько другой и повязан на бизнес-логику. То есть, я пока могу квалифицированно говорить именно о системном аудите.
GZ>>Мессаги же об ошибке должны писаться синхронно. AVK>Зачем?
Сейчас у нас у одного клиента зависает сервер. Причем напрочь. Берет на себя 100 процентов ресурсов сервера, и перестает подавать признаки жизни. Но поскольку там используется стандартный синхронный логгер, я могу точно утверждать что никакой exception при этом не вываливается. Поскольку ошибка возникает недетерменированно и очень редко, на нее пока забили. Включать полный лог, который генерит мегабайты информации при стандартном логгере нельзя, поскольку начинает тормозить основная функциональность пользователей. Пока не сильно бьют, не трогаем. Будут бить подключим нормальный производительный трейсер, и будем решать проблему.
AVK>Для функционирования сервера они не имеют никакого значения? Они имеют значение только для пользователя.
Мое IMHO кто есть пользователь, выше. А упущенная ошибка — это хуже некуда. Ошибка которая не отображается в логе, но выражается в постоянных звонках пользователей — неприятна многим.
AVK>А ему пофигу та микрозадержка, которая получится из-за немгновенной отработки диспетчера. Главное — последовательность обеспечить. А вот если из-за тормозов диска при сбросе лога у нас тормозится основной код, это никуда не годится.
В том то и дело, что если мы сбрасываем не по одной мессаге, а сразу скопом, то скорость увеличивается на порядок. Я прогонял трейсер на нагрузку, действительно увеличивается на порядок. Каждое обращение к диску — латентно. Особенно если ты каждый раз открываешь файл.
GZ>>так как бывали ситуации что происходило зависание и ошибки оставались в буфере. AVK>Как может зависнуть поток сброса на диск при ошибках в прикладном коде?
ХЗ. Но факт пока остается фактом(см. выше).
GZ>>А вот если оно влияет на порядок записи, то безусловно нет. AVK>Нет, на порядок не влияет. Просто удобно троттлинг делать не тупой, а с учетом значения этого поля, наименее приоритетные события глушить первыми.
Если мы достигли максимума очереди, то если это происходит часто, то лучше перенастроить увеличить размер очереди. Если не часто, то почему бы не пожертвовать одним рабочим потоком. Сброс мегабайта информации на диск — сейчас не настолько дорог. Но при этом качеством информации не жертвовать.
AVK>Обычно просто, если уж логи начали захлебываться от критических ошибок, то дальше детально что то фиксировать смысла уже нет никакого — полный приплызд, система просто не способна выполнять свои функции.
+1 AVK>А так, чтобы надо было бороться за скорость записи критических ошибок в лог — это, ИМХО, какая то весьма экзотическая ситуация.
Детерменированность записи ошибки. Я посмотрел твой код, ты сделал очередь которая сбрасывает по одной ошибке. То есть в твоем коде — это не настолько важно, поскольку вероятность того что при записи в файл будут фатальные проблемы убивающие всю систему — достаточно мало. В моем файловом логгере — сообщения буфферизуются. Это увеличивает пропускную способность при трассировке, но существует вероятность что наиболее важная информация, а именно ошибки, не успеют сохраниться до краха/остановки в файл существуют. Поэтому жертвуется производительность текущего потока создавшего ошибку. Что IMHO не является криминальным. Например, если произошла ошибка загрузки модулей, что есть фатал, информация об ошибке будет точно сохранена. Твоя система сохранения ошибок очень подходит к mail серверу, но моя эффективней себя ведет с файлами.
AVK>>>Это все понятно. Вопрос в том как это долно выглядеть в конфиге. GZ>>Что-то типа:
[skipped]
AVK>Ужос, честно говоря. Слишком сложно.
А ты что предлагаешь?
Здравствуйте, GlebZ, Вы писали:
GZ>Это не есть истина в последней инстанции, поскольку тут я руководсвуюсь только своим опытом, и сфера деятельности моя достаточно
Очевидно, что акценты в немалой степени пределяются опытом. На аднный момент мне не очень интересна архитектура сильно масштабируемых систем под большие нагрузки. Соотв. и сервер создавался прежде всего под задачи большой сложности, но относительно невысокой нагрузки.
GZ> узка(делопроизводство/документооборот). Вполне возможно существуют и другие цели которые следовало бы достичь с помощью логгера. Пользователем информации логгера являются администраторы сервера, служба сопровождения, и конечно мы, бренные разработчики. Аудит предназначенный для пользователя(по крайней мере в моем отсеке) несколько другой и повязан на бизнес-логику. То есть, я пока могу квалифицированно говорить именно о системном аудите.
Тут понимаешь какое дело. С одной стороны хочется конечно что то такое придумать более менее универсальное. Но с доугой стороны те же высокопроизводительные решения ломают или усложняют архитектуру в угоду максимальной эффективности. Ну а дальше начинается баланс приоритетов.
GZ>В том то и дело, что если мы сбрасываем не по одной мессаге, а сразу скопом, то скорость увеличивается на порядок.
А если мы сбрасываем скопом, то получаем те же яйца, вид в профиль. И даже хуже. В том варианте что сейчас объем несброшенных сообщений определяется только скоростью записи на диск. А вот в варианте с таймером при зависании мы потеряем весь недосброшенный лог, даже если нагрузка низкая и никаких проблем писать в лог мгновенно нет.
AVK>>Как может зависнуть поток сброса на диск при ошибках в прикладном коде? GZ>ХЗ. Но факт пока остается фактом(см. выше).
Боюсь, при подобных проблемах лог управляемого кода вряд ли поможет. Налицо умирание рантайма, и средства для отлова подобного совсем другие.
GZ>Если мы достигли максимума очереди, то если это происходит часто, то лучше перенастроить увеличить размер очереди.
Нет, то лучше просигнализировать о проблемах админу чтобы он урезал аппетиты, или докупил быстрый диск.
GZ> Если не часто, то почему бы не пожертвовать одним рабочим потоком.
Я не понимаю как жертвование еще одним потоком может помочь.
AVK>>А так, чтобы надо было бороться за скорость записи критических ошибок в лог — это, ИМХО, какая то весьма экзотическая ситуация. GZ>Детерменированность записи ошибки. Я посмотрел твой код, ты сделал очередь которая сбрасывает по одной ошибке.
Неверно. Очередь у меня сбрасывается мгновенно. Переполнение ее возможно только если скорость поступления событий будет выше скорости из сброса.
GZ>В моем файловом логгере — сообщения буфферизуются. Это увеличивает пропускную способность при трассировке, но существует вероятность что наиболее важная информация, а именно ошибки, не успеют сохраниться до краха/остановки в файл существуют.
В моем варианте, как я уже писал, вероятность такого существенно меньше, потому что нет никакого фиксированного буфера и фиксированного таймаута и время между генерацией события и сбросом его на диск при умеренном темпе заполнения лога сопоставимо с временем записи единичного события на диск.
AVK>>Ужос, честно говоря. Слишком сложно. GZ>А ты что предлагаешь?
Здравствуйте, AndrewVK, Вы писали:
AVK>Очевидно, что акценты в немалой степени пределяются опытом. На аднный момент мне не очень интересна архитектура сильно масштабируемых систем под большие нагрузки. Соотв. и сервер создавался прежде всего под задачи большой сложности, но относительно невысокой нагрузки.
Дык и я не занимаюсь серверами реального времени. Тут нагрузка как раз в сложности. Чем больше подсистем и сущностей, тем толще трассировочный лог. Выхлоп лога в режиме полной трассировки значительно превосходит выхлоп полезной информации.
AVK>Тут понимаешь какое дело. С одной стороны хочется конечно что то такое придумать более менее универсальное. Но с доугой стороны те же высокопроизводительные решения ломают или усложняют архитектуру в угоду максимальной эффективности. Ну а дальше начинается баланс приоритетов.
Да получается другая вещь. Ты ограничил программиста своей очередью. В то же время — функциональность лога зависит от его типа. Никто не будет трассироваться через мыло. Для мыла, очередь вообще должна быть небольшой. Если у нас более 10/100 сообщений в секунду, то мы рискуем получить антиспаммерскую функциональность. Когда почтарики не будут успевать пересылать спам. И для него не важно точное количество ошибок. Важно больше их наличие. Он не предназначен для трассировки. А вот файловый кэш — предназначен. Для него должна быть большая очередь. И проглоченные месаги трассировки приводят к ситуации когда лучше бы лога вообще не было.
AVK>А если мы сбрасываем скопом, то получаем те же яйца, вид в профиль. И даже хуже. В том варианте что сейчас объем несброшенных сообщений определяется только скоростью записи на диск. А вот в варианте с таймером при зависании мы потеряем весь недосброшенный лог, даже если нагрузка низкая и никаких проблем писать в лог мгновенно нет.
Как это обходится — я описал.
GZ>>Если мы достигли максимума очереди, то если это происходит часто, то лучше перенастроить увеличить размер очереди. AVK>Нет, то лучше просигнализировать о проблемах админу чтобы он урезал аппетиты, или докупил быстрый диск.
А также быстрый mail сервер. Кстати, лог у меня блокируется только на момент записи. При нескольких мег(а иногда и гиг) трассировки на стандартном логе, разобраться в нем нельзя. Убить файл тоже нельзя — заблокирован. Опять приходим к неприятной перегрузке.
GZ>> Если не часто, то почему бы не пожертвовать одним рабочим потоком. AVK>Я не понимаю как жертвование еще одним потоком может помочь.
Ошибочным потоком. Тот поток который вызывает error, он же и сбрасывает на диск без асинхронности.
AVK>Неверно. Очередь у меня сбрасывается мгновенно. Переполнение ее возможно только если скорость поступления событий будет выше скорости из сброса.
+1. Опять думаем mail сервер.
AVK>>>Ужос, честно говоря. Слишком сложно. GZ>>А ты что предлагаешь?
AVK>Что то вроде такого: AVK>
AVK>Пишем все сообщения с приоритетом High и выше и все сообщения подсистемы SubsystemA с приоритетом выше Low.
В принципе прекрасно, но что это ошибка или информация — надо различать. У них разные форматы записи.
Здравствуйте, GlebZ, Вы писали:
AVK>>Очевидно, что акценты в немалой степени пределяются опытом. На аднный момент мне не очень интересна архитектура сильно масштабируемых систем под большие нагрузки. Соотв. и сервер создавался прежде всего под задачи большой сложности, но относительно невысокой нагрузки. GZ>Дык и я не занимаюсь серверами реального времени.
Сервера реального времени под .NET?
AVK>>Тут понимаешь какое дело. С одной стороны хочется конечно что то такое придумать более менее универсальное. Но с доугой стороны те же высокопроизводительные решения ломают или усложняют архитектуру в угоду максимальной эффективности. Ну а дальше начинается баланс приоритетов. GZ>Да получается другая вещь. Ты ограничил программиста своей очередью.
Я много чем ограничил программиста. Не ограничивать ничем нельзя — за удобство и фукнционал обычно как раз ограничениями платить приходится.
GZ> В то же время — функциональность лога зависит от его типа. Никто не будет трассироваться через мыло. Для мыла, очередь вообще должна быть небольшой.
Это вопросы администрирования.
GZ> Если у нас более 10/100 сообщений в секунду, то мы рискуем получить антиспаммерскую функциональность. Когда почтарики не будут успевать пересылать спам. И для него не важно точное количество ошибок. Важно больше их наличие. Он не предназначен для трассировки.
Ну так не используй, делов то.
GZ> А вот файловый кэш — предназначен. Для него должна быть большая очередь.
Зачем там большая очередь? Очередь в моем коде используется исключительно потому, что в некоторые моменты времени темп поступления сообщений может превышать возможности дисков. Не более того.
GZ>Как это обходится — я описал.
Извини, но из твоего сумбурного описания я мало что понял. Кидает тебя из стороны в сторону — то запись синхронная, то большой буфер, то лог, в который записать не успеваем.
AVK>>Нет, то лучше просигнализировать о проблемах админу чтобы он урезал аппетиты, или докупил быстрый диск. GZ>А также быстрый mail сервер.
Я тебе уже сказал — для мейлеров в качестве "буфера" используют БД. И это специфичная именно для мейлера функциональность. Я вообще не уверен, что мейлер должен изображать из себя лог — он очень сильно по своей логике от лога отличается.
GZ> Кстати, лог у меня блокируется только на момент записи
У меня тоже.
GZ>. При нескольких мег(а иногда и гиг) трассировки на стандартном логе, разобраться в нем нельзя.
При чем тут стандартный лог?
AVK>>Я не понимаю как жертвование еще одним потоком может помочь. GZ>Ошибочным потоком. Тот поток который вызывает error, он же и сбрасывает на диск без асинхронности.
Что то ты путаешься в показаниях. Либо отдельный поток, либо без асинхронности, но никак не одновременно.
AVK>>Неверно. Очередь у меня сбрасывается мгновенно. Переполнение ее возможно только если скорость поступления событий будет выше скорости из сброса. GZ>+1. Опять думаем mail сервер.
Такое ощущеия, что ты меня не слушаешь. Если ты отсылку письма делаешь прямо в потоке логгера — ты сам себе злобный буратина. Логгер тут не при чем.
AVK>>Что то вроде такого: AVK>>
AVK>>Пишем все сообщения с приоритетом High и выше и все сообщения подсистемы SubsystemA с приоритетом выше Low. GZ>В принципе прекрасно, но что это ошибка или информация — надо различать.
AVK>>>Пишем все сообщения с приоритетом High и выше и все сообщения подсистемы SubsystemA с приоритетом выше Low. GZ>>В принципе прекрасно, но что это ошибка или информация — надо различать.
AVK>
Здравствуйте, AndrewVK, Вы писали:
AVK>>>Очевидно, что акценты в немалой степени пределяются опытом. На аднный момент мне не очень интересна архитектура сильно масштабируемых систем под большие нагрузки. Соотв. и сервер создавался прежде всего под задачи большой сложности, но относительно невысокой нагрузки. GZ>>Дык и я не занимаюсь серверами реального времени. AVK>Сервера реального времени под .NET?
И даже не под net. А вот масштабируемыми приходится.
Ладно, сейчас уже нет времени, уезжаю:
Сделал тест.
Testing Buffered:
Тест Writing:12 ms
RunningThread=602000 cycles; 50166 cycles in ms
Testing NotBuffered:
Тест Writing:2030 ms
RunningThread=96107000 cycles; 47343 cycles in ms
Results:
Buffered time is 0,591133004926108 %
UnBuffered cycles is 94,3726826934577 %
Фактически получается что в 200 раз быстрее работает если не открывать каждый раз. Это называется на порядки, и железом не лечится. Время выполнения параллельного потока практически одинаковое.
Текст теста:
using System;
using System.Text;
using System.Threading;
using System.IO;
using System.Diagnostics;
namespace TestWrite
{
class Program
{
string toWrite;
long timeWrite = 0;
long timeBufferedWrite;
long timeNotBufferedWrite;
long cyclesInMs;
long cyclesBuffered;
long cyclesUnbuffered;
const int writeCyclesCount = 1000;
public ManualResetEvent evStart = new ManualResetEvent(false);
public ManualResetEvent evEnd = new ManualResetEvent(false);
public void TestWriting(object o)
{
bool isBuffered = (bool)o;
evStart.WaitOne();
Stopwatch watch = Stopwatch.StartNew();
if (isBuffered)
Buffered();
else
NotBuffered();
watch.Stop();
timeWrite = watch.ElapsedMilliseconds;
evEnd.Set();
Console.WriteLine(String.Format("Тест Writing:{0} ms", watch.ElapsedMilliseconds));
}
private void Buffered()
{
using (StreamWriter writer = new StreamWriter(@"c:\test.log", true))
{
for (int i = 0; i < writeCyclesCount; i++)
{
writer.WriteLine(toWrite);
}
}
}
private void NotBuffered()
{
for (int i = 0; i < writeCyclesCount; i++)
{
using (StreamWriter writer = new StreamWriter(@"c:\test.log", true))
{
writer.WriteLine(toWrite);
}
}
}
public void RunningThread(object state)
{
evStart.WaitOne();
long j = 0;
while (j < long.MaxValue)
{
j++;
if (j % 1000 == 0)
if (evEnd.WaitOne(0, false))
break;
}
Console.WriteLine(String.Format("RunningThread={0} cycles; {1} cycles in ms", j, j / timeWrite));
cyclesInMs = j/timeWrite;
}
private void PrepareString()
{
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 50; i++)
sb.Append("0123456789");
toWrite = sb.ToString();
}
public void Test()
{
PrepareString();
Console.WriteLine("Testing Buffered:");
Thread thread1 = new Thread(RunningThread);
Thread thread2 = new Thread(TestWriting);
thread2.Start(true);
thread1.Start();
evStart.Set();
thread1.Join();
thread2.Join();
cyclesBuffered=cyclesInMs;
timeBufferedWrite=timeWrite;
evStart.Reset();
evEnd.Reset();
Console.WriteLine("Testing NotBuffered:");
thread1 = new Thread(RunningThread);
thread2 = new Thread(TestWriting);
thread2.Start(false);
thread1.Start();
evStart.Set();
thread1.Join();
thread2.Join();
cyclesUnbuffered=cyclesInMs;
timeNotBufferedWrite=timeWrite;
Console.WriteLine("Results:");
Console.WriteLine("Buffered time is {0} %", (double)timeBufferedWrite*100/timeNotBufferedWrite);
Console.WriteLine("UnBuffered cycles is {0} %", (double)cyclesUnbuffered * 100 / cyclesBuffered);
}
static void Main(string[] args)
{
new Program().Test();
}
}
}
Здравствуйте, GlebZ, Вы писали:
GZ>Ладно, сейчас уже нет времени, уезжаю: GZ>Сделал тест.
GZ>
GZ>Testing Buffered:
GZ>Тест Writing:12 ms
GZ>RunningThread=602000 cycles; 50166 cycles in ms
GZ>Testing NotBuffered:
GZ>Тест Writing:2030 ms
GZ>RunningThread=96107000 cycles; 47343 cycles in ms
GZ>Results:
GZ>Buffered time is 0,591133004926108 %
GZ>UnBuffered cycles is 94,3726826934577 %
GZ>Фактически получается что в 200 раз быстрее работает если не открывать каждый раз. Это называется на порядки, и железом не лечится. Время выполнения параллельного потока практически одинаковое.
Тест был запущен под Windows 2003 сервер, на двухядерном проце.
GZ>Кое что допишу по тесту после.
И что оно показало:
1. При буферизованной записи 1 мБ информации результат 12 ms. Для подавляющего кол-ва приложений/запросов — это пренебрежимо небольшая величина, и ею можно пренебречь и вообще пользоваться синхронным вызовом сброса.
2. Выполнение не тормозится в обоих случаях в случае многопроцессорности. В случае буферизации есть даже выигрыш, однако пренебрежительно небольшой. В случае же однопроцессорности (или можно говорить о нехватке процессоров относительно потоков) выигрыш больше.(см внизу).
3. Определяющей является именно латентность при открытии закрытии файла.
4. Фактически визуально видно что при синхронном логгировании выполнение тормозится в 2-3 раза. Иногда даже на порядки. А посему становится вероятным что переполнение очереди достаточно вероятно, так как производительность основного выполнения значительно выше. Я буферизованную асинхронку не от хорошей жизни в свое время написал.
Это было для двухядерного проца. Для домашнего одноядерного P4 без всякого гипертрейдинга с Windows XP:
Testing Buffered:
Тест Writing:5 ms
RunningThread=16000 cycles; 3200 cycles in ms
Testing NotBuffered:
Тест Writing:109 ms
RunningThread=16000 cycles; 146 cycles in ms
Results:
Buffered time is 4,58715596330275 %
UnBuffered cycles is 4,5625 %
Что касается твоей очереди. Я не думаю что это хорошая идея делать асинхронную очередь как единый механизм для всех логгеров. Все таки я бы ее сделал именно как helper класс, а выбор использовать такую, или делать другую — дело разработчика. Например, я бы при наличии своего логгера не стал бы использовать именно твою асинхронность, а это приводит к отказу от твоего логгера как такового. В принципе и ты согласен что логгер по крайней мере для mail — должен кардинально различаться. Я бы сказал больше, логгер предназначенный для трассировки, и просто для показа ошибок должны различаться, и различаться в том числе по функциональности.
AVK>Что то ты путаешься в показаниях. Либо отдельный поток, либо без асинхронности, но никак не одновременно.
Поясню, если ты не смотрел сырцы файлового которые я выложил.
1. При сохранении сообщения info — оно кладется в очередь и ожидает пока таймер не сбросит очередь в файл. Если очередь заполнена, то она расширяется в два раза. Если достигнут максимум, то оно сбрасывается в текущем потоке без таймера. Учитывая что потери буферизованного сохранения малы, и это делается только при максимуме очереди, ничего криминального нет.
2. При сохранении ошибки, сообщение добавляется в очередь, и этот же поток сохраняет очередь в хранилище. С учетом того что поток генерирующий ошибки не жалко, а время сохранения буфера достаточно мало, ничего криминального в этом, опять ж,е нет.
3. Если пиковые нагрузки прошли, то через некоторое время очередь уменьшается в два раза. Пока не достигнет минимума.
4. Если файл по каким-то причинам недоступен, то логгер объявляется мертвым и перестает принимать сообщения до тех пор, пока процедура проверки не увидит что логгер восстановился. Пока логгер мертвый, сообщения не принимаются, чтобы не нагружать ресурсы сервака ошибками. Процедура проверки жив-нежив, асинхронная. И период проверки автоматически увеличивается.
При всей гибкости, сырец QueueLogger.cs — достаточно небольшой по размеру, и достаточно прост. И не зависит от типа сохранения. Это буфферизованная очередь предназначенная в большей степени для работы трассировки. Ее с таким же успехом можно использовать для базы данных. DirLogger.cs — это уже работа с файлами при использовании данной очереди. Провязаны они через наследования (делались давно и первая целевая платформа была Net 1.1).
Здравствуйте, migel, Вы писали:
M>хъ M>хм а что, были сомнения в тормознутости операций открытия закрытия файлов
Вопрос не в тормознутости а в ее количестве и общем влиянии на систему. Если влияние 2-3 раза, или даже 5-6 — это ничего. Если на порядки — значит что-то надо делать ибо железом такие обломы не исправишь. Чем больше будет кол-во сообщений(а по сути сложность системы), тем более будет влияния на общее функционирование лога.
Здравствуйте, GlebZ, Вы писали:
GZ>Что касается твоей очереди. Я не думаю что это хорошая идея делать асинхронную очередь как единый механизм для всех логгеров. Все таки я бы ее сделал именно как helper класс, а выбор использовать такую, или делать другую — дело разработчика. Например, я бы при наличии своего логгера не стал бы использовать именно твою асинхронность, а это приводит к отказу от твоего логгера как такового. В принципе и ты согласен что логгер по крайней мере для mail — должен кардинально различаться.
Ты, кажется, не понимаешь смысл этой асинхронности. Она предназначена для того, чтобы убрать из основного кода задержку на логгирование по минимуму. Для решения задачи медленной работы саого лога оно не присбособленно, эту задачу надо решать отдельно, причем в каждом логе по своему. Нужна тебе буферизация при выводе в файл — делай ее в файловом логе, нужна запись в БД для мейлера — делай в мейлере. А то, что есть в логгере экономит время основному потоку на дспетчеризации, отсечении плохих логов, и, в перспективе, на выполнении предиката фильтра для каждого лога.
GZ> Я бы сказал больше, логгер предназначенный для трассировки, и просто для показа ошибок должны различаться, и различаться в том числе по функциональности.
Для трассировки, ИМХО, хватит штатных механизмов дотнета.
GZ>1. При сохранении сообщения info — оно кладется в очередь и ожидает пока таймер не сбросит очередь в файл.
Значит асинхронно.
GZ> Если очередь заполнена, то она расширяется в два раза. Если достигнут максимум, то оно сбрасывается в текущем потоке без таймера.
Тормозя при этом основной поток?
GZ> Учитывая что потери буферизованного сохранения малы, и это делается только при максимуме очереди, ничего криминального нет.
Не, либо оно не делается либо делается в смертельной ситуации, и тогда твоя синхронность просто не нужна, либо оно делается в процессе работы, тогда это криминал.
... << RSDN@Home 1.2.0 alpha rev. 725 on Windows Vista 6.0.6000.0>>
Здравствуйте, AndrewVK, Вы писали:
AVK>Ты, кажется, не понимаешь смысл этой асинхронности. Она предназначена для того, чтобы убрать из основного кода задержку на логгирование по минимуму. Для решения задачи медленной работы саого лога оно не присбособленно, эту задачу надо решать отдельно, причем в каждом логе по своему. Нужна тебе буферизация при выводе в файл — делай ее в файловом логе, нужна запись в БД для мейлера — делай в мейлере. А то, что есть в логгере экономит время основному потоку на дспетчеризации, отсечении плохих логов, и, в перспективе, на выполнении предиката фильтра для каждого лога.
Это то понятно. В принципе я понял смысл, ничего криминального нет. Возможно ты прав, особенно в последнем предложении. Единственное что — отсечение плохих логов не стоит делать на каждом сообщении. Лог вполне может писать в какой то потерявшийся web сервис, или потерявшейся коннект к БД. В результате в лучшем случае накачаешь никому не нужных данных в другие логи, в худшем — очередь на каждом сообщении будет сидеть на чьем-то таймауте. За это время могут и пару сотен мегабайт сообщений накачать в память.
AVK>Для трассировки, ИМХО, хватит штатных механизмов дотнета.
Слишком неудобно. Собственно с этого и начал.
GZ>>1. При сохранении сообщения info — оно кладется в очередь и ожидает пока таймер не сбросит очередь в файл. AVK>Значит асинхронно.
Да. Основной режим работы асинхронный.
GZ>> Если очередь заполнена, то она расширяется в два раза. Если достигнут максимум, то оно сбрасывается в текущем потоке без таймера. AVK>Тормозя при этом основной поток? GZ>> Учитывая что потери буферизованного сохранения малы, и это делается только при максимуме очереди, ничего криминального нет. AVK>Не, либо оно не делается либо делается в смертельной ситуации, и тогда твоя синхронность просто не нужна, либо оно делается в процессе работы, тогда это криминал.
Ничего криминального нет. Криминал будет если мы под задачи логгера возьмем излишнюю память требуемые основной логике. Требования к памяти лога в силу его текстуальности выше чем полезный данные сервака. Поэтому очередь ограничена. При некотором превышении — жертвуем 8-13 ms от одного из сотен потоков. Это фигня. Практически латентность вызова БД.
Здравствуйте, GlebZ, Вы писали:
GZ>Единственное что — отсечение плохих логов не стоит делать на каждом сообщении.
Это обсуждаемо. Я уже писал, что с ходу не придумал какой то правильной политики, поэтому сделал самую прпостую. Просто задел на будущее.
AVK>>Не, либо оно не делается либо делается в смертельной ситуации, и тогда твоя синхронность просто не нужна, либо оно делается в процессе работы, тогда это криминал. GZ>Ничего криминального нет.
Не знаю Мне кажется, что программа должна прежде всего выполнять свою основную работу, а уж потом все остальное. Я вообще не сторонник работы на одном крыле — лучше сразу выявить проблемы и потребовать их устранения, нежели ковылять кое как, а потом расхлебывать последствия.
... << RSDN@Home 1.2.0 alpha rev. 725 on Windows Vista 6.0.6000.0>>