Изменение log4net FileAppender во время ведения журнала

Мы пытаемся настроить серверный процесс так, чтобы каждый раз, когда он получает запрос, он регистрировал этот запрос в НОВОЕ имя файла.

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

То, что, казалось, работало, это:

В первый раз, когда мы получаем запрос, мы настраиваем FileAppender «PerRequest» следующим образом:

fileAppender = new FileAppender();
log.InfoFormat("Initializing log4net per request logging");
log4net.Layout.PatternLayout layout = new Layout.PatternLayout("%date %property{processid} %property{username} %-5level %logger - %message%newline");
fileAppender.Layout = layout;
layout.ActivateOptions();
fileAppender.AppendToFile = true;
fileAppender.Name = "PerRunLogger";
fileAppender.File = makeNewRequestLogName(); // Returns a unique filename (uses a Guid)
log.InfoFormat("Configured PerRequest logger to log to '{0}'", fileAppender.File);
fileAppender.ActivateOptions();
log4net.Config.BasicConfigurator.Configure(fileAppender);

Затем каждый раз, когда мы получаем новый запрос, мы делаем следующее:

fileAppender.File = makeNewRequestLogName();
log.InfoFormat("Configured PerRequest logger to log to '{0}'", fileAppender.File);
fileAppender.ActivateOptions();

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

Это работало довольно хорошо... Но при большой нагрузке мы начали замечать, что файл журнала «PerRequest» часто содержит огромные куски «отсутствующих» строк журнала. например что-то вроде этого:

2009-09-23 19:17:17,133 4332 hollingp DEBUG PostProcessInfrastructure.PostProcessRunner - Started post processing
* normal log lines here, omitted for brevity *
2009-09-23 19:17:36,414 4332 hollingp DEBUG PluginRegistry.PostProcessVersions.PostProcessPluginCacheVersion - About to run pub_GetPostProcessingVersion stored proc

*Normally lots of log lines here, but every now and then, NOTHING *

2009-09-23 19:17:37,742 4332 hollingp DEBUG PostProcessInfrastructure.PostProcessRunner - Finished post processing

Нет хорошего объяснения тому, что мы видим в файле журнала — нет пути кода (даже если выдается исключение), который объяснил бы «отсутствующие» строки журнала — что-то (на самом деле довольно много вещей ) должен был быть зарегистрирован в этом потоке между строкой в ​​19:17:36 и строкой в ​​19:17:37.

По общему признанию, вся эта техника немного хитрая, но мы не могли придумать другого способа сделать это.

Итак, первый вопрос: есть ли лучший способ достичь того, чего мы хотим?

Второй вопрос: кто-нибудь может объяснить, что может происходить? Подозрение в том, что необходимо выполнить некоторую безопасность/блокировку потоков, но где? Что нужно заблокировать, если это так?

Нет риска того, что другой процесс попытается войти в тот же файл, потому что, как указано в комментарии в коде, мы выделяем имя файла журнала с помощью GUID — нет никаких шансов, что другой процесс попытается войти в тот же файл. тот же файл... а другой нить? Мы не можем этого исключить.


person Paul Hollingsworth    schedule 24.09.2009    source источник


Ответы (2)


Из часто задаваемых вопросов по log4net:

Многие разработчики сталкиваются с проблемой различения выходных данных журнала, происходящих из одного и того же класса, но разных клиентских запросов. Они придумывают оригинальные механизмы для разнесения лога по разным файлам. В большинстве случаев это не правильный подход.

Проще использовать свойство контекста или стек (ThreadContext). Как правило, ThreadContext.Properties[ID] = XXX конкретная информация о клиенте, такая как имя хоста клиента, идентификатор или любая другая отличительная информация, когда начинается обработка запроса клиента. После этого вывод журнала будет автоматически включать данные контекста, чтобы вы могли различать журналы из разных клиентских запросов, даже если они выводятся в один и тот же файл.

Дополнительные сведения см. в классах ThreadContext и PatternLayout.

person Zack Elan    schedule 25.09.2009
comment
Да, я думаю, это лучший ответ ... но какое-то дерьмо, что они не предоставляют какое-то добавление мультиплексирования, которое может переключаться на разные имена файлов в зависимости от свойств контекста. поиск в массивах лог-файлов, попытка собрать воедино все строки, связанные с одним конкретным запросом, — это кошмар службы поддержки. В долгосрочной перспективе мы собираемся создать сервер журналов, который разделит все для нас. - person Paul Hollingsworth; 25.09.2009
comment
Верно, но это работает в обе стороны — если вы когда-нибудь столкнетесь с проблемой, основной причиной которой является несколько одновременных сеансов, взаимодействующих каким-то образом, этот объединенный журнал будет бесценным. И вместо того, чтобы писать полноценный собственный сервер журналов, вы могли бы довольно тривиально написать инструмент командной строки для разделения файла журнала. Затем, когда у вас есть журнал, который вы хотите проанализировать, просто поместите его в .exe, и он выдаст отдельные журналы. - person Zack Elan; 25.09.2009
comment
Однако этот инструмент командной строки для разделения журналов может занять долгое время. - person Paul Hollingsworth; 25.09.2009
comment
long = 2 минуты для файла размером полгигабайта на старой машине. - person graffic; 13.10.2009

Итак, первый вопрос: есть ли лучший способ достичь того, чего мы хотим?

Должен ли это быть отдельный файл для каждого запроса?

Если нет, то как насчет создания собственного пользовательского макета шаблона и включения сведений о запросе в шаблон журнала? Пример Google нашел.

Если это так, как насчет расширения RollingFileAppender и изменения новое условие файла, чтобы вместо того, чтобы быть связанным с размером файла (или чем-то еще), оно было основано на запросе?

Я полагаю, вы уже экспериментировали с LockingModel?

person si618    schedule 24.09.2009
comment
Спасибо - постараюсь выяснить, есть ли способ взломать RollingFileAppender таким образом. - person Paul Hollingsworth; 25.09.2009